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/3] 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/3] 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

>From 211667d1e7044f5e8d5584f54d129e8091f93de7 Mon Sep 17 00:00:00 2001
From: Kashika Akhouri <[email protected]>
Date: Tue, 9 Dec 2025 06:50:04 +0000
Subject: [PATCH 3/3] Introduce new frontend flag for annotation inference

---
 clang/include/clang/Basic/LangOptions.def           |  2 ++
 clang/include/clang/Options/Options.td              |  8 ++++++++
 clang/lib/Analysis/LifetimeSafety/Checker.cpp       | 13 +++++++++----
 .../test/Sema/warn-lifetime-safety-suggestions.cpp  |  8 ++++----
 clang/test/Sema/warn-lifetime-safety.cpp            |  2 +-
 5 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..a136432993a3c 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -499,6 +499,8 @@ LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety 
extension for C")
 
 LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, "Experimental lifetime 
safety analysis for C++")
 
+LANGOPT(EnableLifetimeSafetyInference, 1, 0, NotCompatible, "Experimental 
lifetime safety inference analysis for C++")
+
 LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector 
type")
 
 #undef LANGOPT
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index c6841937c8d39..39c5753e50aed 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -1955,6 +1955,14 @@ defm lifetime_safety : BoolFOption<
   BothFlags<[], [CC1Option],
           " experimental lifetime safety for C++">>;
 
+defm lifetime_safety_inference
+    : BoolFOption<"experimental-lifetime-safety-inference",
+                  LangOpts<"EnableLifetimeSafetyInference">, DefaultFalse,
+                  PosFlag<SetTrue, [], [CC1Option], "Enable">,
+                  NegFlag<SetFalse, [], [CC1Option], "Disable">,
+                  BothFlags<[], [CC1Option],
+                            " experimental lifetime safety inference for 
C++">>;
+
 defm addrsig : BoolFOption<"addrsig",
   CodeGenOpts<"Addrsig">, DefaultFalse,
   PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit">,
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index c8592a623dd2f..99071d6b46c1e 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;
-  ASTContext &AC;
+  ASTContext &AST;
 
 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.getASTContext()) {
+        Reporter(Reporter), AST(ADC.getASTContext()) {
     for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>())
       for (const Fact *F : FactMgr.getFacts(B))
         if (const auto *EF = F->getAs<ExpireFact>())
@@ -71,7 +71,11 @@ class LifetimeChecker {
           checkAnnotations(OEF);
     issuePendingWarnings();
     suggestAnnotations();
-    inferAnnotations();
+    //  Annotation inference is currently guarded by a frontend flag. In the
+    //  future, this might be replaced by a design that differentiates between
+    //  explicit and inferred findings with separate warning groups.
+    if (AST.getLangOpts().EnableLifetimeSafetyInference)
+      inferAnnotations();
   }
 
   /// Checks if an escaping origin holds a placeholder loan, indicating a
@@ -172,7 +176,8 @@ class LifetimeChecker {
     for (const auto &[ConstPVD, EscapeExpr] : AnnotationWarningsMap) {
       ParmVarDecl *PVD = const_cast<ParmVarDecl *>(ConstPVD);
       if (!PVD->hasAttr<LifetimeBoundAttr>())
-        PVD->addAttr(LifetimeBoundAttr::CreateImplicit(AC, 
PVD->getLocation()));
+        PVD->addAttr(
+            LifetimeBoundAttr::CreateImplicit(AST, PVD->getLocation()));
     }
   }
 };
diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp 
b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index 248179e8ba7b6..592215bf94d4a 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -fexperimental-lifetime-safety 
-Wexperimental-lifetime-safety-suggestions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fexperimental-lifetime-safety 
-fexperimental-lifetime-safety-inference 
-Wexperimental-lifetime-safety-suggestions -verify %s
 
 struct MyObj {
   int id;
@@ -117,14 +117,14 @@ View return_view_callee(View a) {     // expected-warning 
{{param should be mark
 } // incorrect_order_inference_view
 
 namespace incorrect_order_inference_object {
-View return_object_callee(View a);
+MyObj* return_object_callee(MyObj* a);
 
 // FIXME: No lifetime annotation suggestion warning when functions are not 
present in the callee-before-caller pattern
-View return_object_caller(View a) {
+MyObj* return_object_caller(MyObj* a) {
   return return_object_callee(a);
 }
 
-View return_object_callee(View a) {     // expected-warning {{param should be 
marked [[clang::lifetimebound]]}}.
+MyObj* return_object_callee(MyObj* a) {     // expected-warning {{param should 
be marked [[clang::lifetimebound]]}}.
   return a;                           // expected-note {{param returned here}}
 }   
 } // incorrect_order_inference_object
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp 
b/clang/test/Sema/warn-lifetime-safety.cpp
index 8cd1bd8bcc54c..b993d4df7b235 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 
-Wno-experimental-lifetime-safety-suggestions -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fexperimental-lifetime-safety 
-fexperimental-lifetime-safety-inference -Wexperimental-lifetime-safety 
-Wno-dangling -Wno-experimental-lifetime-safety-suggestions -verify %s
 
 struct MyObj {
   int id;

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

Reply via email to