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

>From 038c9bc70f18059da3097899f5bb3639faaabb0b Mon Sep 17 00:00:00 2001
From: Kashika Akhouri <[email protected]>
Date: Wed, 17 Jun 2026 14:33:44 +0000
Subject: [PATCH 1/2] Add support for simple structs without annotation

---
 clang/lib/Analysis/LifetimeSafety/Origins.cpp |  23 +-
 clang/test/Sema/LifetimeSafety/capture-by.cpp | 362 ++++++++++++++----
 clang/test/Sema/LifetimeSafety/safety.cpp     |   7 +-
 3 files changed, 312 insertions(+), 80 deletions(-)

diff --git a/clang/lib/Analysis/LifetimeSafety/Origins.cpp 
b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
index 55d3b36e3163a..7aa188d22b781 100644
--- a/clang/lib/Analysis/LifetimeSafety/Origins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
@@ -81,9 +81,9 @@ class LifetimeAnnotatedOriginTypeCollector
     if (!FD)
       return;
     FD = getDeclWithMergedLifetimeBoundAttrs(FD);
+    const auto *MD = dyn_cast<CXXMethodDecl>(FD);
 
-    if (const auto *MD = dyn_cast<CXXMethodDecl>(FD);
-        MD && MD->isInstance() && !isa<CXXConstructorDecl>(MD) &&
+    if (MD && MD->isInstance() && !isa<CXXConstructorDecl>(MD) &&
         implicitObjectParamIsLifetimeBound(MD)) {
       CollectedTypes.push_back(RetType);
       return;
@@ -94,6 +94,25 @@ class LifetimeAnnotatedOriginTypeCollector
         CollectedTypes.push_back(RetType);
         return;
       }
+      if (auto *Attr = Param->getAttr<LifetimeCaptureByAttr>()) {
+        for (int Idx : Attr->params()) {
+          if (Idx == LifetimeCaptureByAttr::Global ||
+              Idx == LifetimeCaptureByAttr::Unknown ||
+              Idx == LifetimeCaptureByAttr::Invalid)
+            continue;
+          if (Idx == LifetimeCaptureByAttr::This) {
+            if (MD && MD->isInstance())
+              CollectedTypes.push_back(MD->getFunctionObjectParameterType());
+          } else if (int LogicalIdx =
+                         Idx -
+                         (MD && MD->isImplicitObjectMemberFunction() ? 1 : 0);
+                     LogicalIdx >= 0 &&
+                     (unsigned)LogicalIdx < FD->getNumParams()) {
+            CollectedTypes.push_back(
+                FD->getParamDecl(LogicalIdx)->getType().getNonReferenceType());
+          }
+        }
+      }
     }
   }
 };
diff --git a/clang/test/Sema/LifetimeSafety/capture-by.cpp 
b/clang/test/Sema/LifetimeSafety/capture-by.cpp
index 2877d8d6cd5f9..00571fa34d87a 100644
--- a/clang/test/Sema/LifetimeSafety/capture-by.cpp
+++ b/clang/test/Sema/LifetimeSafety/capture-by.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 --std=c++20 -fsyntax-only -verify -Wdangling-capture %s
+// RUN: %clang_cc1 --std=c++20 -fsyntax-only -Wno-dangling -verify=cfg 
-Wlifetime-safety %s
 
 #include "Inputs/lifetime-analysis.h"
 
@@ -11,13 +12,28 @@ void captureInt(const int &i 
[[clang::lifetime_capture_by(x)]], X &x);
 void captureRValInt(int &&i [[clang::lifetime_capture_by(x)]], X &x);
 void noCaptureInt(int i [[clang::lifetime_capture_by(x)]], X &x);
 
-void use() {
-  int local;
-  captureInt(1, // expected-warning {{object whose reference is captured by 
'x' will be destroyed at the end of the full-expression}}
-            x);
+void temporary_int_capture() {
+  captureInt(1,x); // expected-warning {{object whose reference is captured by 
'x' will be destroyed at the end of the full-expression}}
+                   // cfg-warning@-1 {{temporary object does not live long 
enough}}
+                   // cfg-note@-2 {{destroyed here}}
+  (void)x;         // cfg-note {{later used here}} 
   captureRValInt(1, x); // expected-warning {{object whose reference is 
captured by 'x' will be destroyed at the end of the full-expression}}
-  captureInt(local, x);
+                      // cfg-warning@-1 {{temporary object does not live long 
enough}}
+                      // cfg-note@-2 {{destroyed here}}
+( void)x;              // cfg-note {{later used here}} 
+}
+
+void local_int_capture() {
+  {
+    int local;
+    captureInt(local, x); // cfg-warning {{local variable 'local' does not 
live long enough}}
+  }                       // cfg-note {{destroyed here}}
+  (void)x;                // cfg-note {{later used here}} 
+}
+
+void safe_int_captures() {
   noCaptureInt(1, x);
+  int local;
   noCaptureInt(local, x);
 }
 } // namespace capture_int
@@ -30,12 +46,25 @@ struct X {} x;
 void captureString(const std::string &s [[clang::lifetime_capture_by(x)]], X 
&x);
 void captureRValString(std::string &&s [[clang::lifetime_capture_by(x)]], X 
&x);
 
-void use() {
-  std::string local_string;
+void temporary_string_capture() {
   captureString(std::string(), x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}}
-  captureString(local_string, x);
-  captureRValString(std::move(local_string), x);
+                                   // cfg-warning@-1 {{temporary object does 
not live long enough}}
+                                   // cfg-note@-2 {{destroyed here}}
+  (void)x;                         // cfg-note {{later used here}}
   captureRValString(std::string(), x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}}
+                                       // cfg-warning@-1 {{temporary object 
does not live long enough}}
+                                       // cfg-note@-2 {{destroyed here}}
+  (void)x;                             // cfg-note {{later used here}}   
+}
+
+void local_string_capture() {
+  {
+    std::string local_string1, local_string2;
+    captureString(local_string1, x);                // cfg-warning {{local 
variable 'local_string1' does not live long enough}}
+    captureRValString(std::move(local_string2), x); // cfg-warning {{local 
variable 'local_string2' does not live long enough}}
+                                    // cfg-note@-1 {{result of call to 
'move<std::basic_string<char> &>' aliases the storage of local variable 
'local_string2'}}
+  }                                 // cfg-note 2 {{destroyed here}}           
                      
+  (void)x;                          // cfg-note 2 {{later used here}}          
               
 }
 } // namespace capture_string
 
@@ -43,7 +72,7 @@ void use() {
 // Capture std::string_view (gsl pointer types)
 // ****************************************************************************
 namespace capture_string_view {
-struct X {} x;
+struct X {} x;   // cfg-note 2 {{this global dangles}}
 void captureStringView(std::string_view s [[clang::lifetime_capture_by(x)]], X 
&x);
 void captureRValStringView(std::string_view &&sv 
[[clang::lifetime_capture_by(x)]], X &x);
 void noCaptureStringView(std::string_view sv, X &x);
@@ -53,35 +82,80 @@ std::string_view getNotLifetimeBoundView(const std::string& 
s);
 const std::string& getLifetimeBoundString(const std::string &s 
[[clang::lifetimebound]]);
 const std::string& getLifetimeBoundString(std::string_view sv 
[[clang::lifetimebound]]);
 
-void use() {
-  std::string_view local_string_view;
-  std::string local_string;
-  captureStringView(local_string_view, x);
-  captureStringView(std::string(), // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}}
-            x);
-
-  captureStringView(getLifetimeBoundView(local_string), x);
-  captureStringView(getNotLifetimeBoundView(std::string()), x);
-  captureRValStringView(std::move(local_string_view), x);
+void temporary_string_capture() {
+  captureStringView(std::string(), x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}}
+                                       // cfg-warning@-1 {{temporary object 
does not live long enough}}
+                                       // cfg-note@-2 {{destroyed here}}
+  (void)x;                             // cfg-note {{later used here}}       
   captureRValStringView(std::string(), x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}}
-  captureRValStringView(std::string_view{"abcd"}, x);
+                                           // cfg-warning@-1 {{temporary 
object does not live long enough}}
+                                           // cfg-note@-2 {{destroyed here}}
+  (void)x;                                 // cfg-note {{later used here}}
+  captureRValStringView(std::string_view{"abcd"}, x); // cfg-warning 
{{temporary object does not live long enough}}
+                                                      // cfg-note@-1 
{{destroyed here}}
+  (void)x;                                            // cfg-note {{later used 
here}}                
+}
 
-  noCaptureStringView(local_string_view, x);
-  noCaptureStringView(std::string(), x);
+void local_string_capture() {
+  {
+    std::string local_string;
+    captureStringView(getLifetimeBoundView(local_string), x);  // cfg-warning 
{{local variable 'local_string' does not live long enough}}
+                                                               // cfg-note@-1 
{{result of call to 'getLifetimeBoundView' aliases the storage of local 
variable 'local_string'}}
+  }                                                            // cfg-note 
{{destroyed here}}
+  (void)x;      // cfg-note {{later used here}}
+  std::string_view local_string_view;
+  captureRValStringView(std::move(local_string_view), x); // cfg-warning 
{{stack memory associated with local variable 'local_string_view' escapes to 
the global variable 'x' which will dangle}}
+}
 
-  // With lifetimebound functions.
-  captureStringView(getLifetimeBoundView(
-  std::string() // expected-warning {{object whose reference is captured by 
'x' will be destroyed at the end of the full-expression}}
-  ), x);
-  captureRValStringView(getLifetimeBoundView(local_string), x);
+// Lifetimebound captures
+void temporary_string_view_lifetimebound_capture() {
+  captureStringView(getLifetimeBoundView( // cfg-note {{result of call to 
'getLifetimeBoundView' aliases the storage of temporary object}}
+  std::string()                           // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}}
+  ), x);                                  // cfg-warning@-1 {{temporary object 
does not live long enough}}
+                                          // cfg-note@-1 {{destroyed here}}
+  (void)x;                                // cfg-note {{later used here}}
+  captureStringView(getLifetimeBoundString(std::string()), x);   // 
expected-warning {{object whose reference is captured by 'x' will be destroyed 
at the end of the full-expression}}
+                                                                 // 
cfg-warning@-1 {{temporary object does not live long enough}}
+                                                                 // 
cfg-note@-2 {{destroyed here}}
+                                                                 // 
cfg-note@-3 {{result of call to 'getLifetimeBoundString' aliases the storage of 
temporary object}}
+  (void)x;                                                       // cfg-note 
{{later used here}}
   captureRValStringView(getLifetimeBoundView(std::string()), x); // 
