https://github.com/spavloff updated 
https://github.com/llvm/llvm-project/pull/155213

>From 52499a2a3fde7c66f398e5730f782e0faf6f6e2d Mon Sep 17 00:00:00 2001
From: Serge Pavlov <[email protected]>
Date: Mon, 25 Aug 2025 12:20:21 +0700
Subject: [PATCH 1/3] [clang] Check captured variables for noreturn attribute

Anaysis for noreturn attribute now misses the case when an assignment to
a variable is made inside a lambda function call. This change fixes that
case.
---
 clang/lib/Sema/AnalysisBasedWarnings.cpp | 35 ++++++++++++++++++++++++
 clang/test/SemaCXX/noreturn-vars.cpp     | 13 +++++++++
 2 files changed, 48 insertions(+)

diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 0b94b1044f072..fe1498003e7da 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -467,6 +467,41 @@ struct TransferFunctions : public 
StmtVisitor<TransferFunctions> {
               AllValuesAreNoReturn = false;
     }
   }
+
+  void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
+    if (CE->getOperator() == OO_Call && CE->getNumArgs() > 0) {
+      Expr *Obj = CE->getArg(0)->IgnoreParenCasts();
+      if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Obj))
+        Obj = MTE->getSubExpr();
+      if (auto *DRE = dyn_cast<DeclRefExpr>(Obj)) {
+        auto *D = dyn_cast<VarDecl>(DRE->getDecl());
+        if (D->hasInit())
+          Obj = D->getInit();
+      }
+      Visit(Obj);
+    }
+  }
+
+  void VisitLambdaExpr(LambdaExpr *LE) {
+    for (const LambdaCapture &Capture : LE->captures())
+      if (Capture.capturesVariable())
+        if (const VarDecl *VD = dyn_cast<VarDecl>(Capture.getCapturedVar()))
+          if (VD == Var)
+            if (Capture.getCaptureKind() == LCK_ByRef)
+              AllValuesAreNoReturn = false;
+  }
+
+  void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE) {
+    Visit(MTE->getSubExpr());
+  }
+
+  void VisitExprWithCleanups(FullExpr *FE) {
+    Visit(FE->getSubExpr());
+  }
+
+  void VisitCXXConstructExpr(CXXConstructExpr *CE) {
+    Visit(CE->getArg(0));
+  }
 };
 } // namespace
 
diff --git a/clang/test/SemaCXX/noreturn-vars.cpp 
b/clang/test/SemaCXX/noreturn-vars.cpp
index ca65fcf5ca31d..3b2473c1bc670 100644
--- a/clang/test/SemaCXX/noreturn-vars.cpp
+++ b/clang/test/SemaCXX/noreturn-vars.cpp
@@ -225,3 +225,16 @@ extern void abc_02(func_type *);
   abc_02(&func_ptr);
   func_ptr();
 } // expected-warning {{function declared 'noreturn' should not return}}
+
+[[noreturn]] void test_lambda() {
+  func_type func_ptr = noret;
+  [&func_ptr]() { func_ptr = ordinary; } ();
+  func_ptr();
+} // expected-warning {{function declared 'noreturn' should not return}}
+
+[[noreturn]] void test_lambda_var(int x) {
+  func_type func_ptr = noret;
+  auto LF = [&](){func_ptr = ordinary;};
+  LF();
+  func_ptr();
+} // expected-warning {{function declared 'noreturn' should not return}}

>From 8c258f43414876636f9d4029cc6c3c2cbcc7b993 Mon Sep 17 00:00:00 2001
From: Serge Pavlov <[email protected]>
Date: Thu, 18 Sep 2025 00:14:48 +0700
Subject: [PATCH 2/3] Addressreview notes

---
 clang/lib/Sema/AnalysisBasedWarnings.cpp |  8 ++---
 clang/test/SemaCXX/noreturn-vars.cpp     | 40 ++++++++++++++++++++++--
 2 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index fe1498003e7da..b16c9989fbbb4 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -480,6 +480,7 @@ struct TransferFunctions : public 
StmtVisitor<TransferFunctions> {
       }
       Visit(Obj);
     }
