https://github.com/NeKon69 updated 
https://github.com/llvm/llvm-project/pull/198784

>From f95dcf6ef9be88c85f4a94735e93077046ecfe68 Mon Sep 17 00:00:00 2001
From: NeKon69 <[email protected]>
Date: Wed, 20 May 2026 16:30:14 +0300
Subject: [PATCH 1/2] remove function

---
 clang/lib/Analysis/LifetimeSafety/Checker.cpp | 57 ++++---------------
 .../test/Sema/warn-lifetime-safety-fixits.cpp |  9 ++-
 .../Sema/warn-lifetime-safety-suggestions.cpp | 24 ++++----
 3 files changed, 27 insertions(+), 63 deletions(-)

diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index d6a15139aa4ea..4b9d195411179 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -353,66 +353,31 @@ class LifetimeChecker {
             Scope};
   }
 
-  /// Returns the declaration of a function that is visible across translation
-  /// units, if such a declaration exists and is different from the definition.
-  static const FunctionDecl *getCrossTUDecl(const FunctionDecl &FD,
-                                            SourceManager &SM) {
-    if (!FD.isExternallyVisible())
-      return nullptr;
-    const FileID DefinitionFile = SM.getFileID(FD.getLocation());
-    for (const FunctionDecl *Redecl : FD.redecls())
-      if (SM.getFileID(Redecl->getLocation()) != DefinitionFile)
-        return Redecl;
-
-    return nullptr;
-  }
-
-  static const FunctionDecl *getCrossTUDecl(const ParmVarDecl &PVD,
-                                            SourceManager &SM) {
-    if (const auto *FD = dyn_cast<FunctionDecl>(PVD.getDeclContext()))
-      return getCrossTUDecl(*FD, SM);
-    return nullptr;
-  }
-
-  static void suggestWithScopeForParmVar(LifetimeSafetySemaHelper *SemaHelper,
-                                         const ParmVarDecl *PVD,
-                                         SourceManager &SM,
-                                         EscapingTarget EscapeTarget) {
+  void suggestWithScopeForParmVar(const ParmVarDecl *PVD,
+                                  EscapingTarget EscapeTarget) {
     if (llvm::isa<const VarDecl *>(EscapeTarget))
       return;
 
-    if (const FunctionDecl *CrossTUDecl = getCrossTUDecl(*PVD, SM))
-      SemaHelper->suggestLifetimeboundToParmVar(
-          WarningScope::CrossTU,
-          CrossTUDecl->getParamDecl(PVD->getFunctionScopeIndex()),
-          EscapeTarget);
-    else
-      SemaHelper->suggestLifetimeboundToParmVar(WarningScope::IntraTU, PVD,
-                                                EscapeTarget);
+    auto [Parm, Scope] = getCanonicalDeclForAttr(cast<FunctionDecl>(FD), PVD);
+    SemaHelper->suggestLifetimeboundToParmVar(Scope, Parm, EscapeTarget);
   }
 
-  static void
-  suggestWithScopeForImplicitThis(LifetimeSafetySemaHelper *SemaHelper,
-                                  const CXXMethodDecl *MD, SourceManager &SM,
-                                  const Expr *EscapeExpr) {
-    if (const FunctionDecl *CrossTUDecl = getCrossTUDecl(*MD, SM))
-      SemaHelper->suggestLifetimeboundToImplicitThis(
-          WarningScope::CrossTU, cast<CXXMethodDecl>(CrossTUDecl), EscapeExpr);
-    else
-      SemaHelper->suggestLifetimeboundToImplicitThis(WarningScope::IntraTU, MD,
-                                                     EscapeExpr);
+  void suggestWithScopeForImplicitThis(const CXXMethodDecl *MD,
+                                       const Expr *EscapeExpr) {
+    auto [MethodDecl, Scope] = getCanonicalDeclForAttr(MD);
+    SemaHelper->suggestLifetimeboundToImplicitThis(Scope, MethodDecl,
+                                                   EscapeExpr);
   }
 
   void suggestAnnotations() {
     if (!SemaHelper)
       return;
-    SourceManager &SM = AST.getSourceManager();
     for (auto [Target, EscapeTarget] : AnnotationWarningsMap) {
       if (const auto *PVD = Target.dyn_cast<const ParmVarDecl *>())
-        suggestWithScopeForParmVar(SemaHelper, PVD, SM, EscapeTarget);
+        suggestWithScopeForParmVar(PVD, EscapeTarget);
       else if (const auto *MD = Target.dyn_cast<const CXXMethodDecl *>()) {
         if (const auto *EscapeExpr = EscapeTarget.dyn_cast<const Expr *>())
-          suggestWithScopeForImplicitThis(SemaHelper, MD, SM, EscapeExpr);
+          suggestWithScopeForImplicitThis(MD, EscapeExpr);
         else
           llvm_unreachable("Implicit this can only escape via Expr (return)");
       }
diff --git a/clang/test/Sema/warn-lifetime-safety-fixits.cpp 
b/clang/test/Sema/warn-lifetime-safety-fixits.cpp
index 88d8bd379de8b..d9c7e8d3f0519 100644
--- a/clang/test/Sema/warn-lifetime-safety-fixits.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-fixits.cpp
@@ -69,12 +69,11 @@ int *arr_default(int a[2] = nullptr) {
   return a;
 }
 
-// FIXME: Iterate over redecls and add [[clang::lifetimebound]]
 View multi_decl(View a);
+// CHECK: :[[@LINE-1]]:17: warning: parameter in intra-TU function should be 
marked
+// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:23-[[@LINE-2]]:23}:" 
{{\[\[}}clang::lifetimebound]]"
 View multi_decl(View a);
 View multi_decl(View a) {
-  // CHECK: :[[@LINE-1]]:17: warning: parameter in intra-TU function should be 
marked
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:23-[[@LINE-2]]:23}:" 
{{\[\[}}clang::lifetimebound]]"
   return a;
 }
 
@@ -145,10 +144,10 @@ struct OutOfLine {
   OutOfLine() {}
   ~OutOfLine() {}
   const OutOfLine &get() const;
+  // CHECK: :[[@LINE-1]]:31: warning: implicit this in intra-TU function 
should be marked
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:31-[[@LINE-2]]:31}:" 
{{\[\[}}clang::lifetimebound]]"
 };
 const OutOfLine &OutOfLine::get() const {
-  // CHECK: :[[@LINE-1]]:40: warning: implicit this in intra-TU function 
should be marked
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:40-[[@LINE-2]]:40}:" 
{{\[\[}}clang::lifetimebound]]"
   return *this;
 }
 
diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp 
b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index 973c610eb58ab..5122e634e594f 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -46,8 +46,8 @@ inline View inline_header_return_view(View a) {  // 
expected-warning {{parameter
   return a;                                      // expected-note {{param 
returned here}}
 }
 
-View redeclared_in_header(View a);
-inline View redeclared_in_header(View a) {  // expected-warning {{parameter in 
intra-TU function should be marked [[clang::lifetimebound]]}}
+View redeclared_in_header(View a);          // expected-warning {{parameter in 
intra-TU function should be marked [[clang::lifetimebound]]}}
+inline View redeclared_in_header(View a) {
   return a;                                 // expected-note {{param returned 
here}}
 }
 