expected-warning {{object whose reference is captured by 'x' will be destroyed 
at the end of the full-expression}}
-  captureRValStringView(getNotLifetimeBoundView(std::string()), x);
-  noCaptureStringView(getLifetimeBoundView(std::string()), x);
-  captureStringView(getLifetimeBoundString(std::string()), x); // 
expected-warning {{object whose reference is captured by 'x' will be destroyed 
at the end of the full-expression}}
+                                                                 // 
cfg-warning@-1 {{temporary object does not live long enough}}
+                                                                 // 
cfg-note@-2 {{destroyed here}}
+  (void)x;                                                       // cfg-note 
{{later used here}}                                                             
  
+  captureRValStringView(getNotLifetimeBoundView(std::string()), x);  // 
cfg-warning {{stack memory associated with temporary object escapes to the 
global variable 'x' which will dangle}}
+}
+
+void local_string_lifetimebound_capture() {
+ {
+    std::string local_string;
+    captureRValStringView(getLifetimeBoundView(local_string), x); // 
cfg-warning {{temporary object does not live long enough}}
+                                                                  // 
cfg-note@-1 {{destroyed here}}
+ }
+ (void)x;                                                         // cfg-note 
{{later used here}}
+}
+
+void temporary_nested_lifetimebound_capture() {
   
captureStringView(getLifetimeBoundString(getLifetimeBoundView(std::string())), 
x); // expected-warning {{object whose reference is captured by 'x' will be 
destroyed at the end of the full-expression}}
-  captureStringView(getLifetimeBoundString(getLifetimeBoundString(
+                                                                               
      // cfg-warning@-1 {{temporary object does not live long enough}}
+                                                                               
      // cfg-note@-2 {{destroyed here}}
+                                                                               
      // cfg-note@-3 {{result of call to 'getLifetimeBoundView' aliases the 
storage of temporary object}}
+                                                                               
      // cfg-note@-4 {{result of call to 'getLifetimeBoundString' aliases the 
storage of temporary object}}
+  (void)x;                                                                     
      // cfg-note {{later used here}}
+  captureStringView(getLifetimeBoundString(getLifetimeBoundString(             
      // cfg-note 2 {{result of call to 'getLifetimeBoundString' aliases the 
storage of temporary object}}
     std::string()  // expected-warning {{object whose reference is captured by 
'x' will be destroyed at the end of the full-expression}}
-    )), x);
+    )), x);        // cfg-warning@-1 {{temporary object does not live long 
enough}}
+                   // cfg-note@-1 {{destroyed here}}
+  (void)x;         // cfg-note {{later used here}}
+}
+
+void safe_captures() {
+  std::string_view local_string_view;
+  captureStringView(local_string_view, x);
+  captureStringView(getNotLifetimeBoundView(std::string()), x);
+  noCaptureStringView(local_string_view, x);
+  noCaptureStringView(std::string(), x);
+  noCaptureStringView(getLifetimeBoundView(std::string()), x);
 }
 } // namespace capture_string_view
 
@@ -92,15 +166,25 @@ const std::string* getLifetimeBoundPointer(const 
std::string &s [[clang::lifetim
 const std::string* getNotLifetimeBoundPointer(const std::string &s);
 
 namespace capture_pointer {
-struct X {} x;
+struct X {} x;   // cfg-note {{this global dangles}}
 void capturePointer(const std::string* sp [[clang::lifetime_capture_by(x)]], X 
&x);
-void use() {
+
+void temporary_pointer_lifetimebound_capture() {
   capturePointer(getLifetimeBoundPointer(std::string()), x); // 
expected-warning {{object whose reference is captured by 'x' will be destroyed 
at the end of the full-expression}}
+                                                             // cfg-warning@-1 
{{temporary object does not live long enough}}
+                                                             // cfg-note@-2 
{{destroyed here}}
+                                                             // cfg-note@-3 
{{result of call to 'getLifetimeBoundPointer' aliases the storage of temporary 
object}}
+  (void)x;                                                   // cfg-note 
{{later used here}}
+}
+
+void temporary_nested_lifetimebound_capture() {
   capturePointer(getLifetimeBoundPointer(*getLifetimeBoundPointer(
     std::string()  // expected-warning {{object whose reference is captured by 
'x' will be destroyed at the end of the full-expression}}
-    )), x);
-  capturePointer(getNotLifetimeBoundPointer(std::string()), x);
+    )), x);        // cfg-warning@-1 {{stack memory associated with temporary 
object escapes to the global variable 'x' which will dangle}}
+}
 
+void safe_capture() {
+  capturePointer(getNotLifetimeBoundPointer(std::string()), x);
 }
 } // namespace capture_pointer
 
@@ -108,23 +192,41 @@ void use() {
 // Arrays and initializer lists.
 // ****************************************************************************
 namespace init_lists {
-struct X {} x;
+struct X {} x;    // cfg-note {{this global dangles}}
 void captureVector(const std::vector<int> &a 
[[clang::lifetime_capture_by(x)]], X &x);
 void captureArray(int array [[clang::lifetime_capture_by(x)]] [2], X &x);
 void captureInitList(std::initializer_list<int> abc 
[[clang::lifetime_capture_by(x)]], X &x);
 
-
 std::initializer_list<int> getLifetimeBoundInitList(std::initializer_list<int> 
abc [[clang::lifetimebound]]);
 
-void use() {
+void temporary_vector_capture() {
   captureVector({1, 2, 3}, x); // expected-warning {{object whose reference is 
captured by 'x' will be destroyed at the end of the full-expression}}
+                               // cfg-warning@-1 {{temporary object does not 
live long enough}}
+                               // cfg-note@-2 {{destroyed here}}
+  (void)x;                     // cfg-note {{later used here}}       
   captureVector(std::vector<int>{}, x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}}
-  std::vector<int> local_vector;
-  captureVector(local_vector, x);
+                                        // cfg-warning@-1 {{temporary object 
does not live long enough}}
+                                        // cfg-note@-2 {{destroyed here}}
+  (void)x;                              // cfg-note {{later used here}}        
+}
+
+void local_vector_capture() {
+  {
+    std::vector<int> local_vector;
+    captureVector(local_vector, x);    // cfg-warning {{local variable 
'local_vector' does not live long enough}}
+  }                                    // cfg-note {{destroyed here}}
+  (void)x;                             // cfg-note {{later used here}}
+}
+
+void local_array_capture() {
   int local_array[2]; 
-  captureArray(local_array, x);
-  captureInitList({1, 2}, x); // expected-warning {{object whose reference is 
captured by 'x' will be destroyed at the end of the full-expression}}
-  captureInitList(getLifetimeBoundInitList({1, 2}), x); // expected-warning 
{{object whose reference is captured by 'x' will be destroyed at the end of the 
full-expression}}
+  captureArray(local_array, x);      // cfg-warning {{stack memory associated 
with local variable 'local_array' escapes to the global variable 'x' which will 
dangle}}
+}
+
+// FIXME: Add support for initializer lists in -Wlifetime-safety
+void initializer_list_capture() {
+  captureInitList({1, 2}, x); // expected-warning {{object whose reference is 
captured by 'x' will be destroyed at the end of the full-expression}}         
+  captureInitList(getLifetimeBoundInitList({1, 2}), x); // expected-warning 
{{object whose reference is captured by 'x' will be destroyed at the end of the 
full-expression}}                                     
 }
 } // namespace init_lists
 
@@ -136,6 +238,8 @@ struct X {} x;
 struct S {
   void capture(X &x) [[clang::lifetime_capture_by(x)]];
 };
+
+// FIXME: Add support for capture of method declarations in -Wlifetime-safety
 void use() {
   S{}.capture(x); // expected-warning {{object whose reference is captured by 
'x' will be destroyed at the end of the full-expression}}
   S s;
@@ -166,6 +270,7 @@ void captureByUnknown(std::string_view s 
[[clang::lifetime_capture_by(unknown)]]
 
 std::string_view getLifetimeBoundView(const std::string& s 
[[clang::lifetimebound]]);
 
+// FIXME: Add support for capture by global and unknown in -Wlifetime-safety
 void use() {  
   std::string_view local_string_view;
   std::string local_string;
@@ -195,12 +300,30 @@ std::string_view getLifetimeBoundView(const std::string& 
s [[clang::lifetimeboun
 std::string_view getNotLifetimeBoundView(const std::string& s);
 const std::string& getLifetimeBoundString(const std::string &s 
[[clang::lifetimebound]]);
 
-void use() {
+void temporary_capture_by_this() {
   S s;
   s.captureInt(1); // expected-warning {{object whose reference is captured by 
's' will be destroyed at the end of the full-expression}}
+                   // cfg-warning@-1 {{temporary object does not live long 
enough}}
+                   // cfg-note@-2 {{destroyed here}}
+  (void)s;         // cfg-note {{later used here}}       
   s.captureView(std::string()); // expected-warning {{object whose reference 
is captured by 's' will be destroyed at the end of the full-expression}}
-  s.captureView(getLifetimeBoundView(std::string())); // expected-warning 
{{object whose reference is captured by 's' will be destroyed at the end of the 
full-expression}}
+                                // cfg-warning@-1 {{temporary object does not 
live long enough}}
+                                // cfg-note@-2 {{destroyed here}}
+  (void)s;                      // cfg-note {{later used here}}                
              
+}
+
+void lifetimebound_capture_by_this() {
+  S s;
+  s.captureView(getLifetimeBoundView(std::string()));    // expected-warning 
{{object whose reference is captured by 's' will be destroyed at the end of the 
full-expression}}
+                                                         // cfg-warning@-1 
{{temporary object does not live long enough}}
+                                                         // cfg-note@-2 
{{destroyed here}}
+                                                         // cfg-note@-3 
{{esult of call to 'getLifetimeBoundView' aliases the storage of temporary 
object}}
+  (void)s;                                               // cfg-note {{later 
used here}}         
   s.captureView(getLifetimeBoundString(std::string()));  // expected-warning 
{{object whose reference is captured by 's' will be destroyed at the end of the 
full-expression}}
+                                                         // cfg-warning@-1 
{{temporary object does not live long enough}}
+                                                         // cfg-note@-2 
{{destroyed here}}
+                                                         // cfg-note@-3 
{{result of call to 'getLifetimeBoundString' aliases the storage of temporary 
object}}
+  (void)s;                                               // cfg-note {{later 
used here}}        
   s.captureView(getNotLifetimeBoundView(std::string()));
 }  
 } // namespace capture_by_this
@@ -254,9 +377,18 @@ struct MySet {
 void user_defined_containers() {
   MySet<int> set_of_int;
   set_of_int.insert(1); // expected-warning {{object whose reference is 
captured by 'set_of_int' will be destroyed at the end of the full-expression}}
+                        // cfg-warning@-1 {{temporary object does not live 
long enough}}
+                        // cfg-note@-2 {{destroyed here}}
+  (void)set_of_int;     // cfg-note {{later used here}}                   
   MySet<std::string_view> set_of_sv;