+    VisitCallExpr(CE);
   }
 
   void VisitLambdaExpr(LambdaExpr *LE) {
@@ -495,12 +496,11 @@ struct TransferFunctions : public 
StmtVisitor<TransferFunctions> {
     Visit(MTE->getSubExpr());
   }
 
-  void VisitExprWithCleanups(FullExpr *FE) {
-    Visit(FE->getSubExpr());
-  }
+  void VisitExprWithCleanups(FullExpr *FE) { Visit(FE->getSubExpr()); }
 
   void VisitCXXConstructExpr(CXXConstructExpr *CE) {
-    Visit(CE->getArg(0));
+    if (CE->getNumArgs() > 0)
+      Visit(CE->getArg(0));
   }
 };
 } // namespace
diff --git a/clang/test/SemaCXX/noreturn-vars.cpp 
b/clang/test/SemaCXX/noreturn-vars.cpp
index 3b2473c1bc670..9b23dc96d9ae0 100644
--- a/clang/test/SemaCXX/noreturn-vars.cpp
+++ b/clang/test/SemaCXX/noreturn-vars.cpp
@@ -226,15 +226,49 @@ extern void abc_02(func_type *);
   func_ptr();
 } // expected-warning {{function declared 'noreturn' should not return}}
 
-[[noreturn]] void test_lambda() {
+[[noreturn]] void test_lambda_capture_ref() {
   func_type func_ptr = noret;
   [&func_ptr]() { func_ptr = ordinary; } ();
   func_ptr();
 } // expected-warning {{function declared 'noreturn' should not return}}
 
-[[noreturn]] void test_lambda_var(int x) {
+[[noreturn]] void test_lambda_var_capture_ref() {
   func_type func_ptr = noret;
-  auto LF = [&](){func_ptr = ordinary;};
+  auto LF = [&func_ptr](){func_ptr = ordinary; };
   LF();
   func_ptr();
 } // expected-warning {{function declared 'noreturn' should not return}}
+
+[[noreturn]] void test_lambda_capture_ref_all() {
+  func_type func_ptr = noret;
+  [&]() { func_ptr = ordinary; } ();
+  func_ptr();
+} // expected-warning {{function declared 'noreturn' should not return}}
+
+[[noreturn]] void test_lambda_var_capture_ref_all() {
+  func_type func_ptr = noret;
+  auto LF = [&](){func_ptr = ordinary; };
+  LF();
+  func_ptr();
+} // expected-warning {{function declared 'noreturn' should not return}}
+
+[[noreturn]] void lambda_capture_by_value() {
+  func_type func_ptr = noret;
+  auto LF = [func_ptr](){ return func_ptr; };
+  LF();
+  func_ptr();
+}
+
+[[noreturn]] void lambda_pass_by_ref() {
+  func_type func_ptr = noret;
+  auto LF = [](func_type &fptr){ fptr = ordinary; };
+  LF(func_ptr);
+  func_ptr();
+} // expected-warning {{function declared 'noreturn' should not return}}
+
+[[noreturn]] void lambda_pass_by_value() {
+  func_type func_ptr = noret;
+  auto LF = [](func_type fptr){ fptr = ordinary; };
+  LF(func_ptr);
+  func_ptr();
+}

>From 3dc5d78a14e0232d5ccc4e14a9cf707111dabdb7 Mon Sep 17 00:00:00 2001
From: Serge Pavlov <[email protected]>
Date: Thu, 30 Oct 2025 01:33:28 +0700
Subject: [PATCH 3/3] Small enhancements

---
 clang/lib/Sema/AnalysisBasedWarnings.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index b16c9989fbbb4..88fd63156d002 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -475,7 +475,7 @@ struct TransferFunctions : public 
StmtVisitor<TransferFunctions> {
         Obj = MTE->getSubExpr();
       if (auto *DRE = dyn_cast<DeclRefExpr>(Obj)) {
         auto *D = dyn_cast<VarDecl>(DRE->getDecl());
-        if (D->hasInit())
+        if (D && D->hasInit())
           Obj = D->getInit();
       }
       Visit(Obj);
@@ -487,9 +487,8 @@ struct TransferFunctions : public 
StmtVisitor<TransferFunctions> {
     for (const LambdaCapture &Capture : LE->captures())
       if (Capture.capturesVariable())
         if (const VarDecl *VD = dyn_cast<VarDecl>(Capture.getCapturedVar()))
-          if (VD == Var)
-            if (Capture.getCaptureKind() == LCK_ByRef)
-              AllValuesAreNoReturn = false;
+          if (VD == Var && Capture.getCaptureKind() == LCK_ByRef)
+            AllValuesAreNoReturn = false;
   }
 
   void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE) {

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

Reply via email to