Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[FixIt] Improve Source Ranges and Fix-It Hints for Unused Lambda Captures #106445 #117953

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 48 commits into
base: main
Choose a base branch
Loading
from

Conversation

charan-003
Copy link

Key Changes
Enhancements in SemaLambda.cpp:

Updated the ExplicitCaptureRanges logic to compute more precise source ranges for unused lambda captures.

  • Fixed the handling of edge cases, including:
  • Trailing and leading whitespace in captures.
  • Redundant commas.
  • Mixed captures (e.g., [=, &a, b]).

Test Improvements in fixit-unused-lambda-capture.cpp:

  • Added new tests to validate correct Fix-It suggestions for edge cases:
  • Redundant commas like [a, , b].
  • Leading/trailing whitespace in capture lists.
  • Mixed capture styles (e.g., [=, &a]).
  • Single and multiple unused captures in different scenarios.

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.
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.
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Nov 28, 2024
@llvmbot
Copy link
Member

llvmbot commented Nov 28, 2024

@llvm/pr-subscribers-clang

Author: None (charan-003)

Changes

Key Changes
Enhancements in SemaLambda.cpp:

Updated the ExplicitCaptureRanges logic to compute more precise source ranges for unused lambda captures.

  • Fixed the handling of edge cases, including:
  • Trailing and leading whitespace in captures.
  • Redundant commas.
  • Mixed captures (e.g., [=, &a, b]).

Test Improvements in fixit-unused-lambda-capture.cpp:

  • Added new tests to validate correct Fix-It suggestions for edge cases:
  • Redundant commas like [a, , b].
  • Leading/trailing whitespace in capture lists.
  • Mixed capture styles (e.g., [=, &a]).
  • Single and multiple unused captures in different scenarios.

Full diff: https://github.com/llvm/llvm-project/pull/117953.diff

2 Files Affected:

  • (modified) clang/lib/Sema/SemaLambda.cpp (+10-3)
  • (modified) clang/test/FixIt/fixit-unused-lambda-capture.cpp (+32)
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index a67c0b2b367d1a..e7417d1a884dcd 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1164,8 +1164,11 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
                           /*FunctionScopeIndexToStopAtPtr*/ nullptr,
                           C->Kind == LCK_StarThis);
       if (!LSI->Captures.empty())
-        LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
-      continue;
+      {
+          SourceRange TrimmedRange = Lexer::makeFileCharRange(
+              C->ExplicitRange, SM, LangOpts);
+          LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange;
+      }
     }
 
     assert(C->Id && "missing identifier for capture");
@@ -1329,7 +1332,11 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
       tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc);
     }
     if (!LSI->Captures.empty())
-      LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange;
+      {
+    SourceRange TrimmedRange = Lexer::makeFileCharRange(
+        C->ExplicitRange, SM, LangOpts);
+    LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange;
+}
   }
   finishLambdaExplicitCaptures(LSI);
   LSI->ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;