-  set_of_sv.insert(std::string());  // expected-warning {{object whose 
reference is captured by 'set_of_sv' will be destroyed at the end of the 
full-expression}}
-  set_of_sv.insert(std::string_view());
+  set_of_sv.insert(std::string());       // expected-warning {{object whose 
reference is captured by 'set_of_sv' will be destroyed at the end of the 
full-expression}}
+                                         // cfg-warning@-1 {{temporary object 
does not live long enough}}
+                                         // cfg-note@-2 {{destroyed here}}
+  (void)set_of_sv;                       // cfg-note {{later used here}}       
         
+  set_of_sv.insert(std::string_view());  // cfg-warning {{temporary object 
does not live long enough}}
+                                         // cfg-note@-1 {{destroyed here}}
+  (void)set_of_sv;                       // cfg-note {{later used here}}       
                                             
+                                    
 }
 } // namespace containers_no_distinction
 
@@ -286,13 +418,29 @@ void use_container() {
   
   MyVector<std::string_view> vector_of_view;
   vector_of_view.push_back(std::string()); // expected-warning {{object whose 
reference is captured by 'vector_of_view' will be destroyed at the end of the 
full-expression}}
+                                           // cfg-warning@-1 {{temporary 
object does not live long enough}}
+                                           // cfg-note@-2 {{destroyed here}}
+  (void)vector_of_view;                    // cfg-note {{later used here}}
   vector_of_view.push_back(getLifetimeBoundView(std::string())); // 
expected-warning {{object whose reference is captured by 'vector_of_view' will 
be destroyed at the end of the full-expression}}
-  
+                                                                 // 
cfg-warning@-1 {{temporary object does not live long enough}}
+                                                                 // 
cfg-note@-2 {{destroyed here}}
+  (void)vector_of_view;                                          // cfg-note 
{{later used here}}
+
   MyVector<const std::string*> vector_of_pointer;
   vector_of_pointer.push_back(getLifetimeBoundPointer(std::string())); // 
expected-warning {{object whose reference is captured by 'vector_of_pointer' 
will be destroyed at the end of the full-expression}}
+                                                                       // 
cfg-warning@-1 {{temporary object does not live long enough}}
+                                                                       // 
cfg-note@-2 {{destroyed here}}
+  (void)vector_of_pointer;                                             // 
cfg-note {{later used here}}
   
vector_of_pointer.push_back(getLifetimeBoundPointer(*getLifetimeBoundPointer(std::string())));
 // expected-warning {{object whose reference is captured by 
'vector_of_pointer' will be destroyed at the end of the full-expression}}
-  vector_of_pointer.push_back(getLifetimeBoundPointer(local));
-  vector_of_pointer.push_back(getNotLifetimeBoundPointer(std::string()));
+                                                                               
                  // cfg-warning@-1 {{temporary object does not live long 
enough}}
+                                                                               
                  // cfg-note@-2 {{destroyed here}}
+  (void)vector_of_pointer;                                                     
                  // cfg-note {{later used here}}
+  vector_of_pointer.push_back(getLifetimeBoundPointer(local));              // 
cfg-warning {{temporary object does not live long enough}}
+                                                                            // 
cfg-note@-1 {{destroyed here}}
+  (void)vector_of_pointer;                                                  // 
cfg-note {{later used here}}
+  vector_of_pointer.push_back(getNotLifetimeBoundPointer(std::string()));   // 
cfg-warning {{temporary object does not live long enough}}
+                                                                            // 
cfg-note@-1 {{destroyed here}}
+  (void)vector_of_pointer;                                                  // 
cfg-note {{later used here}}
 }
 
 // ****************************************************************************
@@ -323,18 +471,38 @@ const std::string& 
getLifetimeBoundString(std::string_view sv [[clang::lifetimeb
 void use_my_view() {
   std::string local;
   MyVector<MyStringView> vector_of_my_view;
-  vector_of_my_view.push_back(getMySV());
-  vector_of_my_view.push_back(MyStringView{});
-  vector_of_my_view.push_back(std::string_view{});
-  vector_of_my_view.push_back(std::string{}); // expected-warning {{object 
whose reference is captured by 'vector_of_my_view' will be destroyed at the end 
of the full-expression}}
+  vector_of_my_view.push_back(getMySV());           // cfg-warning {{temporary 
object does not live long enough}}
+                                                    // cfg-note@-1 {{destroyed 
here}}
+  (void)vector_of_my_view;                          // cfg-note {{later used 
here}}
+  vector_of_my_view.push_back(MyStringView{});      // cfg-warning {{temporary 
object does not live long enough}}
+                                                    // cfg-note@-1 {{destroyed 
here}}
+  (void)vector_of_my_view;                          // cfg-note {{later used 
here}}
+  vector_of_my_view.push_back(std::string_view{});  // cfg-warning {{temporary 
object does not live long enough}}
+                                                    // cfg-note@-1 {{destroyed 
here}}
+  (void)vector_of_my_view;                          // cfg-note {{later used 
here}}
+  vector_of_my_view.push_back(std::string{});       // expected-warning 
{{object whose reference is captured by 'vector_of_my_view' will be destroyed 
at the end of the full-expression}}
+                                                    // cfg-warning@-1 
{{temporary object does not live long enough}}
+                                                    // cfg-note@-2 {{destroyed 
here}}
+  (void)vector_of_my_view;                          // cfg-note {{later used 
here}}                                            
   vector_of_my_view.push_back(getLifetimeBoundView(std::string{})); // 
expected-warning {{object whose reference is captured by 'vector_of_my_view' 
will be destroyed at the end of the full-expression}}
+                                                    // cfg-warning@-1 
{{temporary object does not live long enough}}
+                                                    // cfg-note@-2 {{destroyed 
here}}
+  (void)vector_of_my_view;                          // cfg-note {{later used 
here}}                                                   
   
vector_of_my_view.push_back(getLifetimeBoundString(getLifetimeBoundView(std::string{})));
 // expected-warning {{object whose reference is captured by 
'vector_of_my_view' will be destroyed at the end of the full-expression}}
-  
vector_of_my_view.push_back(getNotLifetimeBoundView(getLifetimeBoundString(getLifetimeBoundView(std::string{}))));
+                                                    // cfg-warning@-1 
{{temporary object does not live long enough}}
+                                                    // cfg-note@-2 {{destroyed 
here}}
+  (void)vector_of_my_view;                          // cfg-note {{later used 
here}}                                                    
+  
vector_of_my_view.push_back(getNotLifetimeBoundView(getLifetimeBoundString(getLifetimeBoundView(std::string{}))));
 // cfg-warning {{temporary object does not live long enough}}
+                                                    // cfg-note@-1 {{destroyed 
here}}
+  (void)vector_of_my_view;                          // cfg-note {{later used 
here}}       
   
   // Use with container of other view types.
   MyVector<std::string_view> vector_of_view;
-  vector_of_view.push_back(getMySV());
+  vector_of_view.push_back(getMySV());              // cfg-warning {{temporary 
object does not live long enough}}
+                                                    // cfg-note@-1 {{destroyed 
here}}
+  (void)vector_of_view;                             // cfg-note {{later used 
here}}
   vector_of_view.push_back(getMySVNotP());
+  (void)vector_of_view;
 }
 
 // ****************************************************************************
@@ -345,10 +513,18 @@ void use_with_optional_view() {
 
   std::optional<std::string_view> optional_of_view;
   vector_of_view.push_back(optional_of_view.value());
-  vector_of_view.push_back(getOptionalS().value()); // expected-warning 
{{object whose reference is captured by 'vector_of_view' will be destroyed at 
the end of the full-expression}}
-  
-  vector_of_view.push_back(getOptionalSV().value());
-  vector_of_view.push_back(getOptionalMySV().value());
+  vector_of_view.push_back(getOptionalS().value());      // expected-warning 
{{object whose reference is captured by 'vector_of_view' will be destroyed at 
the end of the full-expression}}
+                                                         // cfg-warning@-1 
{{temporary object does not live long enough}}
+                                                         // cfg-note@-2 
{{destroyed here}}                                                         
+  (void)vector_of_view;                                  // cfg-note {{later 
used here}}  
+  vector_of_view.push_back(getOptionalSV().value());     // cfg-warning 
{{temporary object does not live long enough}}
+                                                         // cfg-note@-1 
{{destroyed here}}
+                                                         // cfg-note@-2 
{{result of call to 'value' aliases the storage of temporary object}}
+  (void)vector_of_view;                                  // cfg-note {{later 
used here}}  
+  vector_of_view.push_back(getOptionalMySV().value());   // cfg-warning 
{{temporary object does not live long enough}}
+                                                         // cfg-note@-1 
{{destroyed here}}
+                                                         // cfg-note@-2 
{{result of call to 'value' aliases the storage of temporary object}}
+  (void)vector_of_view;                                  // cfg-note {{later 
used here}}  
   vector_of_view.push_back(getOptionalMySVNotP().value());
 }
 } // namespace conatiners_with_different
@@ -367,17 +543,30 @@ void capture3(const std::string_view& s 
[[clang::lifetime_capture_by(x)]], std::
 void use() {
   std::vector<std::string_view> x1;
   capture1(std::string(), x1); // expected-warning {{object whose reference is 
captured by 'x1' will be destroyed at the end of the full-expression}}
+                               // cfg-warning@-1 {{temporary object does not 
live long enough}}
+                               // cfg-note@-2 {{destroyed here}}
+  (void)x1;                    // cfg-note {{later used here}}
   capture1(std::string_view(), x1);
 
   std::vector<std::string_view*> x2;
   // Clang considers 'const std::string_view&' to refer to the owner
   // 'std::string' and not 'std::string_view'. Therefore no diagnostic here.
-  capture2(std::string_view(), x2);
-  capture2(std::string(), x2); // expected-warning {{object whose reference is 
captured by 'x2' will be destroyed at the end of the full-expression}}
+  capture2(std::string_view(), x2);  // cfg-warning {{temporary object does 
not live long enough}} 
+                                     // cfg-note@-1 {{destroyed here}}
+  (void)x2;                          // cfg-note {{later used here}}
+  capture2(std::string(), x2);       // expected-warning {{object whose 
reference is captured by 'x2' will be destroyed at the end of the 
full-expression}}
+                                     // cfg-warning@-1 {{temporary object does 
not live long enough}} 
+                                     // cfg-note@-2 {{destroyed here}}
+  (void)x2;                          // cfg-note {{later used here}}
   
   std::vector<std::string_view> x3;
