https://github.com/zwuis updated 
https://github.com/llvm/llvm-project/pull/159364

>From 06b010d27dcfbd3a03453d6aab04f854ed734891 Mon Sep 17 00:00:00 2001
From: Yanzuo Liu <[email protected]>
Date: Wed, 17 Sep 2025 21:54:01 +0800
Subject: [PATCH 1/2] Make lambda in non-dependent context generate same
 analysis-based warnings as function[ template]

---
 clang/docs/ReleaseNotes.rst              |  3 ++
 clang/include/clang/Sema/Sema.h          |  2 +-
 clang/lib/Sema/Sema.cpp                  |  4 +--
 clang/lib/Sema/SemaExpr.cpp              |  2 +-
 clang/lib/Sema/SemaLambda.cpp            | 16 +++++++++--
 clang/test/SemaCXX/warn-unused-value.cpp | 36 ++++++++++++++++++++++++
 6 files changed, 56 insertions(+), 7 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 518ed9e0f4b3e..0b68512d0c872 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -312,6 +312,9 @@ Improvements to Clang's diagnostics
   properly being rejected when used at compile-time. It was not implemented
   and caused assertion failures before (#GH158471).
 
+- Some reachability-analysis-based warnings in lambda expression which is in
+  non-templated context are emitted same as in function[ template].
+
 Improvements to Clang's time-trace
 ----------------------------------
 
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d017d1f829015..197b1eedc906d 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1166,7 +1166,7 @@ class Sema final : public SemaBase {
   /// getCurFunctionOrMethodDecl - Return the Decl for the current ObjC method
   /// or C function we're in, otherwise return null.  If we're currently
   /// in a 'block', this returns the containing context.
-  NamedDecl *getCurFunctionOrMethodDecl() const;
+  NamedDecl *getCurFunctionOrMethodDecl(bool AllowLambda = false) const;
 
   /// Warn if we're implicitly casting from a _Nullable pointer type to a
   /// _Nonnull one.
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 39fa25f66f3b7..913a11bedc55d 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1656,8 +1656,8 @@ ObjCMethodDecl *Sema::getCurMethodDecl() {
   return dyn_cast<ObjCMethodDecl>(DC);
 }
 
-NamedDecl *Sema::getCurFunctionOrMethodDecl() const {
-  DeclContext *DC = getFunctionLevelDeclContext();
+NamedDecl *Sema::getCurFunctionOrMethodDecl(bool AllowLambda) const {
+  DeclContext *DC = getFunctionLevelDeclContext(AllowLambda);
   if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC))
     return cast<NamedDecl>(DC);
   return nullptr;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 73b16ae09e922..b6fdcfb646cb0 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -20542,7 +20542,7 @@ void Sema::MarkDeclarationsReferencedInExpr(Expr *E,
 ///        namespace { auto *p = new double[3][false ? (1, 2) : 3]; }
 bool Sema::DiagIfReachable(SourceLocation Loc, ArrayRef<const Stmt *> Stmts,
                            const PartialDiagnostic &PD) {
-  if (!Stmts.empty() && getCurFunctionOrMethodDecl()) {
+  if (!Stmts.empty() && getCurFunctionOrMethodDecl(/*AllowLambda=*/true)) {
     if (!FunctionScopes.empty())
       FunctionScopes.back()->PossiblyUnreachableDiags.push_back(
           sema::PossiblyUnreachableDiag(PD, Loc, Stmts));
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index fbc2e7eb30676..2a6d0b5b4a9de 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1972,6 +1972,10 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation 
StartLoc, Stmt *Body) {
   if (LSI.CallOperator->hasAttr<SYCLKernelEntryPointAttr>())
     SYCL().CheckSYCLEntryPointFunctionDecl(LSI.CallOperator);
 
+  // TODO: Find out if passing LSI.CallOperator->getDescribedFunctionTemplate()
+  //       is necessary when it is a generic lambda. Are there any behaviour
+  //       changes? `FunctionTemplateDecl` is always passed when handling 
simple
+  //       function templates.
   ActOnFinishFunctionBody(LSI.CallOperator, Body, /*IsInstantiation=*/false,
                           /*RetainFunctionScopeInfo=*/true);
 
@@ -2162,11 +2166,17 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation 
StartLoc,
 
   PopExpressionEvaluationContext();
 
-  sema::AnalysisBasedWarnings::Policy WP =
-      AnalysisWarnings.getPolicyInEffectAt(EndLoc);
   // We cannot release LSI until we finish computing captures, which
   // requires the scope to be popped.
-  Sema::PoppedFunctionScopePtr _ = PopFunctionScopeInfo(&WP, 
LSI->CallOperator);
+  Sema::PoppedFunctionScopePtr _ = [&] {
+    if (LSI->CallOperator->getDescribedFunctionTemplate())
+      return PopFunctionScopeInfo(/*WP=*/nullptr,
+                                  TemplateOrNonTemplateCallOperatorDecl);
+
+    sema::AnalysisBasedWarnings::Policy WP =
+        AnalysisWarnings.getPolicyInEffectAt(EndLoc);
+    return PopFunctionScopeInfo(&WP, TemplateOrNonTemplateCallOperatorDecl);
+  }();
 
   // True if the current capture has a used capture or default before it.
   bool CurHasPreviousCapture = CaptureDefault != LCD_None;
diff --git a/clang/test/SemaCXX/warn-unused-value.cpp 
b/clang/test/SemaCXX/warn-unused-value.cpp
index 2a07a0324f3f0..7a2cbab275e0c 100644
--- a/clang/test/SemaCXX/warn-unused-value.cpp
+++ b/clang/test/SemaCXX/warn-unused-value.cpp
@@ -178,3 +178,39 @@ auto b() {
 }
 } // namespace test6
 #endif
+
+// ensure lambda in non-dependent context generate same diagnostics as 
function[ template]
+namespace lambda_in_non_dependent_context {
+void f1() {
+  0, 0; // expected-warning {{left operand of comma operator has no effect}}
+  return;
+  0, 0;
+}
+template <typename T> void f2(T) {
+  0, 0; // expected-warning {{left operand of comma operator has no effect}}
+  return;
+  0, 0; // expected-warning {{left operand of comma operator has no effect}}
+}
+auto L1 = [] {
+  0, 0; // expected-warning {{left operand of comma operator has no effect}}
+  return;
+  0, 0;
+};
+auto L2 = [](auto) {
+  0, 0; // expected-warning {{left operand of comma operator has no effect}}
+  return;
+  0, 0; // expected-warning {{left operand of comma operator has no effect}}
+};
+void f() {
+  auto L1 = [] {
+    0, 0; // expected-warning {{left operand of comma operator has no effect}}
+    return;
+    0, 0;
+  };
+  auto L2 = [](auto) {
+    0, 0; // expected-warning {{left operand of comma operator has no effect}}
+    return;
+    0, 0; // expected-warning {{left operand of comma operator has no effect}}
+  };
+}
+}

>From a1a6e2809a1569c1313ecb2fac0023bcf6e175ee Mon Sep 17 00:00:00 2001
From: Yanzuo Liu <[email protected]>
Date: Thu, 18 Sep 2025 09:22:54 +0800
Subject: [PATCH 2/2] Fix comment, fix test, and avoid unnecessary IILE

---
 clang/lib/Sema/SemaLambda.cpp            | 26 +++++++++++-------------
 clang/test/SemaCXX/warn-unused-value.cpp |  2 ++
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 2a6d0b5b4a9de..56af63d7eb35f 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1973,7 +1973,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, 
Stmt *Body) {
     SYCL().CheckSYCLEntryPointFunctionDecl(LSI.CallOperator);
 
   // TODO: Find out if passing LSI.CallOperator->getDescribedFunctionTemplate()
-  //       is necessary when it is a generic lambda. Are there any behaviour
+  //       is better when it is a generic lambda. Are there any behaviour
   //       changes? `FunctionTemplateDecl` is always passed when handling 
simple
   //       function templates.
   ActOnFinishFunctionBody(LSI.CallOperator, Body, /*IsInstantiation=*/false,
@@ -2153,12 +2153,17 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation 
StartLoc,
   CleanupInfo LambdaCleanup = LSI->Cleanup;
   bool ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack;
   bool IsGenericLambda = Class->isGenericLambda();
+  sema::AnalysisBasedWarnings::Policy WP =
+      AnalysisWarnings.getPolicyInEffectAt(EndLoc);
 
   CallOperator->setLexicalDeclContext(Class);
-  Decl *TemplateOrNonTemplateCallOperatorDecl =
-      CallOperator->getDescribedFunctionTemplate()
-          ? CallOperator->getDescribedFunctionTemplate()
-          : cast<Decl>(CallOperator);
+  Decl *TemplateOrNonTemplateCallOperatorDecl = CallOperator;
+  sema::AnalysisBasedWarnings::Policy *ActivePolicy = &WP;
+  if (IsGenericLambda) {
+    TemplateOrNonTemplateCallOperatorDecl =
+        CallOperator->getDescribedFunctionTemplate();
+    ActivePolicy = nullptr;
+  }
 
   // FIXME: Is this really the best choice? Keeping the lexical decl context
   // set as CurContext seems more faithful to the source.
@@ -2168,15 +2173,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc,
 
   // We cannot release LSI until we finish computing captures, which
   // requires the scope to be popped.
-  Sema::PoppedFunctionScopePtr _ = [&] {
-    if (LSI->CallOperator->getDescribedFunctionTemplate())
-      return PopFunctionScopeInfo(/*WP=*/nullptr,
-                                  TemplateOrNonTemplateCallOperatorDecl);
-
-    sema::AnalysisBasedWarnings::Policy WP =
-        AnalysisWarnings.getPolicyInEffectAt(EndLoc);
-    return PopFunctionScopeInfo(&WP, TemplateOrNonTemplateCallOperatorDecl);
-  }();
+  Sema::PoppedFunctionScopePtr _ =
+      PopFunctionScopeInfo(ActivePolicy, 
TemplateOrNonTemplateCallOperatorDecl);
 
   // True if the current capture has a used capture or default before it.
   bool CurHasPreviousCapture = CaptureDefault != LCD_None;
diff --git a/clang/test/SemaCXX/warn-unused-value.cpp 
b/clang/test/SemaCXX/warn-unused-value.cpp
index 7a2cbab275e0c..5f77c52c8ddc2 100644
--- a/clang/test/SemaCXX/warn-unused-value.cpp
+++ b/clang/test/SemaCXX/warn-unused-value.cpp
@@ -179,6 +179,7 @@ auto b() {
 } // namespace test6
 #endif
 
+#if __cplusplus >= 201402L
 // ensure lambda in non-dependent context generate same diagnostics as 
function[ template]
 namespace lambda_in_non_dependent_context {
 void f1() {
@@ -214,3 +215,4 @@ void f() {
   };
 }
 }
+#endif

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to