@@ -177,8 +177,8 @@ View reassigned_to_another_parameter(
   return a;       // expected-note {{param returned here}} 
 }
 
-View intra_tu_func_redecl(View a);
-View intra_tu_func_redecl(View a) {   // expected-warning {{parameter in 
intra-TU function should be marked [[clang::lifetimebound]]}}.
+View intra_tu_func_redecl(View a);    // expected-warning {{parameter in 
intra-TU function should be marked [[clang::lifetimebound]]}}.
+View intra_tu_func_redecl(View a) {
   return a;                           // expected-note {{param returned here}} 
 }
 }
@@ -282,25 +282,25 @@ MyObj* return_pointer_by_func(MyObj* a) {         // 
expected-warning {{paramete
 } // namespace correct_order_inference
 
 namespace incorrect_order_inference_view {
-View return_view_callee(View a);
+View return_view_callee(View a);      // expected-warning {{parameter in 
intra-TU function should be marked [[clang::lifetimebound]]}}.
 
 View return_view_caller(View a) {     // expected-warning {{parameter in 
intra-TU function should be marked [[clang::lifetimebound]]}}.
   return return_view_callee(a);       // expected-note {{param returned here}}
 }
 
-View return_view_callee(View a) {     // expected-warning {{parameter in 
intra-TU function should be marked [[clang::lifetimebound]]}}.
+View return_view_callee(View a) {
   return a;                           // expected-note {{param returned here}}
 }   
 } // namespace incorrect_order_inference_view
 
 namespace incorrect_order_inference_object {
-MyObj* return_object_callee(MyObj* a);
+MyObj* return_object_callee(MyObj* a);       // expected-warning {{parameter 
in intra-TU function should be marked [[clang::lifetimebound]]}}.
 
 MyObj* return_object_caller(MyObj* a) {      // expected-warning {{parameter 
in intra-TU function should be marked [[clang::lifetimebound]]}}.
   return return_object_callee(a);            // expected-note {{param returned 