-  capture3(std::string_view(), x3);
-  capture3(std::string(), x3); // expected-warning {{object whose reference is 
captured by 'x3' will be destroyed at the end of the full-expression}}
+  capture3(std::string_view(), x3);  // cfg-warning {{temporary object does 
not live long enough}} 
+                                     // cfg-note@-1 {{destroyed here}}
+  (void)x3;                          // cfg-note {{later used here}}           
+  capture3(std::string(), x3);       // expected-warning {{object whose 
reference is captured by 'x3' will be destroyed at the end of the 
full-expression}}
+                                     // cfg-warning@-1 {{temporary object does 
not live long enough}} 
+                                     // cfg-note@-2 {{destroyed here}}
+  (void)x3;                          // cfg-note {{later used here}}       
 }
 } // namespace temporary_views
 
@@ -391,15 +580,32 @@ const std::string* getNotLifetimeBoundPointer(const 
std::string &s);
 std::string_view getLifetimeBoundView(const std::string& s 
[[clang::lifetimebound]]);
 std::string_view getNotLifetimeBoundView(const std::string& s);
 void use() {
-  std::string local;
   std::vector<std::string_view> views;
   views.push_back(std::string()); // expected-warning {{object whose reference 
is captured by 'views' will be destroyed at the end of the full-expression}}
+                                  // cfg-warning@-1 {{temporary object does 
not live long enough}}
+                                  // cfg-note@-2 {{destroyed here}}
+  (void)views;                    // cfg-note {{later used here}}             
   views.insert(views.begin(), 
-            std::string()); // expected-warning {{object whose reference is 
captured by 'views' will be destroyed at the end of the full-expression}}
-  views.push_back(getLifetimeBoundView(std::string())); // expected-warning 
{{object whose reference is captured by 'views' will be destroyed at the end of 
the full-expression}}
-  views.push_back(getNotLifetimeBoundView(std::string()));
-  views.push_back(local);
-  views.insert(views.end(), local);
+            std::string());       // expected-warning {{object whose reference 
is captured by 'views' will be destroyed at the end of the full-expression}}
+                                  // cfg-warning@-1 {{temporary object does 
not live long enough}}
+                                  // cfg-note@-2 {{destroyed here}}
+  (void)views;                    // cfg-note {{later used here}}              
               
+  views.push_back(getLifetimeBoundView(std::string()));    // expected-warning 
{{object whose reference is captured by 'views' will be destroyed at the end of 
the full-expression}}
+                                                           // cfg-warning@-1 
{{temporary object does not live long enough}}
+                                                           // cfg-note@-2 
{{destroyed here}}
+  (void)views;                                             // cfg-note {{later 
used here}}                                                             
+  views.push_back(getNotLifetimeBoundView(std::string())); // cfg-warning 
{{temporary object does not live long enough}}
+                                                           // cfg-note@-1 
{{destroyed here}}
+  (void)views;                                             // cfg-note {{later 
used here}}  
+  {
+      std::string local1, local2;
+      views.push_back(local1);            // cfg-warning {{temporary object 
does not live long enough}}
+                                          // cfg-note@-1 {{destroyed here}}
+      (void)views;                        // cfg-note {{later used here}}      
        
+      views.insert(views.end(), local2);  // cfg-warning {{temporary object 
does not live long enough}}
+                                          // cfg-note@-1 {{destroyed here}}
+  }                                       
+  (void)views;                            // cfg-note {{later used here}}
 
   std::vector<std::string> strings;
   strings.push_back(std::string());
@@ -407,6 +613,7 @@ void use() {
 
   std::vector<const std::string*> pointers;
   pointers.push_back(getLifetimeBoundPointer(std::string()));
+  std::string local;
   pointers.push_back(&local);
 }
 
@@ -420,8 +627,15 @@ struct [[gsl::Pointer]] Span {
 void use() {
   std::vector<Span<int>> spans;
   spans.push_back(std::vector<int>{1, 2, 3}); // expected-warning {{object 
whose reference is captured by 'spans' will be destroyed at the end of the 
full-expression}}
-  std::vector<int> local;
-  spans.push_back(local);
+                                              // cfg-warning@-1 {{temporary 
object does not live long enough}}
+                                              // cfg-note@-2 {{destroyed here}}
+  (void)spans;                                // cfg-note {{later used here}}  
                                  
+  {
+    std::vector<int> local;
+    spans.push_back(local);    // cfg-warning {{temporary object does not live 
long enough}}
+                               // cfg-note@-1 {{destroyed here}}
+  }                            
+  (void)spans;                 // cfg-note {{later used here}} 
 }
 } // namespace with_span
 } // namespace inferred_capture_by
diff --git a/clang/test/Sema/LifetimeSafety/safety.cpp 
b/clang/test/Sema/LifetimeSafety/safety.cpp
index c838918eb556d..372eb48fdca6c 100644
--- a/clang/test/Sema/LifetimeSafety/safety.cpp
+++ b/clang/test/Sema/LifetimeSafety/safety.cpp
@@ -3644,7 +3644,6 @@ void member_capture() {
   (void)c.stored;   // expected-note {{later used here}}
 }
 
-// FIXME: Add support for simple containers without annotations.
 struct SimpleContainer {
   View stored;
   void set(View s [[clang::lifetime_capture_by(this)]]);
@@ -3654,9 +3653,9 @@ void member_capture_simple_container() {
   SimpleContainer c;
   {
     MyObj local;
-    c.set(local);   
-  }                 
-  (void)c.stored;   
+    c.set(local);   // expected-warning {{local variable 'local' does not live 
long enough}}
+  }                 // expected-note {{destroyed here}}   
+  (void)c.stored;   // expected-note {{later used here}}
 }
 
 void captureTwo(View& into, 

>From 3eb0b54a7a0d41b72b96bf51d25d9a402c557a1a Mon Sep 17 00:00:00 2001
From: Kashika Akhouri <[email protected]>
Date: Tue, 30 Jun 2026 16:50:08 +0000
Subject: [PATCH 2/2] Resolve false positives

---
 .../LifetimeSafety/FactsGenerator.cpp         |  24 +-
 clang/lib/Analysis/LifetimeSafety/Origins.cpp |  26 +-
 clang/test/Sema/LifetimeSafety/capture-by.cpp | 360 +++++++++---------
 3 files changed, 213 insertions(+), 197 deletions(-)

diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp 
b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 9fbfaf8ae606b..3f1d9842f951d 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -896,28 +896,34 @@ void FactsGenerator::handleLifetimeCaptureBy(const 
FunctionDecl *FD,
   const auto *Method = dyn_cast<CXXMethodDecl>(FD);
   bool IsInstance =
       Method && Method->isInstance() && !isa<CXXConstructorDecl>(FD);
-  auto getArgCaptureBy = [FD,
-                          IsInstance](unsigned I) -> LifetimeCaptureByAttr * {
-    const ParmVarDecl *PVD = nullptr;
+  auto getParamDeclAt = [FD, IsInstance](unsigned I) -> const ParmVarDecl * {
     if (IsInstance) {
       // FIXME: Add support for I == 0 i.e. capture_by on function declarations
       if (I > 0 && I - 1 < FD->getNumParams())
-        PVD = FD->getParamDecl(I - 1);
+        return FD->getParamDecl(I - 1);
     } else {
       if (I < FD->getNumParams())
-        PVD = FD->getParamDecl(I);
+        return FD->getParamDecl(I);
     }
-    return PVD ? PVD->getAttr<LifetimeCaptureByAttr>() : nullptr;
+    return nullptr;
   };
   for (unsigned I = 0; I < Args.size(); ++I) {
-    const LifetimeCaptureByAttr *Attr = getArgCaptureBy(I);
+    const ParmVarDecl *PVD = getParamDeclAt(I);
+    if (!PVD)
+      continue;
+    const auto *Attr = PVD->getAttr<LifetimeCaptureByAttr>();
     if (!Attr)
       continue;
     OriginList *CapturedOriginList = getOriginsList(*Args[I]);
     if (!CapturedOriginList)
       continue;
-    if (!CapturedOriginList)
-      continue;
+    if (QualType ParamType = PVD->getType();
+        ParamType->isReferenceType() &&
+        isGslPointerType(ParamType->getPointeeType())) {
+      if (CapturedOriginList->getLength() > 1) {
+        CapturedOriginList = CapturedOriginList->peelOuterOrigin();
+      }
+    }
     for (int CapturingArgIdx : Attr->params()) {
       // FIXME: Add support for capturing to Global/unknown.
       if (CapturingArgIdx == LifetimeCaptureByAttr::Global ||
diff --git a/clang/lib/Analysis/LifetimeSafety/Origins.cpp 
b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
index 7aa188d22b781..f3248bdf3ba8e 100644
--- a/clang/lib/Analysis/LifetimeSafety/Origins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
@@ -57,13 +57,16 @@ class LifetimeAnnotatedOriginTypeCollector
   bool VisitCallExpr(const CallExpr *CE) {
     // Indirect calls (e.g., function pointers) are skipped because lifetime
     // annotations currently apply to declarations, not types.
-    if (const auto *FD = CE->getDirectCallee())
+    if (const auto *FD = CE->getDirectCallee()) {
       collect(FD, FD->getReturnType());
+      collectCaptureBy(FD);
+    }
     return true;
   }
 
   bool VisitCXXConstructExpr(const CXXConstructExpr *CCE) {
     collect(CCE->getConstructor(), CCE->getType());
+    collectCaptureBy(CCE->getConstructor());
     return true;
   }
 
@@ -81,9 +84,9 @@ class LifetimeAnnotatedOriginTypeCollector
     if (!FD)
       return;
     FD = getDeclWithMergedLifetimeBoundAttrs(FD);
-    const auto *MD = dyn_cast<CXXMethodDecl>(FD);
 
-    if (MD && MD->isInstance() && !isa<CXXConstructorDecl>(MD) &&
+    if (const auto *MD = dyn_cast<CXXMethodDecl>(FD);
+        MD && MD->isInstance() && !isa<CXXConstructorDecl>(MD) &&
         implicitObjectParamIsLifetimeBound(MD)) {
       CollectedTypes.push_back(RetType);
       return;
@@ -94,6 +97,17 @@ class LifetimeAnnotatedOriginTypeCollector
         CollectedTypes.push_back(RetType);
         return;
       }
+    }
+  }
+
+  void collectCaptureBy(const FunctionDecl *FD) {
+    if (!FD)
+      return;
+    FD = getDeclWithMergedLifetimeBoundAttrs(FD);
+    const auto *MD = dyn_cast<CXXMethodDecl>(FD);
+    bool IsInstance = MD && MD->isInstance();
+    int Offset = (MD && MD->isImplicitObjectMemberFunction()) ? 1 : 0;
+    for (const auto *Param : FD->parameters()) {
       if (auto *Attr = Param->getAttr<LifetimeCaptureByAttr>()) {
         for (int Idx : Attr->params()) {
           if (Idx == LifetimeCaptureByAttr::Global ||
@@ -101,11 +115,9 @@ class LifetimeAnnotatedOriginTypeCollector
               Idx == LifetimeCaptureByAttr::Invalid)
             continue;
           if (Idx == LifetimeCaptureByAttr::This) {
-            if (MD && MD->isInstance())
+            if (IsInstance)
               CollectedTypes.push_back(MD->getFunctionObjectParameterType());
-          } else if (int LogicalIdx =
-                         Idx -
-                         (MD && MD->isImplicitObjectMemberFunction() ? 1 : 0);
+          } else if (int LogicalIdx = Idx - Offset;
                      LogicalIdx >= 0 &&
                      (unsigned)LogicalIdx < FD->getNumParams()) {
             CollectedTypes.push_back(
diff --git a/clang/test/Sema/LifetimeSafety/capture-by.cpp 
b/clang/test/Sema/LifetimeSafety/capture-by.cpp
index 00571fa34d87a..05f3f6144b8a8 100644
--- a/clang/test/Sema/LifetimeSafety/capture-by.cpp
+++ b/clang/test/Sema/LifetimeSafety/capture-by.cpp
@@ -13,14 +13,14 @@ void captureRValInt(int &&i 
[[clang::lifetime_capture_by(x)]], X &x);
 void noCaptureInt(int i [[clang::lifetime_capture_by(x)]], X &x);
 
 void temporary_int_capture() {
-  captureInt(1,x); // expected-warning {{object whose reference is captured by 
'x' will be destroyed at the end of the full-expression}}
-                   // cfg-warning@-1 {{temporary object does not live long 
enough}}
-                   // cfg-note@-2 {{destroyed here}}
+  captureInt(1,x); // expected-warning {{object whose reference is captured by 
'x' will be destroyed at the end of the full-expression}} \
+                   // cfg-warning {{temporary object does not live long 
enough}} \
+                   // cfg-note {{destroyed here}}
   (void)x;         // cfg-note {{later used here}} 
-  captureRValInt(1, x); // expected-warning {{object whose reference is 
captured by 'x' will be destroyed at the end of the full-expression}}
-                      // cfg-warning@-1 {{temporary object does not live long 
enough}}
-                      // cfg-note@-2 {{destroyed here}}
-( void)x;              // cfg-note {{later used here}} 
+  captureRValInt(1, x); // expected-warning {{object whose reference is 
captured by 'x' will be destroyed at the end of the full-expression}} \
+                        // cfg-warning {{temporary object does not live long 
enough}} \
+                        // cfg-note {{destroyed here}}
+( void)x;               // cfg-note {{later used here}} 
 }
 
 void local_int_capture() {
@@ -45,15 +45,16 @@ namespace capture_string {
 struct X {} x;
 void captureString(const std::string &s [[clang::lifetime_capture_by(x)]], X 
&x);
 void captureRValString(std::string &&s [[clang::lifetime_capture_by(x)]], X 
&x);
+void noCaptureString(std::string s [[clang::lifetime_capture_by(x)]], X &x);
 
 void temporary_string_capture() {
-  captureString(std::string(), x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}}
-                                   // cfg-warning@-1 {{temporary object does 
not live long enough}}
-                                   // cfg-note@-2 {{destroyed here}}
+  captureString(std::string(), x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}} \
+                                   // cfg-warning {{temporary object does not 
live long enough}} \
+                                   // cfg-note {{destroyed here}}
   (void)x;                         // cfg-note {{later used here}}
