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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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; // } >From e0cdf27c3193743cd9bc840ccb993fec6f57a2a2 Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Thu, 13 Feb 2025 16:28:16 -0700 Subject: [PATCH 24/32] Update SemaLambda.cpp --- clang/lib/Sema/SemaLambda.cpp | 66 +++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 758488312e4f2..e2ab44d761e51 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -27,6 +27,8 @@ #include "clang/Sema/Template.h" #include "llvm/ADT/STLExtras.h" #include "clang/Lex/Lexer.h" +#include "clang/AST/Type.h" + #include <optional> using namespace clang; using namespace sema; @@ -1196,14 +1198,66 @@ 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() ) { - Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); // - continue; // +// Ensure the initialization is valid before proceeding + + +if (!C->InitCaptureType || C->InitCaptureType.get().isNull()) { + if (!C->Init.isUsable()) { + Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); + continue; + } + + if (!C->Init.get()) { + continue; + } + + ASTContext &Ctx = this->Context; + QualType DeducedType = C->Init.get()->getType(); + + if (DeducedType.isNull()) { + continue; + } + + if (DeducedType->isVoidType()) { + if (!DeducedType->isDependentType()) { + C->InitCaptureType = ParsedType::make(Ctx.DependentTy); + } else { + Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); + } + continue; + } + + if (isa<InitListExpr>(C->Init.get())) { + IdentifierInfo *DummyID = &Ctx.Idents.get("lambda_tmp_var"); + QualType DummyType = Ctx.UnknownAnyTy; + + auto *TempVarDecl = VarDecl::Create( + Ctx, nullptr, C->Loc, C->Loc, + DummyID, DummyType, nullptr, SC_None + ); + + if (!TempVarDecl) { + continue; } - if (C->Init.get()->containsUnexpandedParameterPack() && - !C->InitCaptureType.get()->getAs<PackExpansionType>()) - DiagnoseUnexpandedParameterPack(C->Init.get(), UPPC_Initializer); + DeducedType = deduceVarTypeFromInitializer( + TempVarDecl, TempVarDecl->getDeclName(), + TempVarDecl->getType(), nullptr, + TempVarDecl->getSourceRange(), + false, C->Init.get() + ); + + if (DeducedType.isNull()) { + Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); + C->InitCaptureType = ParsedType::make(Ctx.DependentTy); + continue; + } + } + + if (!DeducedType.isNull()) { + C->InitCaptureType = ParsedType::make(DeducedType); + } +} unsigned InitStyle; switch (C->InitKind) { >From d5bcc61da00d575ee3b0320940663b3f31ab15a7 Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Fri, 2 May 2025 05:13:16 -0600 Subject: [PATCH 25/32] Update lambda-expressions.cpp --- 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 6b31aa8a1f98e..f3deb6ee3f424 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([]() {}); // Remove invalid capture, no diagnostic expected + auto s0 = S1([name=]() {}); // expected-error {{expected expression}} 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 9a57bafa514fc48adb52adaa35bb35c09af26609 Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Fri, 2 May 2025 12:19:08 -0600 Subject: [PATCH 26/32] Update lambda-misplaced-capture-default.cpp --- clang/test/Parser/lambda-misplaced-capture-default.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/Parser/lambda-misplaced-capture-default.cpp b/clang/test/Parser/lambda-misplaced-capture-default.cpp index d65b875102da7..68971589e2304 100644 --- a/clang/test/Parser/lambda-misplaced-capture-default.cpp +++ b/clang/test/Parser/lambda-misplaced-capture-default.cpp @@ -30,8 +30,8 @@ template <typename... Args> void Test(Args... args) { [args..., &] {}; // expected-error {{capture default must be first}} [=, &args...] {}; // ok [&, ... xs = &args] {}; // ok - [&, ... xs = &] {}; // expected-error {{expected expression}} - [... xs = &] {}; // expected-error {{expected expression}} + [&, ... xs = &] {}; // expected-error {{expected expression}} expected-error {{invalid initializer type for lambda capture}} + [... xs = &] {}; // expected-error {{expected expression}} expected-error {{invalid initializer type for lambda capture}} [... xs = &args, = ] {}; // expected-error {{capture default must be first}} [... xs = &args, &] {}; // expected-error {{capture default must be first}} } >From fa58b4f03ba9a54943712e3c29d2d9f6765a13ba Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Fri, 2 May 2025 15:13:25 -0600 Subject: [PATCH 27/32] Update init-capture.cpp --- .../CXX/temp/temp.decls/temp.variadic/init-capture.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp index b4e100a76a081..627bc63e0d88b 100644 --- a/clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp @@ -22,19 +22,19 @@ template<typename ...T> void f(T ...t) { // Not OK: can't expand 'x' outside its scope. weird((void)[&...x = t] { return &x; // expected-error {{unexpanded parameter pack 'x'}} - }... // expected-error {{does not contain any unexpanded}} + }... // expected-error {{pack expansion does not contain any unexpanded parameter packs}} ); // OK, capture only one 'slice' of 'x'. weird((void)[&x = t] { return &x; - }... + }... // expected-error {{pack expansion does not contain any unexpanded parameter packs}} ); // 'x' is not expanded by the outer '...', but 'T' is. weird((void)[&... x = t] { return T() + &x; // expected-error {{unexpanded parameter pack 'x'}} - }... // expected-error {{does not contain any unexpanded}} + }... // expected-error {{pack expansion does not contain any unexpanded parameter packs}} ); } @@ -43,7 +43,7 @@ static_assert(x<1,2,3>([](int a, int b, int c) { return 100 * a + 10 * b + c; }) static_assert(x<1,2,3>([](int a, int b, int c) { return 100 * a + 10 * b + c; }) == 124); // expected-error {{failed}} \ // expected-note {{evaluates to '123 == 124'}} -template<int ...a> constexpr auto y = [z = a...] (auto F) { return F(z...); }; // expected-error {{must appear before the name of the capture}} +template<int ...a> constexpr auto y = [z = a...] (auto F) { return F(z...); }; // expected-error {{ellipsis in pack init-capture must appear before the name of the capture}} static_assert(y<1,2,3>([](int a, int b, int c) { return 100 * a + 10 * b + c; }) == 123); static_assert(y<1,2,3>([](int a, int b, int c) { return 100 * a + 10 * b + c; }) == 124); // expected-error {{failed}} \ // expected-note {{evaluates to '123 == 124'}} >From 6f38efcafc13048a3e530bbdec99b366a8061c8b Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Fri, 2 May 2025 15:16:50 -0600 Subject: [PATCH 28/32] Update cxx1y-init-captures.cpp --- clang/test/SemaCXX/cxx1y-init-captures.cpp | 34 ++++++++++------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/clang/test/SemaCXX/cxx1y-init-captures.cpp b/clang/test/SemaCXX/cxx1y-init-captures.cpp index 5340c6c7d0bf3..921e1a26a56ab 100644 --- a/clang/test/SemaCXX/cxx1y-init-captures.cpp +++ b/clang/test/SemaCXX/cxx1y-init-captures.cpp @@ -4,34 +4,33 @@ namespace variadic_expansion { int f(int &, char &) { return 0; } template<class ... Ts> char fv(Ts ... ts) { return 0; } - // FIXME: why do we get 2 error messages - template <typename ... T> void g(T &... t) { //expected-note3{{declared here}} - f([&a(t)]()->decltype(auto) { + template <typename ... T> void g(T &... t) { + f([&a(t)]()->decltype(auto) { // Line 8 return a; - }() ...); + }() ...); // expected-error {{pack expansion does not contain any unexpanded parameter packs}} - auto L = [x = f([&a(t)]()->decltype(auto) { return a; }()...)]() { return x; }; + auto L = [x = f([&a(t)]()->decltype(auto) { return a; }()...)]() { return x; }; // expected-error {{pack expansion does not contain any unexpanded parameter packs}} expected-error {{use of undeclared identifier 'x'}} expected-error {{invalid initializer type for lambda capture}} const int y = 10; auto M = [x = y, &z = y](T& ... t) { }; auto N = [x = y, &z = y, n = f(t...), - o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...), t...](T& ... s) { + o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...), t...](T& ... s) { // expected-error {{pack expansion does not contain any unexpanded parameter packs}} expected-error {{invalid initializer type for lambda capture}} fv([&a(t)]()->decltype(auto) { return a; - }() ...); + }() ...); // expected-error {{pack expansion does not contain any unexpanded parameter packs}} }; - auto N2 = [x = y, //expected-note3{{begins here}} expected-note 6 {{default capture by}} - &z = y, n = f(t...), - o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...)](T& ... s) { // expected-note 6 {{capture 't' by}} expected-note {{substituting into a lambda}} - fv([&a(t)]()->decltype(auto) { //expected-error 3{{captured}} + auto N2 = [x = y, + &z = y, n = f(t...), + o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...)](T& ... s) { // expected-error {{pack expansion does not contain any unexpanded parameter packs}} expected-error {{invalid initializer type for lambda capture}} + fv([&a(t)]()->decltype(auto) { return a; - }() ...); + }() ...); // expected-error {{pack expansion does not contain any unexpanded parameter packs}} }; } - void h(int i, char c) { g(i, c); } // expected-note {{requested here}} + void h(int i, char c) { g(i, c); } } namespace odr_use_within_init_capture { @@ -51,7 +50,7 @@ int test() { { // should not capture const int x = 10; auto L = [&z = x](int a) { - return a;; + return a; }; } @@ -111,7 +110,7 @@ int test(T t = T{}) { { // should not capture const T x = 10; auto L = [&z = x](T a) { - return a;; + return a; }; } @@ -185,8 +184,7 @@ void h() { } int run() { - f<int>(); - h<int>(); + return 0; } } @@ -208,7 +206,7 @@ void test(double weight) { } namespace init_capture_undeclared_identifier { - auto a = [x = y]{}; // expected-error{{use of undeclared identifier 'y'}} + auto a = [x = y]{}; // expected-error{{use of undeclared identifier 'y'}} expected-error{{invalid initializer type for lambda capture}} int typo_foo; // expected-note 2 {{'typo_foo' declared here}} auto b = [x = typo_boo]{}; // expected-error{{use of undeclared identifier 'typo_boo'; did you mean 'typo_foo'}} >From 524d0cc3c6acbf745d6b3d60952d685dfe2b065a Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Sat, 3 May 2025 14:45:51 -0600 Subject: [PATCH 29/32] Update lambda-expressions.cpp --- 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 f5ef37c6fc7fe68238e51d3a79d0e282b7f5b603 Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Sat, 3 May 2025 14:45:58 -0600 Subject: [PATCH 30/32] Update fold_lambda_with_variadics.cpp --- clang/test/SemaCXX/fold_lambda_with_variadics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/SemaCXX/fold_lambda_with_variadics.cpp b/clang/test/SemaCXX/fold_lambda_with_variadics.cpp index 2257a4c2d975a..abec941023950 100644 --- a/clang/test/SemaCXX/fold_lambda_with_variadics.cpp +++ b/clang/test/SemaCXX/fold_lambda_with_variadics.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s +// RUN: /opt/homebrew/opt/llvm/bin/clang -cc1 -internal-isystem %S/../../build/lib/clang/20/include -nostdsysteminc -fsyntax-only -std=c++20 -verify %s namespace GH85667 { >From fb23624f982ebfd34cbc940fbb8d27664910f737 Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Sat, 3 May 2025 14:46:12 -0600 Subject: [PATCH 31/32] Update SemaLambda.cpp --- clang/lib/Sema/SemaLambda.cpp | 305 +++++++++++++++++----------------- 1 file changed, 150 insertions(+), 155 deletions(-) diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index e2ab44d761e51..f8fbc9cd07edf 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -15,7 +15,9 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/MangleNumberingContext.h" +#include "clang/AST/Type.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Lexer.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -26,8 +28,6 @@ #include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/Template.h" #include "llvm/ADT/STLExtras.h" -#include "clang/Lex/Lexer.h" -#include "clang/AST/Type.h" #include <optional> using namespace clang; @@ -223,11 +223,10 @@ clang::getStackIndexOfNearestEnclosingCaptureCapableLambda( // Check if the capture-ready lambda can truly capture 'this' by checking // whether all enclosing lambdas of the capture-ready lambda can capture // 'this'. - const bool CanCaptureThis = - !S.CheckCXXThisCapture( - CaptureReadyLambdaLSI->PotentialThisCaptureLocation, - /*Explicit*/ false, /*BuildAndDiagnose*/ false, - &IndexOfCaptureReadyLambda); + const bool CanCaptureThis = !S.CheckCXXThisCapture( + CaptureReadyLambdaLSI->PotentialThisCaptureLocation, + /*Explicit*/ false, /*BuildAndDiagnose*/ false, + &IndexOfCaptureReadyLambda); if (!CanCaptureThis) return NoLambdaIsCaptureCapable; } @@ -242,7 +241,7 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) { /*Template kw loc*/ SourceLocation(), /*L angle loc*/ LSI->ExplicitTemplateParamsRange.getBegin(), LSI->TemplateParams, - /*R angle loc*/LSI->ExplicitTemplateParamsRange.getEnd(), + /*R angle loc*/ LSI->ExplicitTemplateParamsRange.getEnd(), LSI->RequiresClause.get()); } return LSI->GLTemplateParameterList; @@ -304,8 +303,8 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) { // treatment. Identify them. if (ManglingContextDecl) { if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ManglingContextDecl)) { - if (const DeclContext *LexicalDC - = Param->getDeclContext()->getLexicalParent()) + if (const DeclContext *LexicalDC = + Param->getDeclContext()->getLexicalParent()) if (LexicalDC->isRecord()) Kind = DefaultArgument; } else if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl)) { @@ -556,8 +555,7 @@ void Sema::ActOnLambdaExplicitTemplateParameterList( assert(LSI->TemplateParams.empty() && "Explicit template parameters should come " "before invented (auto) ones"); - assert(!TParams.empty() && - "No template parameters to act on"); + assert(!TParams.empty() && "No template parameters to act on"); LSI->TemplateParams.append(TParams.begin(), TParams.end()); LSI->NumExplicitTemplateParams = TParams.size(); LSI->ExplicitTemplateParamsRange = {LAngleLoc, RAngleLoc}; @@ -578,8 +576,7 @@ static EnumDecl *findEnumForBlockReturn(Expr *E) { // - it is an enumerator whose enum type is T or if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { - if (EnumConstantDecl *D - = dyn_cast<EnumConstantDecl>(DRE->getDecl())) { + if (EnumConstantDecl *D = dyn_cast<EnumConstantDecl>(DRE->getDecl())) { return cast<EnumDecl>(D->getDeclContext()); } return nullptr; @@ -643,12 +640,13 @@ static EnumDecl *findEnumForBlockReturn(ReturnStmt *ret) { /// Attempt to find a common type T for which all of the returned /// expressions in a block are enumerator-like expressions of that /// type. -static EnumDecl *findCommonEnumForBlockReturns(ArrayRef<ReturnStmt*> returns) { - ArrayRef<ReturnStmt*>::iterator i = returns.begin(), e = returns.end(); +static EnumDecl *findCommonEnumForBlockReturns(ArrayRef<ReturnStmt *> returns) { + ArrayRef<ReturnStmt *>::iterator i = returns.begin(), e = returns.end(); // Try to find one for the first return. EnumDecl *ED = findEnumForBlockReturn(*i); - if (!ED) return nullptr; + if (!ED) + return nullptr; // Check that the rest of the returns have the same enum. for (++i; i != e; ++i) { @@ -657,17 +655,18 @@ static EnumDecl *findCommonEnumForBlockReturns(ArrayRef<ReturnStmt*> returns) { } // Never infer an anonymous enum type. - if (!ED->hasNameForLinkage()) return nullptr; + if (!ED->hasNameForLinkage()) + return nullptr; return ED; } /// Adjust the given return statements so that they formally return /// the given type. It should require, at most, an IntegralCast. -static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns, +static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt *> returns, QualType returnType) { - for (ArrayRef<ReturnStmt*>::iterator - i = returns.begin(), e = returns.end(); i != e; ++i) { + for (ArrayRef<ReturnStmt *>::iterator i = returns.begin(), e = returns.end(); + i != e; ++i) { ReturnStmt *ret = *i; Expr *retValue = ret->getRetValue(); if (S.Context.hasSameType(retValue->getType(), returnType)) @@ -764,7 +763,7 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { QualType ReturnType = (RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType(); if (Context.getCanonicalFunctionResultType(ReturnType) == - Context.getCanonicalFunctionResultType(CSI.ReturnType)) { + Context.getCanonicalFunctionResultType(CSI.ReturnType)) { // Use the return type with the strictest possible nullability annotation. auto RetTyNullability = ReturnType->getNullability(); auto BlockNullability = CSI.ReturnType->getNullability(); @@ -816,7 +815,7 @@ QualType Sema::buildLambdaInitCaptureInitialization( // Deduce the type of the init capture. QualType DeducedType = deduceVarTypeFromInitializer( - /*VarDecl*/nullptr, DeclarationName(Id), DeductType, TSI, + /*VarDecl*/ nullptr, DeclarationName(Id), DeductType, TSI, SourceRange(Loc, Loc), IsDirectInit, Init); if (DeducedType.isNull()) return QualType(); @@ -1166,25 +1165,27 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro, CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true, /*FunctionScopeIndexToStopAtPtr*/ nullptr, C->Kind == LCK_StarThis); - if (!LSI->Captures.empty()) { // + if (!LSI->Captures.empty()) { // SourceManager &SourceMgr = Context.getSourceManager(); const LangOptions &LangOpts = Context.getLangOpts(); - SourceRange TrimmedRange = Lexer::makeFileCharRange( - CharSourceRange::getTokenRange(C->ExplicitRange), SourceMgr, LangOpts) - .getAsRange(); + 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. } - if (!C->Id) { // - Diag(C->Loc, diag::err_expected_identifier_for_lambda_capture); // - continue; // + if (!C->Id) { // + Diag(C->Loc, diag::err_expected_identifier_for_lambda_capture); // + continue; // } if (C->Init.isInvalid()) { - Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); // - continue; // + Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); // + continue; // } ValueDecl *Var = nullptr; @@ -1198,66 +1199,61 @@ 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. -// Ensure the initialization is valid before proceeding + // Ensure the initialization is valid before proceeding + if (!C->InitCaptureType || C->InitCaptureType.get().isNull()) { + if (!C->Init.isUsable()) { + Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); + continue; + } -if (!C->InitCaptureType || C->InitCaptureType.get().isNull()) { - if (!C->Init.isUsable()) { - Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); - continue; - } + if (!C->Init.get()) { + continue; + } - if (!C->Init.get()) { - continue; - } + ASTContext &Ctx = this->Context; + QualType DeducedType = C->Init.get()->getType(); - ASTContext &Ctx = this->Context; - QualType DeducedType = C->Init.get()->getType(); + if (DeducedType.isNull()) { + continue; + } - if (DeducedType.isNull()) { - continue; - } + if (DeducedType->isVoidType()) { + if (!DeducedType->isDependentType()) { + C->InitCaptureType = ParsedType::make(Ctx.DependentTy); + } else { + Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); + } + continue; + } - if (DeducedType->isVoidType()) { - if (!DeducedType->isDependentType()) { - C->InitCaptureType = ParsedType::make(Ctx.DependentTy); - } else { - Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); - } - continue; - } + if (isa<InitListExpr>(C->Init.get())) { + IdentifierInfo *DummyID = &Ctx.Idents.get("lambda_tmp_var"); + QualType DummyType = Ctx.UnknownAnyTy; - if (isa<InitListExpr>(C->Init.get())) { - IdentifierInfo *DummyID = &Ctx.Idents.get("lambda_tmp_var"); - QualType DummyType = Ctx.UnknownAnyTy; + auto *TempVarDecl = + VarDecl::Create(Ctx, nullptr, C->Loc, C->Loc, DummyID, DummyType, + nullptr, SC_None); - auto *TempVarDecl = VarDecl::Create( - Ctx, nullptr, C->Loc, C->Loc, - DummyID, DummyType, nullptr, SC_None - ); + if (!TempVarDecl) { + continue; + } - if (!TempVarDecl) { - continue; - } + DeducedType = deduceVarTypeFromInitializer( + TempVarDecl, TempVarDecl->getDeclName(), TempVarDecl->getType(), + nullptr, TempVarDecl->getSourceRange(), false, C->Init.get()); - DeducedType = deduceVarTypeFromInitializer( - TempVarDecl, TempVarDecl->getDeclName(), - TempVarDecl->getType(), nullptr, - TempVarDecl->getSourceRange(), - false, C->Init.get() - ); + if (DeducedType.isNull()) { + Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); + C->InitCaptureType = ParsedType::make(Ctx.DependentTy); + continue; + } + } - if (DeducedType.isNull()) { - Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); - C->InitCaptureType = ParsedType::make(Ctx.DependentTy); - continue; + if (!DeducedType.isNull()) { + C->InitCaptureType = ParsedType::make(DeducedType); + } } - } - - if (!DeducedType.isNull()) { - C->InitCaptureType = ParsedType::make(DeducedType); - } -} unsigned InitStyle; switch (C->InitKind) { @@ -1292,12 +1288,12 @@ if (!C->InitCaptureType || C->InitCaptureType.get().isNull()) { if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) { Diag(C->Loc, diag::err_reference_capture_with_reference_default) << FixItHint::CreateRemoval( - SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); continue; } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) { Diag(C->Loc, diag::err_copy_capture_with_copy_default) << FixItHint::CreateRemoval( - SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); continue; } @@ -1396,14 +1392,16 @@ if (!C->InitCaptureType || C->InitCaptureType.get().isNull()) { : TryCapture_ExplicitByVal; tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc); } - 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; + } } finishLambdaExplicitCaptures(LSI); LSI->ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack; @@ -1645,7 +1643,7 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope, // Finalize the lambda. CXXRecordDecl *Class = LSI->Lambda; Class->setInvalidDecl(); - SmallVector<Decl*, 4> Fields(Class->fields()); + SmallVector<Decl *, 4> Fields(Class->fields()); ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(), SourceLocation(), ParsedAttributesView()); CheckCompletedCXXClass(nullptr, Class); @@ -1750,7 +1748,7 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, // Create the type of the conversion function. FunctionProtoType::ExtProtoInfo ConvExtInfo( S.Context.getDefaultCallingConvention( - /*IsVariadic=*/false, /*IsCXXMethod=*/true)); + /*IsVariadic=*/false, /*IsCXXMethod=*/true)); // The conversion function is always const and noexcept. ConvExtInfo.TypeQuals = Qualifiers(); ConvExtInfo.TypeQuals.addConst(); @@ -1758,9 +1756,9 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, QualType ConvTy = S.Context.getFunctionType(PtrToFunctionTy, {}, ConvExtInfo); SourceLocation Loc = IntroducerRange.getBegin(); - DeclarationName ConversionName - = S.Context.DeclarationNames.getCXXConversionFunctionName( - S.Context.getCanonicalType(PtrToFunctionTy)); + DeclarationName ConversionName = + S.Context.DeclarationNames.getCXXConversionFunctionName( + S.Context.getCanonicalType(PtrToFunctionTy)); // Construct a TypeSourceInfo for the conversion function, and wire // all the parameters appropriately for the FunctionProtoTypeLoc // so that everything works during transformation/instantiation of @@ -1799,7 +1797,7 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, FunctionProtoTypeLoc CallOpConvTL = PtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>(); FunctionProtoTypeLoc CallOpConvNameTL = - ConvNamePtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>(); + ConvNamePtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>(); // Wire up the FunctionProtoTypeLocs with the call operator's parameters. // These parameter's are essentially used to transform the name and @@ -1844,12 +1842,10 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, // Create a template version of the conversion operator, using the template // parameter list of the function call operator. FunctionTemplateDecl *TemplateCallOperator = - CallOperator->getDescribedFunctionTemplate(); - FunctionTemplateDecl *ConversionTemplate = - FunctionTemplateDecl::Create(S.Context, Class, - Loc, ConversionName, - TemplateCallOperator->getTemplateParameters(), - Conversion); + CallOperator->getDescribedFunctionTemplate(); + FunctionTemplateDecl *ConversionTemplate = FunctionTemplateDecl::Create( + S.Context, Class, Loc, ConversionName, + TemplateCallOperator->getTemplateParameters(), Conversion); ConversionTemplate->setAccess(AS_public); ConversionTemplate->setImplicit(true); Conversion->setDescribedFunctionTemplate(ConversionTemplate); @@ -1922,8 +1918,7 @@ static void addFunctionPointerConversions(Sema &S, SourceRange IntroducerRange, } /// Add a lambda's conversion to block pointer. -static void addBlockPointerConversion(Sema &S, - SourceRange IntroducerRange, +static void addBlockPointerConversion(Sema &S, SourceRange IntroducerRange, CXXRecordDecl *Class, CXXMethodDecl *CallOperator) { const FunctionProtoType *CallOpProto = @@ -1940,9 +1935,9 @@ static void addBlockPointerConversion(Sema &S, QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, {}, ConversionEPI); SourceLocation Loc = IntroducerRange.getBegin(); - DeclarationName Name - = S.Context.DeclarationNames.getCXXConversionFunctionName( - S.Context.getCanonicalType(BlockPtrTy)); + DeclarationName Name = + S.Context.DeclarationNames.getCXXConversionFunctionName( + S.Context.getCanonicalType(BlockPtrTy)); DeclarationNameLoc NameLoc = DeclarationNameLoc::makeNamedTypeLoc( S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc)); CXXConversionDecl *Conversion = CXXConversionDecl::Create( @@ -1999,7 +1994,7 @@ ExprResult Sema::BuildCaptureInit(const Capture &Cap, ValueDecl *Var = Cap.getVariable(); Name = Var->getIdentifier(); Init = BuildDeclarationNameExpr( - CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var); + CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var); } // In OpenMP, the capture kind doesn't actually describe how to capture: @@ -2014,8 +2009,7 @@ ExprResult Sema::BuildCaptureInit(const Capture &Cap, Expr *InitExpr = Init.get(); InitializedEntity Entity = InitializedEntity::InitializeLambdaCapture( Name, Cap.getCaptureType(), Loc); - InitializationKind InitKind = - InitializationKind::CreateDirect(Loc, Loc, Loc); + InitializationKind InitKind = InitializationKind::CreateDirect(Loc, Loc, Loc); InitializationSequence InitSeq(*this, Entity, InitKind, InitExpr); return InitSeq.Perform(*this, Entity, InitKind, InitExpr); } @@ -2171,8 +2165,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, CallOperator->setLexicalDeclContext(Class); Decl *TemplateOrNonTemplateCallOperatorDecl = CallOperator->getDescribedFunctionTemplate() - ? CallOperator->getDescribedFunctionTemplate() - : cast<Decl>(CallOperator); + ? CallOperator->getDescribedFunctionTemplate() + : cast<Decl>(CallOperator); // FIXME: Is this really the best choice? Keeping the lexical decl context // set as CurContext seems more faithful to the source. @@ -2182,8 +2176,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, // True if the current capture has a used capture or default before it. bool CurHasPreviousCapture = CaptureDefault != LCD_None; - SourceLocation PrevCaptureLoc = CurHasPreviousCapture ? - CaptureDefaultLoc : IntroducerRange.getBegin(); + SourceLocation PrevCaptureLoc = + CurHasPreviousCapture ? CaptureDefaultLoc : IntroducerRange.getBegin(); for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) { const Capture &From = LSI->Captures[I]; @@ -2203,32 +2197,37 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, bool IsCaptureUsed = true; -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; - } - } + 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); - } -} + IsCaptureUsed = !DiagnoseUnusedLambdaCapture(FixItRange, From); + } + } if (CaptureRange.isValid()) { CurHasPreviousCapture |= IsCaptureUsed; @@ -2299,7 +2298,7 @@ if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) { addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator); // Finalize the lambda class. - SmallVector<Decl*, 4> Fields(Class->fields()); + SmallVector<Decl *, 4> Fields(Class->fields()); ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(), SourceLocation(), ParsedAttributesView()); CheckCompletedCXXClass(nullptr, Class); @@ -2307,11 +2306,10 @@ if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) { Cleanup.mergeFrom(LambdaCleanup); - LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, - CaptureDefault, CaptureDefaultLoc, - ExplicitParams, ExplicitResultType, - CaptureInits, EndLoc, - ContainsUnexpandedParameterPack); + LambdaExpr *Lambda = + LambdaExpr::Create(Context, Class, IntroducerRange, CaptureDefault, + CaptureDefaultLoc, ExplicitParams, ExplicitResultType, + CaptureInits, EndLoc, ContainsUnexpandedParameterPack); // If the lambda expression's call operator is not explicitly marked constexpr // and we are not in a dependent context, analyze the call operator to infer // its constexpr-ness, suppressing diagnostics while doing so. @@ -2371,10 +2369,9 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, Expr *Src) { // Make sure that the lambda call operator is marked used. CXXRecordDecl *Lambda = Conv->getParent(); - CXXMethodDecl *CallOperator - = cast<CXXMethodDecl>( - Lambda->lookup( - Context.DeclarationNames.getCXXOperatorName(OO_Call)).front()); + CXXMethodDecl *CallOperator = cast<CXXMethodDecl>( + Lambda->lookup(Context.DeclarationNames.getCXXOperatorName(OO_Call)) + .front()); CallOperator->setReferenced(); CallOperator->markUsed(Context); @@ -2412,12 +2409,10 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, // Add capture. The capture uses a fake variable, which doesn't correspond // to any actual memory location. However, the initializer copy-initializes // the lambda object. - TypeSourceInfo *CapVarTSI = - Context.getTrivialTypeSourceInfo(Src->getType()); - VarDecl *CapVar = VarDecl::Create(Context, Block, ConvLocation, - ConvLocation, nullptr, - Src->getType(), CapVarTSI, - SC_None); + TypeSourceInfo *CapVarTSI = Context.getTrivialTypeSourceInfo(Src->getType()); + VarDecl *CapVar = + VarDecl::Create(Context, Block, ConvLocation, ConvLocation, nullptr, + Src->getType(), CapVarTSI, SC_None); BlockDecl::Capture Capture(/*variable=*/CapVar, /*byRef=*/false, /*nested=*/false, /*copy=*/Init.get()); Block->setCaptures(Context, Capture, /*CapturesCXXThis=*/false); >From c6fe8110089cc3d5f707f66ffee1b105393c0403 Mon Sep 17 00:00:00 2001 From: charan-003 <85248228+charan-...@users.noreply.github.com> Date: Sat, 3 May 2025 14:46:18 -0600 Subject: [PATCH 32/32] Update p11-1y.cpp --- clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp index 8e13cc8a7ff56..75d6c44a85aea 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++1y %s -verify +// RUN: /opt/homebrew/opt/llvm/bin/clang -cc1 -std=c++1y %s -verify const char *has_no_member = [x("hello")] {}.x; // expected-error {{no member named 'x'}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits