https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/169320

>From 8b25d76c2c63afe59b8d312ff083f4779ff27d7a Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Mon, 24 Nov 2025 11:54:49 +0000
Subject: [PATCH] fix-missing-lifetimeends-for-params

---
 clang/lib/Analysis/CFG.cpp                    |  9 +++++++++
 clang/test/Analysis/scopes-cfg-output.cpp     |  2 ++
 clang/test/Sema/warn-lifetime-safety.cpp      | 20 +++++++++++++------
 .../Analysis/FlowSensitive/LoggerTest.cpp     | 11 +++++++++-
 4 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index cdde849b0e026..eeb7ac0a77037 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -1666,6 +1666,12 @@ std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, 
Stmt *Statement) {
   assert(Succ == &cfg->getExit());
   Block = nullptr;  // the EXIT block is empty.  Create all other blocks 
lazily.
 
+  // Add parameters to the initial scope to handle their dtos and lifetime 
ends.
+  LocalScope *paramScope = nullptr;
+  if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D))
+    for (ParmVarDecl *PD : FD->parameters())
+      paramScope = addLocalScopeForVarDecl(PD, paramScope);
+
   if (BuildOpts.AddImplicitDtors)
     if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D))
       addImplicitDtorsForDestructor(DD);
@@ -2246,6 +2252,9 @@ LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl 
*VD,
   if (!VD->hasLocalStorage())
     return Scope;
 
+  if (isa<ParmVarDecl>(VD) && VD->getType()->isReferenceType())
+    return Scope;
+
   if (!BuildOpts.AddLifetime && !BuildOpts.AddScopes &&
       !needsAutomaticDestruction(VD)) {
     assert(BuildOpts.AddImplicitDtors);
diff --git a/clang/test/Analysis/scopes-cfg-output.cpp 
b/clang/test/Analysis/scopes-cfg-output.cpp
index 6ed6f3638f75b..9c75492c33a42 100644
--- a/clang/test/Analysis/scopes-cfg-output.cpp
+++ b/clang/test/Analysis/scopes-cfg-output.cpp
@@ -1437,12 +1437,14 @@ void test_cleanup_functions() {
 // CHECK-NEXT:    4: return;
 // CHECK-NEXT:    5: CleanupFunction (cleanup_int)
 // CHECK-NEXT:    6: CFGScopeEnd(i)
+// CHECK-NEXT:    7: CFGScopeEnd(m)
 // CHECK-NEXT:    Preds (1): B3
 // CHECK-NEXT:    Succs (1): B0
 // CHECK:      [B2]
 // CHECK-NEXT:    1: return;
 // CHECK-NEXT:    2: CleanupFunction (cleanup_int)
 // CHECK-NEXT:    3: CFGScopeEnd(i)
+// CHECK-NEXT:    4: CFGScopeEnd(m)
 // CHECK-NEXT:    Preds (1): B3
 // CHECK-NEXT:    Succs (1): B0
 // CHECK:      [B3]
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp 
b/clang/test/Sema/warn-lifetime-safety.cpp
index e80a05860389c..c08543c27778f 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -529,14 +529,14 @@ TriviallyDestructedClass* trivial_class_uar () {
   return ptr;     // expected-note {{returned here}}
 }
 
-// FIXME: No lifetime warning for this as no expire facts are generated for 
parameters
 const int& return_parameter(int a) { 
-  return a; 
+  return a; // expected-warning {{address of stack memory is returned later}}
+            // expected-note@-1 {{returned here}}
 }
 
-// FIXME: No lifetime warning for this as no expire facts are generated for 
parameters
 int* return_pointer_to_parameter(int a) {
-    return &a;
+    return &a;  // expected-warning {{address of stack memory is returned 
later}}
+                // expected-note@-1 {{returned here}}
 }
 
 const int& return_reference_to_parameter(int a)
@@ -788,9 +788,17 @@ const MyObj& lifetimebound_return_ref_to_local() {
                              // expected-note@-1 {{returned here}}
 }
 
-// FIXME: Fails to diagnose UAR when a reference to a by-value param escapes 
via the return value.
 View lifetimebound_return_of_by_value_param(MyObj stack_param) {
-  return Identity(stack_param); 
+  return Identity(stack_param); // expected-warning {{address of stack memory 
is returned later}}
+                                // expected-note@-1 {{returned here}}
+}
+
+void LambdaUARParam() {
+  auto lambda = [](MyObj stack_param) {
+    return Identity(stack_param); // expected-warning {{address of stack 
memory is returned later}}
+                                  // expected-note@-1 {{returned here}}
+  };
+  lambda(MyObj{});
 }
 
 // FIXME: Fails to diagnose UAF when a reference to a by-value param escapes 
via an out-param.
diff --git a/clang/unittests/Analysis/FlowSensitive/LoggerTest.cpp 
b/clang/unittests/Analysis/FlowSensitive/LoggerTest.cpp
index 88630119ba8a1..30d28fb4698bf 100644
--- a/clang/unittests/Analysis/FlowSensitive/LoggerTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/LoggerTest.cpp
@@ -149,9 +149,18 @@ recordState(Elements=8, Branches=2, Joins=1)
 enterElement(return b ? p : q;)
 transfer()
 recordState(Elements=9, Branches=2, Joins=1)
+enterElement((Lifetime ends))
+transfer()
+recordState(Elements=10, Branches=2, Joins=1)
+enterElement((Lifetime ends))
+transfer()
+recordState(Elements=11, Branches=2, Joins=1)
+enterElement((Lifetime ends))
+transfer()
+recordState(Elements=12, Branches=2, Joins=1)
 
 enterBlock(0, false)
-recordState(Elements=9, Branches=2, Joins=1)
+recordState(Elements=12, Branches=2, Joins=1)
 
 endAnalysis()
 )");

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

Reply via email to