-  captureRValString(std::string(), x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}}
-                                       // cfg-warning@-1 {{temporary object 
does not live long enough}}
-                                       // cfg-note@-2 {{destroyed here}}
+  captureRValString(std::string(), x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}} \
+                                       // cfg-warning {{temporary object does 
not live long enough}} \
+                                       // cfg-note {{destroyed here}}
   (void)x;                             // cfg-note {{later used here}}   
 }
 
@@ -61,18 +62,24 @@ void local_string_capture() {
   {
     std::string local_string1, local_string2;
     captureString(local_string1, x);                // cfg-warning {{local 
variable 'local_string1' does not live long enough}}
-    captureRValString(std::move(local_string2), x); // cfg-warning {{local 
variable 'local_string2' does not live long enough}}
-                                    // cfg-note@-1 {{result of call to 
'move<std::basic_string<char> &>' aliases the storage of local variable 
'local_string2'}}
+    captureRValString(std::move(local_string2), x); // cfg-warning {{local 
variable 'local_string2' does not live long enough}} \
+                                    // cfg-note {{result of call to 
'move<std::basic_string<char> &>' aliases the storage of local variable 
'local_string2'}}
   }                                 // cfg-note 2 {{destroyed here}}           
                      
   (void)x;                          // cfg-note 2 {{later used here}}          
               
 }
+
+void safe_string_captures() {
+  noCaptureString(std::string(), x);
+  std::string local;
+  noCaptureString(local, x);
+}
 } // namespace capture_string
 
 // ****************************************************************************
 // Capture std::string_view (gsl pointer types)
 // ****************************************************************************
 namespace capture_string_view {
-struct X {} x;   // cfg-note 2 {{this global dangles}}
+struct X {} x;
 void captureStringView(std::string_view s [[clang::lifetime_capture_by(x)]], X 
&x);
 void captureRValStringView(std::string_view &&sv 
[[clang::lifetime_capture_by(x)]], X &x);
 void noCaptureStringView(std::string_view sv, X &x);
@@ -83,76 +90,74 @@ const std::string& getLifetimeBoundString(const std::string 
&s [[clang::lifetime
 const std::string& getLifetimeBoundString(std::string_view sv 
[[clang::lifetimebound]]);
 
 void temporary_string_capture() {
-  captureStringView(std::string(), x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}}
-                                       // cfg-warning@-1 {{temporary object 
does not live long enough}}
-                                       // cfg-note@-2 {{destroyed here}}
+  captureStringView(std::string(), x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}} \
+                                       // cfg-warning {{temporary object does 
not live long enough}} \
+                                       // cfg-note {{destroyed here}}
   (void)x;                             // cfg-note {{later used here}}       
-  captureRValStringView(std::string(), x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}}
-                                           // cfg-warning@-1 {{temporary 
object does not live long enough}}
-                                           // cfg-note@-2 {{destroyed here}}
-  (void)x;                                 // cfg-note {{later used here}}
-  captureRValStringView(std::string_view{"abcd"}, x); // cfg-warning 
{{temporary object does not live long enough}}
-                                                      // cfg-note@-1 
{{destroyed here}}
-  (void)x;                                            // cfg-note {{later used 
here}}                
+  captureRValStringView(std::string(), x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}} \
+                                           // cfg-warning {{temporary object 
does not live long enough}} \
+                                           // cfg-note {{destroyed here}}
+  (void)x;                                 // cfg-note {{later used here}}     
                                                 
 }
 
 void local_string_capture() {
   {
     std::string local_string;
-    captureStringView(getLifetimeBoundView(local_string), x);  // cfg-warning 
{{local variable 'local_string' does not live long enough}}
-                                                               // cfg-note@-1 
{{result of call to 'getLifetimeBoundView' aliases the storage of local 
variable 'local_string'}}
+    captureStringView(getLifetimeBoundView(local_string), x);  // cfg-warning 
{{local variable 'local_string' does not live long enough}} \
+                                                               // cfg-note 
{{result of call to 'getLifetimeBoundView' aliases the storage of local 
variable 'local_string'}}
   }                                                            // cfg-note 
{{destroyed here}}
   (void)x;      // cfg-note {{later used here}}
-  std::string_view local_string_view;
-  captureRValStringView(std::move(local_string_view), x); // cfg-warning 
{{stack memory associated with local variable 'local_string_view' escapes to 
the global variable 'x' which will dangle}}
 }
 
 // Lifetimebound captures
 void temporary_string_view_lifetimebound_capture() {
   captureStringView(getLifetimeBoundView( // cfg-note {{result of call to 
'getLifetimeBoundView' aliases the storage of temporary object}}
-  std::string()                           // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}}
-  ), x);                                  // cfg-warning@-1 {{temporary object 
does not live long enough}}
-                                          // cfg-note@-1 {{destroyed here}}
+  std::string()), x);                     // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}} \
+                                          // cfg-warning {{temporary object 
does not live long enough}} \
+                                          // cfg-note {{destroyed here}}
   (void)x;                                // cfg-note {{later used here}}
-  captureStringView(getLifetimeBoundString(std::string()), x);   // 
expected-warning {{object whose reference is captured by 'x' will be destroyed 
at the end of the full-expression}}
-                                                                 // 
cfg-warning@-1 {{temporary object does not live long enough}}
-                                                                 // 
cfg-note@-2 {{destroyed here}}
-                                                                 // 
cfg-note@-3 {{result of call to 'getLifetimeBoundString' aliases the storage of 
temporary object}}
+  captureStringView(getLifetimeBoundString(std::string()), x);   // 
expected-warning {{object whose reference is captured by 'x' will be destroyed 
at the end of the full-expression}} \
+                                                                 // 
cfg-warning {{temporary object does not live long enough}} \
+                                                                 // cfg-note 
{{destroyed here}} \
+                                                                 // cfg-note 
{{result of call to 'getLifetimeBoundString' aliases the storage of temporary 
object}}
   (void)x;                                                       // cfg-note 
{{later used here}}
-  captureRValStringView(getLifetimeBoundView(std::string()), x); // 
expected-warning {{object whose reference is captured by 'x' will be destroyed 
at the end of the full-expression}}
-                                                                 // 
cfg-warning@-1 {{temporary object does not live long enough}}
-                                                                 // 
cfg-note@-2 {{destroyed here}}
+  captureRValStringView(getLifetimeBoundView(std::string()), x); // 
expected-warning {{object whose reference is captured by 'x' will be destroyed 
at the end of the full-expression}} \
+                                                                 // 
cfg-warning {{temporary object does not live long enough}} \
+                                                                 // cfg-note 
{{result of call to 'getLifetimeBoundView' aliases the storage of temporary 
object}} \
+                                                                 // cfg-note 
{{destroyed here}}
   (void)x;                                                       // cfg-note 
{{later used here}}                                                             
  
