https://github.com/kashika0112 updated 
https://github.com/llvm/llvm-project/pull/171081

>From d9e30d12154c68a956bbf8eabb1a56a572e8e118 Mon Sep 17 00:00:00 2001
From: Kashika Akhouri <[email protected]>
Date: Mon, 8 Dec 2025 06:14:28 +0000
Subject: [PATCH 1/2] Add annotation inference

---
 clang/lib/Analysis/LifetimeSafety/Checker.cpp   | 17 ++++++++++++++++-
 .../Sema/warn-lifetime-safety-suggestions.cpp   | 12 ++++++++++++
 clang/test/Sema/warn-lifetime-safety.cpp        | 16 +++++++++++++++-
 3 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 74792768e2c57..f5236f63da34a 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -55,13 +55,14 @@ class LifetimeChecker {
   const LiveOriginsAnalysis &LiveOrigins;
   const FactManager &FactMgr;
   LifetimeSafetyReporter *Reporter;
+  AnalysisDeclContext &AC;
 
 public:
   LifetimeChecker(const LoanPropagationAnalysis &LoanPropagation,
                   const LiveOriginsAnalysis &LiveOrigins, const FactManager 
&FM,
                   AnalysisDeclContext &ADC, LifetimeSafetyReporter *Reporter)
       : LoanPropagation(LoanPropagation), LiveOrigins(LiveOrigins), 
FactMgr(FM),
-        Reporter(Reporter) {
+        Reporter(Reporter), AC(ADC) {
     for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>())
       for (const Fact *F : FactMgr.getFacts(B))
         if (const auto *EF = F->getAs<ExpireFact>())
@@ -70,6 +71,7 @@ class LifetimeChecker {
           checkAnnotations(OEF);
     issuePendingWarnings();
     suggestAnnotations();
+    inferAnnotations();
   }
 
   /// Checks if an escaping origin holds a placeholder loan, indicating a
@@ -160,6 +162,19 @@ class LifetimeChecker {
     for (const auto &[PVD, EscapeExpr] : AnnotationWarningsMap)
       Reporter->suggestAnnotation(PVD, EscapeExpr);
   }
+
+  void inferAnnotations() {
+    /// NOTE: This currently only adds the attribute to the function definition
+    /// being analyzed. For full inter-procedural inference to work reliably
+    /// (e.g., with out-of-order definitions), this attribute would also need 
to
+    /// be added to all other redeclarations of the function.
+    for (const auto &[ConstPVD, EscapeExpr] : AnnotationWarningsMap) {
+      ParmVarDecl *PVD = const_cast<ParmVarDecl *>(ConstPVD);
+      ASTContext &Ctx = AC.getASTContext();
+      auto *Attr = LifetimeBoundAttr::CreateImplicit(Ctx, SourceLocation());
+      PVD->addAttr(Attr);
+    }
+  }
 };
 } // namespace
 
diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp 
b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index c0f675a301d14..087899b9f5d3f 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -89,6 +89,18 @@ void test_getView_on_temporary() {
   (void)sv;
 }
 
+//===----------------------------------------------------------------------===//
+// Annotation Inference Test Cases
+//===----------------------------------------------------------------------===//
+
+View return_view_by_func (View a) {    // expected-warning {{param should be 
marked [[clang::lifetimebound]]}}.
+  return return_view_directly(a);      // expected-note {{param returned here}}
+}
+
+MyObj* return_pointer_by_func (MyObj* a) {         // expected-warning {{param 
should be marked [[clang::lifetimebound]]}}.
+  return return_pointer_object(a);                 // expected-note {{param 
returned here}} 
+}
+
 
//===----------------------------------------------------------------------===//
 // Negative Test Cases
 
//===----------------------------------------------------------------------===//
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp 
b/clang/test/Sema/warn-lifetime-safety.cpp
index 1191469e23df1..251324f968acd 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -fexperimental-lifetime-safety 
-Wexperimental-lifetime-safety -Wno-dangling -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fexperimental-lifetime-safety 
-Wexperimental-lifetime-safety -Wno-dangling 
-Wno-experimental-lifetime-safety-suggestions -verify %s
 
 struct MyObj {
   int id;
@@ -552,6 +552,20 @@ const int& get_ref_to_local() {
                       // expected-note@-1 {{returned here}}
 }
 
+View inference_callee_return_identity(View a) {
+  return a;
+}
+
+View inference_caller_forwards_callee(View a) {
+  return inference_callee_return_identity(a);
+}
+
+View inference_top_level_return_stack_view() {
+  MyObj local_stack;
+  return inference_caller_forwards_callee(local_stack);     // 
expected-warning {{address of stack memory is returned later}}
+                                                            // 
expected-note@-1 {{returned here}}
+}
+
 
//===----------------------------------------------------------------------===//
 // Use-After-Scope & Use-After-Return (Return-Stack-Address) Combined
 // These are cases where the diagnostic kind is determined by location

>From cd528bbe55c053500d8055d3ce0d9b336ca1287d Mon Sep 17 00:00:00 2001
From: Kashika Akhouri <[email protected]>
Date: Mon, 8 Dec 2025 12:54:29 +0000
Subject: [PATCH 2/2] Add more unit tests

---
 clang/lib/Analysis/LifetimeSafety/Checker.cpp | 18 ++++-----
 .../Sema/warn-lifetime-safety-suggestions.cpp | 28 ++++++++++++++
 clang/test/Sema/warn-lifetime-safety.cpp      | 38 +++++++++++++++++++
 3 files changed, 75 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index f5236f63da34a..c8592a623dd2f 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -55,14 +55,14 @@ class LifetimeChecker {
   const LiveOriginsAnalysis &LiveOrigins;
   const FactManager &FactMgr;
   LifetimeSafetyReporter *Reporter;
-  AnalysisDeclContext &AC;
+  ASTContext &AC;
 
 public:
   LifetimeChecker(const LoanPropagationAnalysis &LoanPropagation,
                   const LiveOriginsAnalysis &LiveOrigins, const FactManager 
&FM,
                   AnalysisDeclContext &ADC, LifetimeSafetyReporter *Reporter)
       : LoanPropagation(LoanPropagation), LiveOrigins(LiveOrigins), 
FactMgr(FM),
-        Reporter(Reporter), AC(ADC) {
+        Reporter(Reporter), AC(ADC.getASTContext()) {
     for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>())
       for (const Fact *F : FactMgr.getFacts(B))
         if (const auto *EF = F->getAs<ExpireFact>())
@@ -164,15 +164,15 @@ class LifetimeChecker {
   }
 
   void inferAnnotations() {
-    /// NOTE: This currently only adds the attribute to the function definition
-    /// being analyzed. For full inter-procedural inference to work reliably
-    /// (e.g., with out-of-order definitions), this attribute would also need 
to
-    /// be added to all other redeclarations of the function.
+    // FIXME: To maximise inference propagation, functions should be analyzed 
in
+    // post-order of the call graph, allowing inferred annotations to propagate
+    // through the call chain
+    // FIXME: Add the inferred attribute to all redeclarations of the function,
+    // not just the definition being analyzed.
     for (const auto &[ConstPVD, EscapeExpr] : AnnotationWarningsMap) {
       ParmVarDecl *PVD = const_cast<ParmVarDecl *>(ConstPVD);
-      ASTContext &Ctx = AC.getASTContext();
-      auto *Attr = LifetimeBoundAttr::CreateImplicit(Ctx, SourceLocation());
-      PVD->addAttr(Attr);
+      if (!PVD->hasAttr<LifetimeBoundAttr>())
+        PVD->addAttr(LifetimeBoundAttr::CreateImplicit(AC, 
PVD->getLocation()));
     }
   }
 };
diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp 
b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index 087899b9f5d3f..248179e8ba7b6 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -93,6 +93,7 @@ void test_getView_on_temporary() {
 // Annotation Inference Test Cases
 
//===----------------------------------------------------------------------===//
 
+namespace correct_order_inference {
 View return_view_by_func (View a) {    // expected-warning {{param should be 
marked [[clang::lifetimebound]]}}.
   return return_view_directly(a);      // expected-note {{param returned here}}
 }
@@ -100,6 +101,33 @@ View return_view_by_func (View a) {    // expected-warning 
{{param should be mar
 MyObj* return_pointer_by_func (MyObj* a) {         // expected-warning {{param 
should be marked [[clang::lifetimebound]]}}.
   return return_pointer_object(a);                 // expected-note {{param 
returned here}} 
 }
+} // correct_order_inference
+
+namespace incorrect_order_inference_view {
+View return_view_callee(View a);
+
+// FIXME: No lifetime annotation suggestion when functions are not present in 
the callee-before-caller pattern
+View return_view_caller(View a) {
+  return return_view_callee(a);
+}
+
+View return_view_callee(View a) {     // expected-warning {{param should be 
marked [[clang::lifetimebound]]}}.
+  return a;                           // expected-note {{param returned here}}
+}   
+} // incorrect_order_inference_view
+
+namespace incorrect_order_inference_object {
+View return_object_callee(View a);
+
+// FIXME: No lifetime annotation suggestion warning when functions are not 
present in the callee-before-caller pattern
+View return_object_caller(View a) {
+  return return_object_callee(a);
+}
+
+View return_object_callee(View a) {     // expected-warning {{param should be 
marked [[clang::lifetimebound]]}}.
+  return a;                           // expected-note {{param returned here}}
+}   
+} // incorrect_order_inference_object
 
 
//===----------------------------------------------------------------------===//
 // Negative Test Cases
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp 
b/clang/test/Sema/warn-lifetime-safety.cpp
index 251324f968acd..8cd1bd8bcc54c 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -552,6 +552,7 @@ const int& get_ref_to_local() {
                       // expected-note@-1 {{returned here}}
 }
 
+namespace simple_annotation_inference {
 View inference_callee_return_identity(View a) {
   return a;
 }
@@ -565,6 +566,43 @@ View inference_top_level_return_stack_view() {
   return inference_caller_forwards_callee(local_stack);     // 
expected-warning {{address of stack memory is returned later}}
                                                             // 
expected-note@-1 {{returned here}}
 }
+} // simple_annotation_inference
+
+namespace inference_in_order_with_redecls {
+View inference_callee_return_identity(View a);
+View inference_callee_return_identity(View a) {
+  return a;
+}
+
+View inference_caller_forwards_callee(View a);
+View inference_caller_forwards_callee(View a) {
+  return inference_callee_return_identity(a);
+}
+  
+View inference_top_level_return_stack_view() {
+  MyObj local_stack;
+  return inference_caller_forwards_callee(local_stack);     // 
expected-warning {{address of stack memory is returned later}}
+                                                            // 
expected-note@-1 {{returned here}}
+}
+} // namespace inference_in_order_with_redecls
+
+namespace inference_with_templates {
+template<typename T>
+T* template_identity(T* a) {
+  return a;
+}
+
+template<typename T>
+T* template_caller(T* a) {
+  return template_identity(a);
+}
+
+// FIXME: Fails to detect UAR as template instantiations are deferred to the 
end of the Translation Unit.
+MyObj* test_template_inference_with_stack() {
+  MyObj local_stack;
+  return template_caller(&local_stack);                                        
      
+}
+} // inference_with_templates
 
 
//===----------------------------------------------------------------------===//
 // Use-After-Scope & Use-After-Return (Return-Stack-Address) Combined

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

Reply via email to