here}}
 }
 
-MyObj* return_object_callee(MyObj* a) {      // expected-warning {{parameter 
in intra-TU function should be marked [[clang::lifetimebound]]}}.
+MyObj* return_object_callee(MyObj* a) {
   return a;                                  // expected-note {{param returned 
here}}
 }   
 } // namespace incorrect_order_inference_object
@@ -322,13 +322,13 @@ View inference_top_level_return_stack_view() {
 } // namespace simple_annotation_inference
 
 namespace inference_in_order_with_redecls {
-View inference_callee_return_identity(View a);
-View inference_callee_return_identity(View a) {   // expected-warning 
{{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}.
+View inference_callee_return_identity(View a);    // expected-warning 
{{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}.
+View inference_callee_return_identity(View a) {
   return a;                                       // expected-note {{param 
returned here}}
 }
 
-View inference_caller_forwards_callee(View a);
-View inference_caller_forwards_callee(View a) {   // expected-warning 
{{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}.
+View inference_caller_forwards_callee(View a);    // expected-warning 
{{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}.
+View inference_caller_forwards_callee(View a) {
   return inference_callee_return_identity(a);     // expected-note {{param 
returned here}}
 }
   

>From 8c31e0f4a28d0c2dd91d91e23fd97131f45d2808 Mon Sep 17 00:00:00 2001
From: NeKon69 <[email protected]>
Date: Wed, 20 May 2026 17:55:45 +0300
Subject: [PATCH 2/2] revert the change and warn on both crosstu declarations
 and canonical declarations

---
 clang/lib/Analysis/LifetimeSafety/Checker.cpp | 43 +++++++++++++++++--
 .../Sema/warn-lifetime-safety-suggestions.cpp |  9 ++++
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 4b9d195411179..f6b116b2d03a6 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -353,20 +353,55 @@ class LifetimeChecker {
             Scope};
   }
 
+  /// Returns the declaration of a function that is visible across translation
+  /// units, if such a declaration exists and is different from the definition.
+  static const FunctionDecl *getCrossTUDecl(const FunctionDecl &FD,
+                                            SourceManager &SM) {
+    if (!FD.isExternallyVisible())
+      return nullptr;
+    const FileID DefinitionFile = SM.getFileID(FD.getLocation());
+    for (const FunctionDecl *Redecl : FD.redecls())
+      if (SM.getFileID(Redecl->getLocation()) != DefinitionFile)
+        return Redecl;
+
+    return nullptr;
+  }
+
+  static const FunctionDecl *getCrossTUDecl(const ParmVarDecl &PVD,
+                                            SourceManager &SM) {
+    if (const auto *FD = dyn_cast<FunctionDecl>(PVD.getDeclContext()))
+      return getCrossTUDecl(*FD, SM);
+    return nullptr;
+  }
+
   void suggestWithScopeForParmVar(const ParmVarDecl *PVD,
                                   EscapingTarget EscapeTarget) {
     if (llvm::isa<const VarDecl *>(EscapeTarget))
       return;
 
-    auto [Parm, Scope] = getCanonicalDeclForAttr(cast<FunctionDecl>(FD), PVD);
-    SemaHelper->suggestLifetimeboundToParmVar(Scope, Parm, EscapeTarget);
+    auto [CanonicalPVD, Scope] =
+        getCanonicalDeclForAttr(cast<FunctionDecl>(FD), PVD);
+    const auto *CrossTUFD = getCrossTUDecl(*PVD, AST.getSourceManager());
+    const auto *CrossTUParm =
+        CrossTUFD ? CrossTUFD->getParamDecl(PVD->getFunctionScopeIndex())
+                  : nullptr;
+
+    SemaHelper->suggestLifetimeboundToParmVar(Scope, CanonicalPVD,
+                                              EscapeTarget);
+    if (CrossTUParm && CrossTUParm != CanonicalPVD)
+      SemaHelper->suggestLifetimeboundToParmVar(WarningScope::CrossTU,
+                                                CrossTUParm, EscapeTarget);
   }
 
   void suggestWithScopeForImplicitThis(const CXXMethodDecl *MD,
                                        const Expr *EscapeExpr) {
-    auto [MethodDecl, Scope] = getCanonicalDeclForAttr(MD);
-    SemaHelper->suggestLifetimeboundToImplicitThis(Scope, MethodDecl,
+    auto [CanonicalDecl, Scope] = getCanonicalDeclForAttr(MD);
+    const auto *CrossTUDecl = getCrossTUDecl(*MD, AST.getSourceManager());
+    SemaHelper->suggestLifetimeboundToImplicitThis(Scope, CanonicalDecl,
                                                    EscapeExpr);
+    if (CrossTUDecl && CrossTUDecl != CanonicalDecl)
+      SemaHelper->suggestLifetimeboundToImplicitThis(
+          WarningScope::CrossTU, cast<CXXMethodDecl>(CrossTUDecl), EscapeExpr);
   }
 
   void suggestAnnotations() {
diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp 
b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index 5122e634e594f..30d1896450236 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -31,6 +31,8 @@ struct [[gsl::Pointer()]] View {
 
 View definition_before_header(View a); // expected-warning {{parameter in 
cross-TU function should be marked [[clang::lifetimebound]]}}
 
+View redeclared_before_header_include(View a); // expected-warning {{parameter 
in cross-TU function should be marked [[clang::lifetimebound]]}}
+
 View return_view_directly(View a); // expected-warning {{parameter in cross-TU 
function should be marked [[clang::lifetimebound]]}}
 
 View conditional_return_view(
@@ -67,6 +69,9 @@ struct ReturnThisPointer {
 
 //--- test_source.cpp
 
+struct View;
+View redeclared_before_header_include(View a); // expected-warning {{parameter 
in intra-TU function should be marked [[clang::lifetimebound]]}}
+
 #include "test_header.h"
 #include "Inputs/lifetime-analysis.h"
 
@@ -74,6 +79,10 @@ View definition_before_header(View a) {
   return a;                               // expected-note {{param returned 
here}}
 }
 
+View redeclared_before_header_include(View a) {
+  return a;                               // expected-note 2 {{param returned 
here}}
+}
+
 View return_view_directly(View a) {
   return a;                             // expected-note {{param returned 
here}}
 }

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

Reply via email to