-  captureRValStringView(getNotLifetimeBoundView(std::string()), x);  // 
cfg-warning {{stack memory associated with temporary object escapes to the 
global variable 'x' which will dangle}}
 }
 
 void local_string_lifetimebound_capture() {
  {
     std::string local_string;
-    captureRValStringView(getLifetimeBoundView(local_string), x); // 
cfg-warning {{temporary object does not live long enough}}
-                                                                  // 
cfg-note@-1 {{destroyed here}}
- }
+    captureRValStringView(getLifetimeBoundView(local_string), x); // 
cfg-warning {{local variable 'local_string' does not live long enough}} \
+                                                                  // cfg-note 
{{result of call to 'getLifetimeBoundView' aliases the storage of local 
variable 'local_string'}}                                                       
                                                                 
+ }                                                                // cfg-note 
{{destroyed here}}
  (void)x;                                                         // cfg-note 
{{later used here}}
 }
 
 void temporary_nested_lifetimebound_capture() {
-  
captureStringView(getLifetimeBoundString(getLifetimeBoundView(std::string())), 
x); // expected-warning {{object whose reference is captured by 'x' will be 
destroyed at the end of the full-expression}}
-                                                                               
      // cfg-warning@-1 {{temporary object does not live long enough}}
-                                                                               
      // cfg-note@-2 {{destroyed here}}
-                                                                               
      // cfg-note@-3 {{result of call to 'getLifetimeBoundView' aliases the 
storage of temporary object}}
-                                                                               
      // cfg-note@-4 {{result of call to 'getLifetimeBoundString' aliases the 
storage of temporary object}}
+  
captureStringView(getLifetimeBoundString(getLifetimeBoundView(std::string())), 
x); // expected-warning {{object whose reference is captured by 'x' will be 
destroyed at the end of the full-expression}} \
+                                                                               
      // cfg-warning {{temporary object does not live long enough}} \
+                                                                               
      // cfg-note {{destroyed here}} \
+                                                                               
      // cfg-note {{result of call to 'getLifetimeBoundView' aliases the 
storage of temporary object}} \
+                                                                               
      // cfg-note {{result of call to 'getLifetimeBoundString' aliases the 
storage of temporary object}}
   (void)x;                                                                     
      // cfg-note {{later used here}}
   captureStringView(getLifetimeBoundString(getLifetimeBoundString(             
      // cfg-note 2 {{result of call to 'getLifetimeBoundString' aliases the 
storage of temporary object}}
-    std::string()  // expected-warning {{object whose reference is captured by 
'x' will be destroyed at the end of the full-expression}}
-    )), x);        // cfg-warning@-1 {{temporary object does not live long 
enough}}
-                   // cfg-note@-1 {{destroyed here}}
-  (void)x;         // cfg-note {{later used here}}
+    std::string())), x);  // expected-warning {{object whose reference is 
captured by 'x' will be destroyed at the end of the full-expression}} \
+                          // cfg-warning {{temporary object does not live long 
enough}} \
+                          // cfg-note {{destroyed here}}
+  (void)x;                // cfg-note {{later used here}}
 }
 
 void safe_captures() {
   std::string_view local_string_view;
   captureStringView(local_string_view, x);
+  captureRValStringView(std::move(local_string_view), x);
+  captureRValStringView(std::string_view{"abcd"}, x);    
   captureStringView(getNotLifetimeBoundView(std::string()), x);
+  captureRValStringView(getNotLifetimeBoundView(std::string()), x);
   noCaptureStringView(local_string_view, x);
   noCaptureStringView(std::string(), x);
   noCaptureStringView(getLifetimeBoundView(std::string()), x);
@@ -170,17 +175,17 @@ struct X {} x;   // cfg-note {{this global dangles}}
 void capturePointer(const std::string* sp [[clang::lifetime_capture_by(x)]], X 
&x);
 
 void temporary_pointer_lifetimebound_capture() {
-  capturePointer(getLifetimeBoundPointer(std::string()), x); // 
expected-warning {{object whose reference is captured by 'x' will be destroyed 
at the end of the full-expression}}
-                                                             // cfg-warning@-1 
{{temporary object does not live long enough}}
-                                                             // cfg-note@-2 
{{destroyed here}}
-                                                             // cfg-note@-3 
{{result of call to 'getLifetimeBoundPointer' aliases the storage of temporary 
object}}
+  capturePointer(getLifetimeBoundPointer(std::string()), x); // 
expected-warning {{object whose reference is captured by 'x' will be destroyed 
at the end of the full-expression}} \
+                                                             // cfg-warning 
{{temporary object does not live long enough}} \
+                                                             // cfg-note 
{{destroyed here}} \
+                                                             // cfg-note 
{{result of call to 'getLifetimeBoundPointer' aliases the storage of temporary 
object}}
   (void)x;                                                   // cfg-note 
{{later used here}}
 }
 
 void temporary_nested_lifetimebound_capture() {
   capturePointer(getLifetimeBoundPointer(*getLifetimeBoundPointer(
-    std::string()  // expected-warning {{object whose reference is captured by 
'x' will be destroyed at the end of the full-expression}}
-    )), x);        // cfg-warning@-1 {{stack memory associated with temporary 
object escapes to the global variable 'x' which will dangle}}
+    std::string())), x);  // expected-warning {{object whose reference is 
captured by 'x' will be destroyed at the end of the full-expression}} \
+                          // cfg-warning {{stack memory associated with 
temporary object escapes to the global variable 'x' which will dangle}}
 }
 
 void safe_capture() {
@@ -200,13 +205,13 @@ void captureInitList(std::initializer_list<int> abc 
[[clang::lifetime_capture_by
 std::initializer_list<int> getLifetimeBoundInitList(std::initializer_list<int> 
abc [[clang::lifetimebound]]);
 
 void temporary_vector_capture() {
-  captureVector({1, 2, 3}, x); // expected-warning {{object whose reference is 
captured by 'x' will be destroyed at the end of the full-expression}}
-                               // cfg-warning@-1 {{temporary object does not 
live long enough}}
-                               // cfg-note@-2 {{destroyed here}}
+  captureVector({1, 2, 3}, x); // expected-warning {{object whose reference is 
captured by 'x' will be destroyed at the end of the full-expression}} \
+                               // cfg-warning {{temporary object does not live 
long enough}} \
+                               // cfg-note {{destroyed here}}
   (void)x;                     // cfg-note {{later used here}}       
-  captureVector(std::vector<int>{}, x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}}
-                                        // cfg-warning@-1 {{temporary object 
does not live long enough}}
-                                        // cfg-note@-2 {{destroyed here}}
+  captureVector(std::vector<int>{}, x); // expected-warning {{object whose 
reference is captured by 'x' will be destroyed at the end of the 
full-expression}} \
+                                        // cfg-warning {{temporary object does 
not live long enough}} \
+                                        // cfg-note {{destroyed here}}
   (void)x;                              // cfg-note {{later used here}}        
 }
 
@@ -225,8 +230,8 @@ void local_array_capture() {
 
 // FIXME: Add support for initializer lists in -Wlifetime-safety
 void initializer_list_capture() {
-  captureInitList({1, 2}, x); // expected-warning {{object whose reference is 
captured by 'x' will be destroyed at the end of the full-expression}}         
-  captureInitList(getLifetimeBoundInitList({1, 2}), x); // expected-warning 
{{object whose reference is captured by 'x' will be destroyed at the end of the 
full-expression}}                                     
+  captureInitList({1, 2}, x); // expected-warning {{object whose reference is 
captured by 'x' will be destroyed at the end of the full-expression}}
+  captureInitList(getLifetimeBoundInitList({1, 2}), x); // expected-warning 
{{object whose reference is captured by 'x' will be destroyed at the end of the 
full-expression}}                                
 }
 } // namespace init_lists
 
@@ -302,27 +307,27 @@ const std::string& getLifetimeBoundString(const 
std::string &s [[clang::lifetime
 
 void temporary_capture_by_this() {
   S s;
-  s.captureInt(1); // expected-warning {{object whose reference is captured by 
's' will be destroyed at the end of the full-expression}}
-                   // cfg-warning@-1 {{temporary object does not live long 
enough}}
-                   // cfg-note@-2 {{destroyed here}}
+  s.captureInt(1); // expected-warning {{object whose reference is captured by 
's' will be destroyed at the end of the full-expression}} \
+                   // cfg-warning {{temporary object does not live long 
enough}} \
+                   // cfg-note {{destroyed here}}
   (void)s;         // cfg-note {{later used here}}       
-  s.captureView(std::string()); // expected-warning {{object whose reference 
is captured by 's' will be destroyed at the end of the full-expression}}
-                                // cfg-warning@-1 {{temporary object does not 
live long enough}}
-                                // cfg-note@-2 {{destroyed here}}
+  s.captureView(std::string()); // expected-warning {{object whose reference 
is captured by 's' will be destroyed at the end of the full-expression}} \
+                                // cfg-warning {{temporary object does not 
live long enough}} \
+                                // cfg-note {{destroyed here}}
   (void)s;                      // cfg-note {{later used here}}                
              
 }
 
 void lifetimebound_capture_by_this() {
   S s;
-  s.captureView(getLifetimeBoundView(std::string()));    // expected-warning 
{{object whose reference is captured by 's' will be destroyed at the end of the 
full-expression}}
-                                                         // cfg-warning@-1 
{{temporary object does not live long enough}}
-                                                         // cfg-note@-2 
{{destroyed here}}
-                                                         // cfg-note@-3 
{{esult of call to 'getLifetimeBoundView' aliases the storage of temporary 
object}}
+  s.captureView(getLifetimeBoundView(std::string()));    // expected-warning 
{{object whose reference is captured by 's' will be destroyed at the end of the 
full-expression}} \
+                                                         // cfg-warning 
{{temporary object does not live long enough}} \
+                                                         // cfg-note 
{{destroyed here}} \
+                                                         // cfg-note {{esult 
of call to 'getLifetimeBoundView' aliases the storage of temporary object}}
   (void)s;                                               // cfg-note {{later 
used here}}         
-  s.captureView(getLifetimeBoundString(std::string()));  // expected-warning 
{{object whose reference is captured by 's' will be destroyed at the end of the 
full-expression}}
-                                                         // cfg-warning@-1 
{{temporary object does not live long enough}}
-                                                         // cfg-note@-2 
{{destroyed here}}
-                                                         // cfg-note@-3 
{{result of call to 'getLifetimeBoundString' aliases the storage of temporary 
object}}
+  s.captureView(getLifetimeBoundString(std::string()));  // expected-warning 
{{object whose reference is captured by 's' will be destroyed at the end of the 
full-expression}} \
+                                                         // cfg-warning 
{{temporary object does not live long enough}} \
+                                                         // cfg-note 
{{destroyed here}} \
+                                                         // cfg-note {{result 
of call to 'getLifetimeBoundString' aliases the storage of temporary object}}
   (void)s;                                               // cfg-note {{later 