diff --git a/clang/test/FixIt/fixit-unused-lambda-capture.cpp b/clang/test/FixIt/fixit-unused-lambda-capture.cpp
index ce0c78d677099a..ae43d4ebbdf821 100644
--- a/clang/test/FixIt/fixit-unused-lambda-capture.cpp
+++ b/clang/test/FixIt/fixit-unused-lambda-capture.cpp
@@ -66,6 +66,38 @@ void test() {
   // CHECK: [z = (n = i)] {};
   [j,z = (n = i)] {};
   // CHECK: [z = (n = i)] {};
+
+  // New Edge Cases
+
+  // Test 1: Leading and trailing whitespace
+  [i,    j] { return i; };
+  // CHECK: [i] { return i; };
+  [i ,    j] { return j; };
+  // CHECK: [j] { return j; };
+  [i  ,  j ,  k] { return j + k; };
+  // CHECK: [j,k] { return j + k; };
+
+  // Test 2: Single unused capture
+  [i] {};
+  // CHECK: [] {};
+  [&i] {};
+  // CHECK: [] {};
+
+  // Test 3: Multiple commas
+  [i,,j] { return j; };
+  // CHECK: [j] { return j; };
+  [,i,j,,k] { return k; };
+  // CHECK: [k] { return k; };
+
+  // Test 4: Mixed captures
+  [=, &i, j] { return i; };
+  // CHECK: [&i] { return i; };
+  [&, i] {};
+  // CHECK: [&] {};
+
+  // Test 5: Capture with comments
+  [/*capture*/ i, j] { return j; };
+  // CHECK: [/*capture*/ j] { return j; };
 }
 
 class ThisTest {

@charan-003 charan-003 changed the title [FixIt] Improve Source Ranges and Fix-It Hints for Unused Lambda Captures [FixIt] Improve Source Ranges and Fix-It Hints for Unused Lambda Captures #106445 Nov 28, 2024
added #include "clang/Lex/Lexer.h"
Copy link
Author

@charan-003 charan-003 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[FixIt] Improve Source Ranges and Fix-It Hints for Unused Lambda Captures #106445

Copy link
Author

@charan-003 charan-003 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[FixIt] Improve Source Ranges and Fix-It Hints for Unused Lambda Captures #106445

Copy link
Author

@charan-003 charan-003 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mprove Source Ranges and Fix-It Hints for Unused Lambda Captures #106445

Copy link
Author

@charan-003 charan-003 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[FixIt] Improve Source Ranges and Fix-It Hints for Unused Lambda Captures #106445

@cor3ntin
Copy link
Contributor

By the time we are in Sema, the ranges should be correct.
I think the issue is somewhere in Parser::ParseLambdaIntroducer. It does seem quite confused https://gcc.godbolt.org/z/h7rfEGnMb

In particular, can you check whether SourceLocation LocEnd = PrevTokLocation; behave correctly?

@charan-003
Copy link
Author

hi @cor3ntin made necessary updates to ParseExprCXX.cpp, but now ten tests are failing. Could you kindly provide on how to debug them? What are the main areas in ParseExprCXX.cpp that I should concentrate on while debugging these kinds of problems?

@charan-003
Copy link
Author

Hi @cor3ntin

After making changes in ParseExprCXX.cpp, I’m down to 10 failing test cases related to lambda parsing and Fix-It hints for unused captures. I reviewed Parser::ParseLambdaIntroducer and checked how SourceLocation LocEnd = PrevTokLocation; is used, but I’m still uncertain about where the incorrect source ranges might be originating.

Could you suggest:

Specific Parsing Logic: Which part of ParseLambdaIntroducer should I focus on when debugging incorrect source ranges? Are there common issues with PrevTokLocation assignments?

Source Location Validations: Would it be helpful to insert assertions or debug prints at specific points in the parser to check computed source ranges during parsing?

Next Steps: Given the test cases I shared earlier, would focusing on a particular test provide better insight into the issue?

Copy link
Author

@charan-003 charan-003 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added few test cases

Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only a quick scroll through here, and @cor3ntin is the right one to review this, but the test coverage for the new diagnostics seems non-existant. And much of the test changes themselves are just changing what looks like they are valid tests.

Please ADD tests for your new things, and make it clear what/why you're changing existing tests in this way.

@@ -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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why change the test? this one seemed like a useful diagnostic, and one I'd like to see.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

github-actions bot commented May 3, 2025

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff HEAD~1 HEAD --extensions cpp -- clang/lib/Parse/ParseExprCXX.cpp clang/lib/Sema/SemaLambda.cpp clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp clang/test/FixIt/fixit-unused-lambda-capture.cpp clang/test/Parser/lambda-misplaced-capture-default.cpp clang/test/SemaCXX/cxx1y-init-captures.cpp
View the diff from clang-format here.
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 5cdb05d26..91342360d 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1274,13 +1274,13 @@ static void tryConsumeLambdaSpecifierToken(Parser &P,
                                  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);
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index be9a9f023..9c02c4703 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"
@@ -28,8 +30,6 @@
 #include "clang/Sema/SemaSYCL.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;
@@ -1189,25 +1189,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;
@@ -1221,66 +1223,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) {
@@ -1420,14 +1417,16 @@ if (!C->InitCaptureType || C->InitCaptureType.get().isNull()) {
                                 : TryCaptureKind::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;
@@ -2236,32 +2235,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;

clang/lib/Parse/ParseExprCXX.cpp Outdated Show resolved Hide resolved
Comment on lines 9 to 49
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; };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you keep the existing tests as they were?

@@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@charan-003 charan-003 requested a review from cor3ntin May 7, 2025 13:04
@charan-003
Copy link
Author

@cor3ntin Also, I'm nearly done with this task. Can it be assigned to me?

Copy link
Contributor

@ojhunt ojhunt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a lot of changes that are non-functional (NFC) formatting changes, it would help to remove those changes from this PR as it makes the PR larger than necessary.

Another common issue is excess braces - the llvm formatting rule is no braces for if, etc if there is a single statement even if the statement crosses multiple lines.

CaptureReadyLambdaLSI->PotentialThisCaptureLocation,
/*Explicit*/ false, /*BuildAndDiagnose*/ false,
&IndexOfCaptureReadyLambda);
const bool CanCaptureThis = !S.CheckCXXThisCapture(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like an irrelevant formatting change? possibly the result of accumulated changes

@@ -238,7 +240,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(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

irrelevant formatting change

@@ -317,8 +319,8 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) {
}

if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ManglingContextDecl)) {
if (const DeclContext *LexicalDC
= Param->getDeclContext()->getLexicalParent())
if (const DeclContext *LexicalDC =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

irrelevant formatting change again

@@ -575,8 +577,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");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NFC formatting change

@@ -597,8 +598,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())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NFC formatting change

}

if (DeducedType->isVoidType()) {
if (!DeducedType->isDependentType()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excess braces again

VarDecl::Create(Ctx, nullptr, C->Loc, C->Loc, DummyID, DummyType,
nullptr, SC_None);

if (!TempVarDecl) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excess brace

}
}

if (!DeducedType.isNull()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excess braces

@@ -1247,12 +1311,12 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
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));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NFC formatting change that should be removed

@@ -1599,7 +1671,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());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NFC formatting change

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.