used here}}        
   s.captureView(getNotLifetimeBoundView(std::string()));
 }  
@@ -376,18 +381,17 @@ struct MySet {
 };
 void user_defined_containers() {
   MySet<int> set_of_int;
-  set_of_int.insert(1); // expected-warning {{object whose reference is 
captured by 'set_of_int' will be destroyed at the end of the full-expression}}
-                        // cfg-warning@-1 {{temporary object does not live 
long enough}}
-                        // cfg-note@-2 {{destroyed here}}
+  set_of_int.insert(1); // expected-warning {{object whose reference is 
captured by 'set_of_int' will be destroyed at the end of the full-expression}} \
+                        // cfg-warning {{temporary object does not live long 
enough}} \
+                        // cfg-note {{destroyed here}}
   (void)set_of_int;     // cfg-note {{later used here}}                   
   MySet<std::string_view> set_of_sv;
-  set_of_sv.insert(std::string());       // expected-warning {{object whose 
reference is captured by 'set_of_sv' will be destroyed at the end of the 
full-expression}}
-                                         // cfg-warning@-1 {{temporary object 
does not live long enough}}
-                                         // cfg-note@-2 {{destroyed here}}
+  set_of_sv.insert(std::string());       // expected-warning {{object whose 
reference is captured by 'set_of_sv' will be destroyed at the end of the 
full-expression}} \
+                                         // cfg-warning {{temporary object 
does not live long enough}} \
+                                         // cfg-note {{destroyed here}}
   (void)set_of_sv;                       // cfg-note {{later used here}}       
         
-  set_of_sv.insert(std::string_view());  // cfg-warning {{temporary object 
does not live long enough}}
-                                         // cfg-note@-1 {{destroyed here}}
-  (void)set_of_sv;                       // cfg-note {{later used here}}       
                                             
+  set_of_sv.insert(std::string_view());
+  (void)set_of_sv;                                             
                                     
 }
 } // namespace containers_no_distinction
@@ -417,29 +421,30 @@ void use_container() {
   vector_of_string.push_back(std::string()); // Ok.
   
   MyVector<std::string_view> vector_of_view;
-  vector_of_view.push_back(std::string()); // expected-warning {{object whose 
reference is captured by 'vector_of_view' will be destroyed at the end of the 
full-expression}}
-                                           // cfg-warning@-1 {{temporary 
object does not live long enough}}
-                                           // cfg-note@-2 {{destroyed here}}
+  vector_of_view.push_back(std::string()); // expected-warning {{object whose 
reference is captured by 'vector_of_view' will be destroyed at the end of the 
full-expression}} \
+                                           // cfg-warning {{temporary object 
does not live long enough}} \
+                                           // cfg-note {{destroyed here}}
   (void)vector_of_view;                    // cfg-note {{later used here}}
-  vector_of_view.push_back(getLifetimeBoundView(std::string())); // 
expected-warning {{object whose reference is captured by 'vector_of_view' will 
be destroyed at the end of the full-expression}}
-                                                                 // 
cfg-warning@-1 {{temporary object does not live long enough}}
-                                                                 // 
cfg-note@-2 {{destroyed here}}
+  vector_of_view.push_back(getLifetimeBoundView(std::string())); // 
expected-warning {{object whose reference is captured by 'vector_of_view' will 
be destroyed at the end of the full-expression}} \
+                                                                 // 
cfg-warning {{temporary object does not live long enough}} \
+                                                                 // cfg-note 
{{destroyed here}} \
+                                                                 // cfg-note 
{{result of call to 'getLifetimeBoundView' aliases the storage of temporary 
object}}
   (void)vector_of_view;                                          // cfg-note 
{{later used here}}
 
   MyVector<const std::string*> vector_of_pointer;
-  vector_of_pointer.push_back(getLifetimeBoundPointer(std::string())); // 
expected-warning {{object whose reference is captured by 'vector_of_pointer' 
will be destroyed at the end of the full-expression}}
-                                                                       // 
cfg-warning@-1 {{temporary object does not live long enough}}
-                                                                       // 
cfg-note@-2 {{destroyed here}}
+  vector_of_pointer.push_back(getLifetimeBoundPointer(std::string())); // 
expected-warning {{object whose reference is captured by 'vector_of_pointer' 
will be destroyed at the end of the full-expression}} \
+                                                                       // 
cfg-warning {{temporary object does not live long enough}} \
+                                                                       // 
cfg-note {{destroyed here}}
   (void)vector_of_pointer;                                             // 
cfg-note {{later used here}}
-  
vector_of_pointer.push_back(getLifetimeBoundPointer(*getLifetimeBoundPointer(std::string())));
 // expected-warning {{object whose reference is captured by 
'vector_of_pointer' will be destroyed at the end of the full-expression}}
-                                                                               
                  // cfg-warning@-1 {{temporary object does not live long 
enough}}
-                                                                               
                  // cfg-note@-2 {{destroyed here}}
+  
vector_of_pointer.push_back(getLifetimeBoundPointer(*getLifetimeBoundPointer(std::string())));
 // expected-warning {{object whose reference is captured by 
'vector_of_pointer' will be destroyed at the end of the full-expression}} \
+                                                                               
                  // cfg-warning {{temporary object does not live long enough}} 
\
+                                                                               
                  // cfg-note {{destroyed here}}
   (void)vector_of_pointer;                                                     
                  // cfg-note {{later used here}}
-  vector_of_pointer.push_back(getLifetimeBoundPointer(local));              // 
cfg-warning {{temporary object does not live long enough}}
-                                                                            // 
cfg-note@-1 {{destroyed here}}
+  vector_of_pointer.push_back(getLifetimeBoundPointer(local));              // 
cfg-warning {{temporary object does not live long enough}} \
+                                                                            // 
cfg-note {{destroyed here}}
   (void)vector_of_pointer;                                                  // 
cfg-note {{later used here}}
-  vector_of_pointer.push_back(getNotLifetimeBoundPointer(std::string()));   // 
cfg-warning {{temporary object does not live long enough}}
-                                                                            // 
cfg-note@-1 {{destroyed here}}
+  vector_of_pointer.push_back(getNotLifetimeBoundPointer(std::string()));   // 
cfg-warning {{temporary object does not live long enough}} \
+                                                                            // 
cfg-note {{destroyed here}}
   (void)vector_of_pointer;                                                  // 
cfg-note {{later used here}}
 }
 
@@ -471,36 +476,34 @@ const std::string& 
getLifetimeBoundString(std::string_view sv [[clang::lifetimeb
 void use_my_view() {
   std::string local;
   MyVector<MyStringView> vector_of_my_view;
-  vector_of_my_view.push_back(getMySV());           // cfg-warning {{temporary 
object does not live long enough}}
-                                                    // cfg-note@-1 {{destroyed 
here}}
-  (void)vector_of_my_view;                          // cfg-note {{later used 
here}}
-  vector_of_my_view.push_back(MyStringView{});      // cfg-warning {{temporary 
object does not live long enough}}
-                                                    // cfg-note@-1 {{destroyed 
here}}
-  (void)vector_of_my_view;                          // cfg-note {{later used 
here}}
-  vector_of_my_view.push_back(std::string_view{});  // cfg-warning {{temporary 
object does not live long enough}}
-                                                    // cfg-note@-1 {{destroyed 
here}}
-  (void)vector_of_my_view;                          // cfg-note {{later used 
here}}
-  vector_of_my_view.push_back(std::string{});       // expected-warning 
{{object whose reference is captured by 'vector_of_my_view' will be destroyed 
at the end of the full-expression}}
-                                                    // cfg-warning@-1 
{{temporary object does not live long enough}}
-                                                    // cfg-note@-2 {{destroyed 
here}}
+  vector_of_my_view.push_back(getMySV());
+  (void)vector_of_my_view;
+  vector_of_my_view.push_back(MyStringView{});
+  (void)vector_of_my_view;
+  vector_of_my_view.push_back(std::string_view{});
+  (void)vector_of_my_view;
+  vector_of_my_view.push_back(std::string{});       // expected-warning 
{{object whose reference is captured by 'vector_of_my_view' will be destroyed 
at the end of the full-expression}} \
+                                                    // cfg-warning {{temporary 
object does not live long enough}} \
+                                                    // cfg-note {{destroyed 
here}}
   (void)vector_of_my_view;                          // cfg-note {{later used 
here}}                                            
-  vector_of_my_view.push_back(getLifetimeBoundView(std::string{})); // 
expected-warning {{object whose reference is captured by 'vector_of_my_view' 
will be destroyed at the end of the full-expression}}
-                                                    // cfg-warning@-1 
{{temporary object does not live long enough}}
-                                                    // cfg-note@-2 {{destroyed 
here}}
+  vector_of_my_view.push_back(getLifetimeBoundView(std::string{})); // 
expected-warning {{object whose reference is captured by 'vector_of_my_view' 
will be destroyed at the end of the full-expression}} \
+                                                    // cfg-warning {{temporary 
object does not live long enough}} \
+                                                    // cfg-note {{destroyed 
here}} \
+                                                    // cfg-note {{result of 
call to 'getLifetimeBoundView' aliases the storage of temporary object}}
   (void)vector_of_my_view;                          // cfg-note {{later used 
here}}                                                   
-  
vector_of_my_view.push_back(getLifetimeBoundString(getLifetimeBoundView(std::string{})));
 // expected-warning {{object whose reference is captured by 
'vector_of_my_view' will be destroyed at the end of the full-expression}}
-                                                    // cfg-warning@-1 
{{temporary object does not live long enough}}
-                                                    // cfg-note@-2 {{destroyed 
here}}
+  
vector_of_my_view.push_back(getLifetimeBoundString(getLifetimeBoundView(std::string{})));
 // expected-warning {{object whose reference is captured by 
'vector_of_my_view' will be destroyed at the end of the full-expression}} \
+                                                    // cfg-warning {{temporary 
object does not live long enough}} \
+                                                    // cfg-note {{destroyed 
here}} \
+                                                    // cfg-note {{esult of 
call to 'getLifetimeBoundView' aliases the storage of temporary object}} \
+                                                    // cfg-note {{result of 
call to 'getLifetimeBoundString' aliases the storage of temporary object}}
   (void)vector_of_my_view;                          // cfg-note {{later used 
here}}                                                    
-  
vector_of_my_view.push_back(getNotLifetimeBoundView(getLifetimeBoundString(getLifetimeBoundView(std::string{}))));
 // cfg-warning {{temporary object does not live long enough}}
-                                                    // cfg-note@-1 {{destroyed 
here}}
-  (void)vector_of_my_view;                          // cfg-note {{later used 
here}}       
+  
vector_of_my_view.push_back(getNotLifetimeBoundView(getLifetimeBoundString(getLifetimeBoundView(std::string{}))));
+  (void)vector_of_my_view;
   
   // Use with container of other view types.
   MyVector<std::string_view> vector_of_view;
-  vector_of_view.push_back(getMySV());              // cfg-warning {{temporary 
object does not live long enough}}
-                                                    // cfg-note@-1 {{destroyed 
here}}
-  (void)vector_of_view;                             // cfg-note {{later used 
here}}
+  vector_of_view.push_back(getMySV());
+  (void)vector_of_view;
   vector_of_view.push_back(getMySVNotP());
   (void)vector_of_view;
 }
@@ -513,18 +516,15 @@ void use_with_optional_view() {
 
   std::optional<std::string_view> optional_of_view;
   vector_of_view.push_back(optional_of_view.value());
-  vector_of_view.push_back(getOptionalS().value());      // expected-warning 
{{object whose reference is captured by 'vector_of_view' will be destroyed at 
the end of the full-expression}}
-                                                         // cfg-warning@-1 
{{temporary object does not live long enough}}
-                                                         // cfg-note@-2 
{{destroyed here}}                                                         
-  (void)vector_of_view;                                  // cfg-note {{later 
used here}}  
-  vector_of_view.push_back(getOptionalSV().value());     // cfg-warning 
{{temporary object does not live long enough}}
-                                                         // cfg-note@-1 
{{destroyed here}}
-                                                         // cfg-note@-2 
{{result of call to 'value' aliases the storage of temporary object}}
-  (void)vector_of_view;                                  // cfg-note {{later 
used here}}  
-  vector_of_view.push_back(getOptionalMySV().value());   // cfg-warning 
{{temporary object does not live long enough}}
-                                                         // cfg-note@-1 
{{destroyed here}}
-                                                         // cfg-note@-2 
{{result of call to 'value' aliases the storage of temporary object}}
+  vector_of_view.push_back(getOptionalS().value());      // expected-warning 
{{object whose reference is captured by 'vector_of_view' will be destroyed at 
the end of the full-expression}} \
+                                                         // cfg-warning 
{{temporary object does not live long enough}} \
+                                                         // cfg-note 
{{destroyed here}} \
+                                                         // cfg-note {{result 
of call to 'value' aliases the storage of temporary object}}                    
                                     
   (void)vector_of_view;                                  // cfg-note {{later 
used here}}  
+  vector_of_view.push_back(getOptionalSV().value());
+  (void)vector_of_view;
+  vector_of_view.push_back(getOptionalMySV().value());
+  (void)vector_of_view;
   vector_of_view.push_back(getOptionalMySVNotP().value());
 }
 } // namespace conatiners_with_different
@@ -542,30 +542,28 @@ void capture3(const std::string_view& s 
[[clang::lifetime_capture_by(x)]], std::
 
 void use() {
   std::vector<std::string_view> x1;
-  capture1(std::string(), x1); // expected-warning {{object whose reference is 
captured by 'x1' will be destroyed at the end of the full-expression}}
-                               // cfg-warning@-1 {{temporary object does not 
live long enough}}
-                               // cfg-note@-2 {{destroyed here}}
+  capture1(std::string(), x1); // expected-warning {{object whose reference is 
captured by 'x1' will be destroyed at the end of the full-expression}} \
+                               // cfg-warning {{temporary object does not live 
long enough}} \
+                               // cfg-note {{destroyed here}}
   (void)x1;                    // cfg-note {{later used here}}
   capture1(std::string_view(), x1);
 
   std::vector<std::string_view*> x2;
   // Clang considers 'const std::string_view&' to refer to the owner
   // 'std::string' and not 'std::string_view'. Therefore no diagnostic here.
-  capture2(std::string_view(), x2);  // cfg-warning {{temporary object does 
not live long enough}} 
-                                     // cfg-note@-1 {{destroyed here}}
-  (void)x2;                          // cfg-note {{later used here}}
-  capture2(std::string(), x2);       // expected-warning {{object whose 
reference is captured by 'x2' will be destroyed at the end of the 
full-expression}}
-                                     // cfg-warning@-1 {{temporary object does 
not live long enough}} 
-                                     // cfg-note@-2 {{destroyed here}}
+  capture2(std::string_view(), x2);
+  (void)x2;
+  capture2(std::string(), x2);       // expected-warning {{object whose 
reference is captured by 'x2' will be destroyed at the end of the 
full-expression}} \
+                                     // cfg-warning {{temporary object does 
not live long enough}} \
+                                     // cfg-note {{destroyed here}}
   (void)x2;                          // cfg-note {{later used here}}
   
   std::vector<std::string_view> x3;
-  capture3(std::string_view(), x3);  // cfg-warning {{temporary object does 
not live long enough}} 
-                                     // cfg-note@-1 {{destroyed here}}
-  (void)x3;                          // cfg-note {{later used here}}           
-  capture3(std::string(), x3);       // expected-warning {{object whose 
reference is captured by 'x3' will be destroyed at the end of the 
full-expression}}
-                                     // cfg-warning@-1 {{temporary object does 
not live long enough}} 
-                                     // cfg-note@-2 {{destroyed here}}
+  capture3(std::string_view(), x3);
+  (void)x3;      
+  capture3(std::string(), x3);       // expected-warning {{object whose 
reference is captured by 'x3' will be destroyed at the end of the 
full-expression}} \
+                                     // cfg-warning {{temporary object does 
not live long enough}}  \
+                                     // cfg-note {{destroyed here}}
   (void)x3;                          // cfg-note {{later used here}}       
 }
 } // namespace temporary_views
@@ -581,40 +579,41 @@ std::string_view getLifetimeBoundView(const std::string& 
s [[clang::lifetimeboun
 std::string_view getNotLifetimeBoundView(const std::string& s);
 void use() {
   std::vector<std::string_view> views;
-  views.push_back(std::string()); // expected-warning {{object whose reference 
is captured by 'views' will be destroyed at the end of the full-expression}}
-                                  // cfg-warning@-1 {{temporary object does 
not live long enough}}
-                                  // cfg-note@-2 {{destroyed here}}
+  views.push_back(std::string()); // expected-warning {{object whose reference 
is captured by 'views' will be destroyed at the end of the full-expression}} \
+                                  // cfg-warning {{temporary object does not 
live long enough}} \
+                                  // cfg-note {{destroyed here}}
   (void)views;                    // cfg-note {{later used here}}             
   views.insert(views.begin(), 
-            std::string());       // expected-warning {{object whose reference 
is captured by 'views' will be destroyed at the end of the full-expression}}
-                                  // cfg-warning@-1 {{temporary object does 
not live long enough}}
-                                  // cfg-note@-2 {{destroyed here}}
+            std::string());       // expected-warning {{object whose reference 
is captured by 'views' will be destroyed at the end of the full-expression}} \
+                                  // cfg-warning {{temporary object does not 
live long enough}} \
+                                  // cfg-note {{destroyed here}}
   (void)views;                    // cfg-note {{later used here}}              
               
-  views.push_back(getLifetimeBoundView(std::string()));    // expected-warning 
{{object whose reference is captured by 'views' will be destroyed at the end of 
the full-expression}}
-                                                           // cfg-warning@-1 
{{temporary object does not live long enough}}
-                                                           // cfg-note@-2 
{{destroyed here}}
+  views.push_back(getLifetimeBoundView(std::string()));    // expected-warning 
{{object whose reference is captured by 'views' will be destroyed at the end of 
the full-expression}} \
+                                                           // cfg-warning 
{{temporary object does not live long enough}} \
+                                                           // cfg-note 
{{destroyed here}} \
+                                                           // cfg-note 
{{result of call to 'getLifetimeBoundView' aliases the storage of temporary 
object}}
   (void)views;                                             // cfg-note {{later 
used here}}                                                             
-  views.push_back(getNotLifetimeBoundView(std::string())); // cfg-warning 
{{temporary object does not live long enough}}
-                                                           // cfg-note@-1 
{{destroyed here}}
-  (void)views;                                             // cfg-note {{later 
used here}}  
+  views.push_back(getNotLifetimeBoundView(std::string()));
+  (void)views;
   {
       std::string local1, local2;
-      views.push_back(local1);            // cfg-warning {{temporary object 
does not live long enough}}
-                                          // cfg-note@-1 {{destroyed here}}
-      (void)views;                        // cfg-note {{later used here}}      
        
-      views.insert(views.end(), local2);  // cfg-warning {{temporary object 
does not live long enough}}
-                                          // cfg-note@-1 {{destroyed here}}
-  }                                       
-  (void)views;                            // cfg-note {{later used here}}
+      views.push_back(local1);    // cfg-warning {{local variable 'local1' 
does not live long enough}}
+      (void)views;       
+      views.insert(views.end(), local2);  // cfg-warning {{local variable 
'local2' does not live long enough}}
+  }                                       // cfg-note 2 {{destroyed here}}     
                                  
+  (void)views;                            // cfg-note 2 {{later used here}}
 
   std::vector<std::string> strings;
   strings.push_back(std::string());
+  (void)views;
   strings.insert(strings.begin(), std::string());
 
   std::vector<const std::string*> pointers;
   pointers.push_back(getLifetimeBoundPointer(std::string()));
+  (void)views;
   std::string local;
   pointers.push_back(&local);
+  (void)views;
 }
 
 namespace with_span {
@@ -626,15 +625,14 @@ struct [[gsl::Pointer]] Span {
 
 void use() {
   std::vector<Span<int>> spans;
-  spans.push_back(std::vector<int>{1, 2, 3}); // expected-warning {{object 
whose reference is captured by 'spans' will be destroyed at the end of the 
full-expression}}
-                                              // cfg-warning@-1 {{temporary 
object does not live long enough}}
-                                              // cfg-note@-2 {{destroyed here}}
+  spans.push_back(std::vector<int>{1, 2, 3}); // expected-warning {{object 
whose reference is captured by 'spans' will be destroyed at the end of the 
full-expression}} \
+                                              // cfg-warning {{temporary 
object does not live long enough}} \
+                                              // cfg-note {{destroyed here}}
   (void)spans;                                // cfg-note {{later used here}}  
                                  
   {
     std::vector<int> local;
-    spans.push_back(local);    // cfg-warning {{temporary object does not live 
long enough}}
-                               // cfg-note@-1 {{destroyed here}}
-  }                            
+    spans.push_back(local);    // cfg-warning {{local variable 'local' does 
not live long enough}}         
+  }                            // cfg-note {{destroyed here}}                  
      
   (void)spans;                 // cfg-note {{later used here}} 
 }
 } // namespace with_span

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

Reply via email to