https://github.com/suoyuan666 created 
https://github.com/llvm/llvm-project/pull/212083

Initially, I planned to make all diagnostics in Checker.cpp use 
`buildOriginFlowChain`. However, after thinking about it, I think the current 
scope is more suitable for review.

>From f7a016b3ff28b78f90057f1bdd6933a2b27c914e Mon Sep 17 00:00:00 2001
From: Yuan Suo <[email protected]>
Date: Sat, 18 Jul 2026 15:06:23 +0800
Subject: [PATCH] Use buildOriginFlowChain for remaining diagnostics in
 issuePendingWarnings

Signed-off-by: Yuan Suo <[email protected]>
---
 .../Analyses/LifetimeSafety/LifetimeSafety.h  |  23 +-
 .../Analyses/LifetimeSafety/LoanPropagation.h |   2 +-
 clang/lib/Analysis/LifetimeSafety/Checker.cpp |  35 +--
 .../LifetimeSafety/LoanPropagation.cpp        |   9 +-
 clang/lib/Sema/SemaLifetimeSafety.h           |  44 ++-
 .../LifetimeSafety/annotation-suggestions.cpp |  23 +-
 .../Sema/LifetimeSafety/dangling-field.cpp    |  27 +-
 .../Sema/LifetimeSafety/dangling-global.cpp   |   2 +-
 .../Sema/LifetimeSafety/invalidations.cpp     |  19 +-
 clang/test/Sema/LifetimeSafety/nocfg.cpp      |  93 +++++--
 clang/test/Sema/LifetimeSafety/safety-c.c     |   6 +-
 clang/test/Sema/LifetimeSafety/safety.cpp     | 252 ++++++++++++------
 12 files changed, 357 insertions(+), 178 deletions(-)

diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index a51ef2f7cc0ba..8e52363a41b4f 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -71,17 +71,20 @@ class LifetimeSafetySemaHelper {
 
   virtual void reportUseAfterReturn(const Expr *IssueExpr,
                                     const Expr *ReturnExpr,
-                                    const Expr *MovedExpr) {}
+                                    const Expr *MovedExpr,
+                                    llvm::ArrayRef<const Expr *> ExprChain) {}
 
   virtual void reportDanglingField(const Expr *IssueExpr,
                                    const FieldDecl *Field,
                                    const Expr *MovedExpr,
-                                   SourceLocation ExpiryLoc) {}
+                                   SourceLocation ExpiryLoc,
+                                   llvm::ArrayRef<const Expr *> ExprChain) {}
 
   virtual void reportDanglingGlobal(const Expr *IssueExpr,
                                     const VarDecl *DanglingGlobal,
                                     const Expr *MovedExpr,
-                                    SourceLocation ExpiryLoc) {}
+                                    SourceLocation ExpiryLoc,
+                                    llvm::ArrayRef<const Expr *> ExprChain) {}
 
   // Reports when a reference/iterator is used after the container operation
   // that invalidated it.
@@ -95,16 +98,22 @@ class LifetimeSafetySemaHelper {
                              llvm::ArrayRef<const Expr *> ExprChain) {}
   virtual void reportInvalidatedField(const Expr *IssueExpr,
                                       const FieldDecl *Field,
-                                      const Expr *InvalidationExpr) {}
+                                      const Expr *InvalidationExpr,
+                                      llvm::ArrayRef<const Expr *> ExprChain) 
{}
   virtual void reportInvalidatedField(const ParmVarDecl *PVD,
                                       const FieldDecl *Field,
-                                      const Expr *InvalidationExpr) {}
+                                      const Expr *InvalidationExpr,
+                                      llvm::ArrayRef<const Expr *> ExprChain) 
{}
   virtual void reportInvalidatedGlobal(const Expr *IssueExpr,
                                        const VarDecl *Global,
-                                       const Expr *InvalidationExpr) {}
+                                       const Expr *InvalidationExpr,
+                                       llvm::ArrayRef<const Expr *> ExprChain) 
{
+  }
   virtual void reportInvalidatedGlobal(const ParmVarDecl *PVD,
                                        const VarDecl *Global,
-                                       const Expr *InvalidationExpr) {}
+                                       const Expr *InvalidationExpr,
+                                       llvm::ArrayRef<const Expr *> ExprChain) 
{
+  }
 
   using EscapingTarget =
       llvm::PointerUnion<const Expr *, const FieldDecl *, const VarDecl *>;
diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h
index e13442facd82d..36c5e4242262e 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h
@@ -51,7 +51,7 @@ class LoanPropagationAnalysis {
                                                    const LoanID TargetLoan,
                                                    const CFG *Cfg) const;
 
-  llvm::SmallVector<OriginID> buildOriginFlowChain(const UseFact *UF,
+  llvm::SmallVector<OriginID> buildOriginFlowChain(const Fact *F,
                                                    const LoanID TargetLoan,
                                                    const CFG *Cfg) const;
 
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 53e5077131147..f099e400ee3b2 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -281,33 +281,35 @@ class LifetimeChecker {
 
       } else if (const auto *OEF =
                      CausingFact.dyn_cast<const OriginEscapesFact *>()) {
+        llvm::SmallVector<const Expr *> ExprChain =
+            getExprChain(LoanPropagation.buildOriginFlowChain(OEF, LID, Cfg));
         if (Warning.InvalidatedByExpr) {
           if (const auto *FieldEscape = dyn_cast<FieldEscapeFact>(OEF)) {
             // Invalidated object escapes to a field.
             if (IssueExpr)
               // Invalidated object on stack escapes to a field.
-              SemaHelper->reportInvalidatedField(IssueExpr,
-                                                 FieldEscape->getFieldDecl(),
-                                                 Warning.InvalidatedByExpr);
+              SemaHelper->reportInvalidatedField(
+                  IssueExpr, FieldEscape->getFieldDecl(),
+                  Warning.InvalidatedByExpr, ExprChain);
             else if (InvalidatedPVD)
               // Invalidated parameter escapes to a field.
-              SemaHelper->reportInvalidatedField(InvalidatedPVD,
-                                                 FieldEscape->getFieldDecl(),
-                                                 Warning.InvalidatedByExpr);
+              SemaHelper->reportInvalidatedField(
+                  InvalidatedPVD, FieldEscape->getFieldDecl(),
+                  Warning.InvalidatedByExpr, ExprChain);
           } else if (const auto *GlobalEscape =
                          dyn_cast<GlobalEscapeFact>(OEF)) {
             // Invalidated object escapes to global or static storage.
             if (IssueExpr)
               // Invalidated object on stack escapes to global or static
               // storage.
-              SemaHelper->reportInvalidatedGlobal(IssueExpr,
-                                                  GlobalEscape->getGlobal(),
-                                                  Warning.InvalidatedByExpr);
+              SemaHelper->reportInvalidatedGlobal(
+                  IssueExpr, GlobalEscape->getGlobal(),
+                  Warning.InvalidatedByExpr, ExprChain);
             else if (InvalidatedPVD)
               // Invalidated parameter escapes to global or static storage.
-              SemaHelper->reportInvalidatedGlobal(InvalidatedPVD,
-                                                  GlobalEscape->getGlobal(),
-                                                  Warning.InvalidatedByExpr);
+              SemaHelper->reportInvalidatedGlobal(
+                  InvalidatedPVD, GlobalEscape->getGlobal(),
+                  Warning.InvalidatedByExpr, ExprChain);
           } else if (isa<ReturnEscapeFact>(OEF)) {
             // FIXME: Diagnose invalidated return escapes separately.
           } else
@@ -315,15 +317,16 @@ class LifetimeChecker {
         } else if (const auto *RetEscape = dyn_cast<ReturnEscapeFact>(OEF))
           // Return stack address.
           SemaHelper->reportUseAfterReturn(
-              IssueExpr, RetEscape->getReturnExpr(), MovedExpr);
+              IssueExpr, RetEscape->getReturnExpr(), MovedExpr, ExprChain);
         else if (const auto *FieldEscape = dyn_cast<FieldEscapeFact>(OEF))
           // Dangling field.
-          SemaHelper->reportDanglingField(
-              IssueExpr, FieldEscape->getFieldDecl(), MovedExpr, ExpiryLoc);
+          SemaHelper->reportDanglingField(IssueExpr,
+                                          FieldEscape->getFieldDecl(),
+                                          MovedExpr, ExpiryLoc, ExprChain);
         else if (const auto *GlobalEscape = dyn_cast<GlobalEscapeFact>(OEF))
           // Global escape.
           SemaHelper->reportDanglingGlobal(IssueExpr, 
GlobalEscape->getGlobal(),
-                                           MovedExpr, ExpiryLoc);
+                                           MovedExpr, ExpiryLoc, ExprChain);
         else
           llvm_unreachable("Unhandled OriginEscapesFact type");
       } else
diff --git a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp 
b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
index 078892bd48c10..b2787c3abc987 100644
--- a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
@@ -366,7 +366,12 @@ llvm::SmallVector<OriginID> 
LoanPropagationAnalysis::buildOriginFlowChain(
 }
 
 llvm::SmallVector<OriginID> LoanPropagationAnalysis::buildOriginFlowChain(
-    const UseFact *UF, const LoanID TargetLoan, const CFG *Cfg) const {
-  return PImpl->buildOriginFlowChain(UF, TargetLoan, Cfg);
+    const Fact *F, const LoanID TargetLoan, const CFG *Cfg) const {
+  if (const auto *UF = llvm::dyn_cast<UseFact>(F))
+    return PImpl->buildOriginFlowChain(UF, TargetLoan, Cfg);
+  if (const auto *OEF = llvm::dyn_cast<OriginEscapesFact>(F))
+    return PImpl->buildOriginFlowChain(OEF, OEF->getEscapedOriginID(),
+                                       TargetLoan, Cfg);
+  llvm_unreachable("Unhandled Fact type");
 }
 } // namespace clang::lifetimes::internal
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h 
b/clang/lib/Sema/SemaLifetimeSafety.h
index 1d9f94be7e22d..eaa5981639e80 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -128,7 +128,8 @@ class LifetimeSafetySemaHelperImpl : public 
LifetimeSafetySemaHelper {
   }
 
   void reportUseAfterReturn(const Expr *IssueExpr, const Expr *ReturnExpr,
-                            const Expr *MovedExpr) override {
+                            const Expr *MovedExpr,
+                            llvm::ArrayRef<const Expr *> ExprChain) override {
     unsigned DiagID = MovedExpr
                           ? diag::warn_lifetime_safety_return_stack_addr_moved
                           : diag::warn_lifetime_safety_return_stack_addr;
@@ -139,14 +140,17 @@ class LifetimeSafetySemaHelperImpl : public 
LifetimeSafetySemaHelper {
     if (MovedExpr)
       S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here)
           << MovedExpr->getSourceRange();
+
+    reportAliasingChain(ExprChain);
+
     S.Diag(ReturnExpr->getExprLoc(), diag::note_lifetime_safety_returned_here)
         << ReturnExpr->getSourceRange();
   }
 
   void reportDanglingField(const Expr *IssueExpr,
                            const FieldDecl *DanglingField,
-                           const Expr *MovedExpr,
-                           SourceLocation ExpiryLoc) override {
+                           const Expr *MovedExpr, SourceLocation ExpiryLoc,
+                           llvm::ArrayRef<const Expr *> ExprChain) override {
     unsigned DiagID = MovedExpr
                           ? diag::warn_lifetime_safety_dangling_field_moved
                           : diag::warn_lifetime_safety_dangling_field;
@@ -158,6 +162,9 @@ class LifetimeSafetySemaHelperImpl : public 
LifetimeSafetySemaHelper {
     if (MovedExpr)
       S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here)
           << MovedExpr->getSourceRange();
+
+    reportAliasingChain(ExprChain);
+
     S.Diag(DanglingField->getLocation(),
            diag::note_lifetime_safety_dangling_field_here)
         << DanglingField->getEndLoc();
@@ -165,8 +172,8 @@ class LifetimeSafetySemaHelperImpl : public 
LifetimeSafetySemaHelper {
 
   void reportDanglingGlobal(const Expr *IssueExpr,
                             const VarDecl *DanglingGlobal,
-                            const Expr *MovedExpr,
-                            SourceLocation ExpiryLoc) override {
+                            const Expr *MovedExpr, SourceLocation ExpiryLoc,
+                            llvm::ArrayRef<const Expr *> ExprChain) override {
     unsigned DiagID = MovedExpr
                           ? diag::warn_lifetime_safety_dangling_global_moved
                           : diag::warn_lifetime_safety_dangling_global;
@@ -178,6 +185,9 @@ class LifetimeSafetySemaHelperImpl : public 
LifetimeSafetySemaHelper {
     if (MovedExpr)
       S.Diag(MovedExpr->getExprLoc(), diag::note_lifetime_safety_moved_here)
           << MovedExpr->getSourceRange();
+
+    reportAliasingChain(ExprChain);
+
     if (DanglingGlobal->isStaticLocal() || 
DanglingGlobal->isStaticDataMember())
       S.Diag(DanglingGlobal->getLocation(),
              diag::note_lifetime_safety_dangling_static_here)
@@ -223,13 +233,15 @@ class LifetimeSafetySemaHelperImpl : public 
LifetimeSafetySemaHelper {
 
   void reportInvalidatedField(const Expr *IssueExpr,
                               const FieldDecl *DanglingField,
-                              const Expr *InvalidationExpr) override {
+                              const Expr *InvalidationExpr,
+                              llvm::ArrayRef<const Expr *> ExprChain) override 
{
     std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
     S.Diag(IssueExpr->getExprLoc(),
            diag::warn_lifetime_safety_invalidated_field)
         << InvalidatedSubject << getDiagSubjectDescription(DanglingField)
         << IssueExpr->getSourceRange();
     reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
+    reportAliasingChain(ExprChain);
     S.Diag(DanglingField->getLocation(),
            diag::note_lifetime_safety_dangling_field_here)
         << DanglingField->getEndLoc();
@@ -237,27 +249,31 @@ class LifetimeSafetySemaHelperImpl : public 
LifetimeSafetySemaHelper {
 
   void reportInvalidatedField(const ParmVarDecl *PVD,
                               const FieldDecl *DanglingField,
-                              const Expr *InvalidationExpr) override {
+                              const Expr *InvalidationExpr,
+                              llvm::ArrayRef<const Expr *> ExprChain) override 
{
     std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
     S.Diag(PVD->getSourceRange().getBegin(),
            diag::warn_lifetime_safety_invalidated_field)
         << InvalidatedSubject << getDiagSubjectDescription(DanglingField)
         << PVD->getSourceRange();
     reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
+    reportAliasingChain(ExprChain);
     S.Diag(DanglingField->getLocation(),
            diag::note_lifetime_safety_dangling_field_here)
         << DanglingField->getEndLoc();
   }
 
-  void reportInvalidatedGlobal(const Expr *IssueExpr,
-                               const VarDecl *DanglingGlobal,
-                               const Expr *InvalidationExpr) override {
+  void
+  reportInvalidatedGlobal(const Expr *IssueExpr, const VarDecl *DanglingGlobal,
+                          const Expr *InvalidationExpr,
+                          llvm::ArrayRef<const Expr *> ExprChain) override {
     std::string InvalidatedSubject = getDiagSubjectDescription(IssueExpr);
     S.Diag(IssueExpr->getExprLoc(),
            diag::warn_lifetime_safety_invalidated_global)
         << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
         << IssueExpr->getSourceRange();
     reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
+    reportAliasingChain(ExprChain);
     if (DanglingGlobal->isStaticLocal() || 
DanglingGlobal->isStaticDataMember())
       S.Diag(DanglingGlobal->getLocation(),
              diag::note_lifetime_safety_dangling_static_here)
@@ -268,15 +284,17 @@ class LifetimeSafetySemaHelperImpl : public 
LifetimeSafetySemaHelper {
           << DanglingGlobal->getEndLoc();
   }
 
-  void reportInvalidatedGlobal(const ParmVarDecl *PVD,
-                               const VarDecl *DanglingGlobal,
-                               const Expr *InvalidationExpr) override {
+  void
+  reportInvalidatedGlobal(const ParmVarDecl *PVD, const VarDecl 
*DanglingGlobal,
+                          const Expr *InvalidationExpr,
+                          llvm::ArrayRef<const Expr *> ExprChain) override {
     std::string InvalidatedSubject = getDiagSubjectDescription(PVD);
     S.Diag(PVD->getSourceRange().getBegin(),
            diag::warn_lifetime_safety_invalidated_global)
         << InvalidatedSubject << getDiagSubjectDescription(DanglingGlobal)
         << PVD->getSourceRange();
     reportInvalidationSite(InvalidationExpr, InvalidatedSubject);
+    reportAliasingChain(ExprChain);
     if (DanglingGlobal->isStaticLocal() || 
DanglingGlobal->isStaticDataMember())
       S.Diag(DanglingGlobal->getLocation(),
              diag::note_lifetime_safety_dangling_static_here)
diff --git a/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp 
b/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp
index 56ed4a6dc7106..3497598196ee5 100644
--- a/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp
+++ b/clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp
@@ -528,7 +528,8 @@ struct CaptureRefToView {
 CaptureRefToView test_ref_to_view() {
   MyObj obj;
   CaptureRefToView x(obj); // expected-warning {{stack memory associated with 
local variable 'obj' is returned}}
-  return x; // expected-note {{returned here}}
+  return x; // expected-note {{returned here}} \
+            // expected-note {{local variable 'x' aliases the storage of local 
variable 'obj'}}
 }
 
 struct CaptureRefToPtr {
@@ -539,7 +540,8 @@ struct CaptureRefToPtr {
 CaptureRefToPtr test_ref_to_ptr() {
   MyObj obj;
   CaptureRefToPtr x(obj); // expected-warning {{stack memory associated with 
local variable 'obj' is returned}}
-  return x; // expected-note {{returned here}}
+  return x; // expected-note {{returned here}} \
+            // expected-note {{local variable 'x' aliases the storage of local 
variable 'obj'}}
 }
 
 struct CaptureViewToView {
@@ -550,8 +552,9 @@ struct CaptureViewToView {
 CaptureViewToView test_view_to_view() {
   MyObj obj;
   View v(obj); // expected-warning {{stack memory associated with local 
variable 'obj' is returned}}
-  CaptureViewToView x(v);
-  return x; // expected-note {{returned here}}
+  CaptureViewToView x(v); // expected-note {{local variable 'v' aliases the 
storage of local variable 'obj'}}
+  return x; // expected-note {{returned here}} \
+            // expected-note {{local variable 'x' aliases the storage of local 
variable 'obj'}}
 }
 
 struct CapturePtrToPtr {
@@ -562,7 +565,8 @@ struct CapturePtrToPtr {
 CapturePtrToPtr test_ptr_to_ptr() {
   MyObj obj;
   CapturePtrToPtr x(&obj); // expected-warning {{stack memory associated with 
local variable 'obj' is returned}}
-  return x; // expected-note {{returned here}}
+  return x; // expected-note {{returned here}} \
+            // expected-note {{local variable 'x' aliases the storage of local 
variable 'obj'}}
 }
 
 struct CaptureRefToRef {
@@ -573,7 +577,8 @@ struct CaptureRefToRef {
 CaptureRefToRef test_ref_to_ref() {
   MyObj obj;
   CaptureRefToRef x(obj); // expected-warning {{stack memory associated with 
local variable 'obj' is returned}}
-  return x; // expected-note {{returned here}}
+  return x; // expected-note {{returned here}} \
+            // expected-note {{local variable 'x' aliases the storage of local 
variable 'obj'}}
 }
 
 struct BaseWithView {
@@ -588,7 +593,8 @@ struct CaptureRefToBaseView : BaseWithView {
 CaptureRefToBaseView test_ref_to_base_view() {
   MyObj obj;
   CaptureRefToBaseView x(obj); // expected-warning {{stack memory associated 
with local variable 'obj' is returned}}
-  return x; // expected-note {{returned here}}
+  return x; // expected-note {{returned here}} \
+            // expected-note {{local variable 'x' aliases the storage of local 
variable 'obj'}}
 }
 } // namespace capturing_constructor
 
@@ -660,7 +666,8 @@ struct HasCtorField {
 HasCtorField test_dangling_field_ctor() {
   MyObj obj;
   HasCtorField x(obj); // expected-warning {{stack memory associated with 
local variable 'obj' is returned}}
-  return x;            // expected-note {{returned here}}
+  return x;            // expected-note {{returned here}} \
+                       // expected-note {{local variable 'x' aliases the 
storage of local variable 'obj'}}
 }
 
 struct HasSetterField {
diff --git a/clang/test/Sema/LifetimeSafety/dangling-field.cpp 
b/clang/test/Sema/LifetimeSafety/dangling-field.cpp
index bc73c4f7e8644..d3190d990d7a1 100644
--- a/clang/test/Sema/LifetimeSafety/dangling-field.cpp
+++ b/clang/test/Sema/LifetimeSafety/dangling-field.cpp
@@ -40,7 +40,8 @@ struct CtorSetInLoop {
 
 struct CtorInitLifetimeBound {
   std::string_view view;  // expected-note {{this field dangles}}
-  CtorInitLifetimeBound(std::string s) : view(construct_view(s)) {} // 
expected-warning {{stack memory associated with parameter 's' escapes to the 
field 'view' which will dangle}}
+  CtorInitLifetimeBound(std::string s) : view(construct_view(s)) {} // 
expected-warning {{stack memory associated with parameter 's' escapes to the 
field 'view' which will dangle}} \
+                                                                    // 
expected-note {{result of call to 'construct_view' aliases the storage of 
parameter 's'}}
 };
 
 struct CtorInitButMoved {
@@ -90,7 +91,8 @@ struct CtorRefField {
 
 struct CtorPointerField {
   const char* ptr; // expected-note {{this field dangles}}
-  CtorPointerField(std::string s) : ptr(s.data()) {}  // expected-warning 
{{stack memory associated with parameter 's' escapes to the field 'ptr' which 
will dangle}}
+  CtorPointerField(std::string s) : ptr(s.data()) {}  // expected-warning 
{{stack memory associated with parameter 's' escapes to the field 'ptr' which 
will dangle}} \
+                                                      // expected-note 
{{result of call to 'data' aliases the storage of parameter 's'}}
   CtorPointerField(Dummy<1> ok, const std::string& s) : ptr(s.data()) {}
   CtorPointerField(Dummy<2> ok, std::string_view view) : ptr(view.data()) {}
 };
@@ -101,12 +103,14 @@ struct MemberSetters {
 
   void setWithParam(std::string s) {
     view = s;     // expected-warning {{stack memory associated with parameter 
's' escapes to the field 'view' which will dangle}}
-    p = s.data(); // expected-warning {{stack memory associated with parameter 
's' escapes to the field 'p' which will dangle}}
+    p = s.data(); // expected-warning {{stack memory associated with parameter 
's' escapes to the field 'p' which will dangle}} \
+                  // expected-note {{result of call to 'data' aliases the 
storage of parameter 's'}}
   }
 
   void setWithParamAndReturn(std::string s) {
     view = s;     // expected-warning {{stack memory associated with parameter 
's' escapes to the field 'view' which will dangle}}
-    p = s.data(); // expected-warning {{stack memory associated with parameter 
's' escapes to the field 'p' which will dangle}}
+    p = s.data(); // expected-warning {{stack memory associated with parameter 
's' escapes to the field 'p' which will dangle}} \
+                  // expected-note {{result of call to 'data' aliases the 
storage of parameter 's'}}
     return;
   }
 
@@ -124,13 +128,15 @@ struct MemberSetters {
   void setWithLocal() {
     std::string s;
     view = s;     // expected-warning {{stack memory associated with local 
variable 's' escapes to the field 'view' which will dangle}}
-    p = s.data(); // expected-warning {{stack memory associated with local 
variable 's' escapes to the field 'p' which will dangle}}
+    p = s.data(); // expected-warning {{stack memory associated with local 
variable 's' escapes to the field 'p' which will dangle}} \
+                  // expected-note {{result of call to 'data' aliases the 
storage of local variable 's'}}
   }
   
   void setWithLocalButMoved() {
     std::string s;
     view = s;                 // expected-warning-re {{stack memory associated 
with local variable 's' may escape to the field 'view' which will dangle. 
{{.*}} may have been moved}}
-    p = s.data();             // expected-warning-re {{stack memory associated 
with local variable 's' may escape to the field 'p' which will dangle. {{.*}} 
may have been moved}}
+    p = s.data();             // expected-warning-re {{stack memory associated 
with local variable 's' may escape to the field 'p' which will dangle. {{.*}} 
may have been moved}} \
+                              // expected-note {{result of call to 'data' 
aliases the storage of local variable 's'}}
     takeString(std::move(s)); // expected-note 2 {{potentially moved here}}
   }
 
@@ -154,14 +160,16 @@ struct MemberSetters {
 
     std::string local;
     view = local;     // expected-warning {{stack memory associated with local 
variable 'local' escapes to the field 'view' which will dangle}}
-    p = local.data(); // expected-warning {{stack memory associated with local 
variable 'local' escapes to the field 'p' which will dangle}}
+    p = local.data(); // expected-warning {{stack memory associated with local 
variable 'local' escapes to the field 'p' which will dangle}} \
+                      // expected-note {{result of call to 'data' aliases the 
storage of local variable 'local'}}
   }
 
   void use_after_scope() {
     {
       std::string local;
       view = local;     // expected-warning {{stack memory associated with 
local variable 'local' escapes to the field 'view' which will dangle}}
-      p = local.data(); // expected-warning {{stack memory associated with 
local variable 'local' escapes to the field 'p' which will dangle}}
+      p = local.data(); // expected-warning {{stack memory associated with 
local variable 'local' escapes to the field 'p' which will dangle}} \
+                        // expected-note {{result of call to 'data' aliases 
the storage of local variable 'local'}}
     }
     (void)view;
     (void)p;
@@ -241,7 +249,8 @@ struct HasUniquePtrField {
   std::unique_ptr<LifetimeBoundCtor> field; // tu-note {{this field dangles}}
 
   void setWithParam(MyObj obj) {
-    field = std::make_unique<LifetimeBoundCtor>(obj); // tu-warning {{stack 
memory associated with parameter 'obj' escapes to the field 'field' which will 
dangle}}
+    field = std::make_unique<LifetimeBoundCtor>(obj); // tu-warning {{stack 
memory associated with parameter 'obj' escapes to the field 'field' which will 
dangle}} \
+                                                      // tu-note {{result of 
call to 'make_unique<MakeUnique::LifetimeBoundCtor, MakeUnique::MyObj &>' 
aliases the storage of parameter 'obj'}}
   }
 };
 } // namespace MakeUnique
diff --git a/clang/test/Sema/LifetimeSafety/dangling-global.cpp 
b/clang/test/Sema/LifetimeSafety/dangling-global.cpp
index bd67a0100131f..586b595946e75 100644
--- a/clang/test/Sema/LifetimeSafety/dangling-global.cpp
+++ b/clang/test/Sema/LifetimeSafety/dangling-global.cpp
@@ -27,7 +27,7 @@ void invoke_function_with_side_effects() {
 void inlined() {
   int local;
   global = &local; // expected-warning {{stack memory associated with local 
variable 'local' escapes to the global variable 'global_backup' which will 
dangle}}
-  global_backup = global; 
+  global_backup = global; // expected-note {{global variable 'global' aliases 
the storage of local variable 'local'}}
   global = nullptr;
 }
 
diff --git a/clang/test/Sema/LifetimeSafety/invalidations.cpp 
b/clang/test/Sema/LifetimeSafety/invalidations.cpp
index 127e375bc023c..45cb7122c8859 100644
--- a/clang/test/Sema/LifetimeSafety/invalidations.cpp
+++ b/clang/test/Sema/LifetimeSafety/invalidations.cpp
@@ -576,7 +576,8 @@ struct SinkOwnerBorrow {
 struct SinkInteriorBorrow {
   const char *dest_; // expected-note {{this field dangles}}
 
-  SinkInteriorBorrow(std::string *dest, int n) : dest_(dest->data()) { // 
expected-warning {{parameter 'dest' escapes to the field 'dest_' and is later 
invalidated}}
+  SinkInteriorBorrow(std::string *dest, int n) : dest_(dest->data()) { // 
expected-warning {{parameter 'dest' escapes to the field 'dest_' and is later 
invalidated}} \
+                                                                       // 
expected-note {{result of call to 'data' aliases the storage of parameter 
'dest'}}
     if (n > 0)
       dest->clear(); // expected-note {{parameter 'dest' is invalidated here}}
   }
@@ -594,12 +595,16 @@ struct S {
 
   void InvalidatedFieldLocalVector() {
     std::vector<std::string> strings;
-    FieldFromLocalVector = *strings.begin(); // expected-warning {{local 
variable 'strings' escapes to the field 'FieldFromLocalVector' and is later 
invalidated}}
+    FieldFromLocalVector = *strings.begin(); // expected-warning {{local 
variable 'strings' escapes to the field 'FieldFromLocalVector' and is later 
invalidated}} \
+                                             // expected-note {{result of call 
to 'begin' aliases the storage of local variable 'strings'}} \
+                                             // expected-note {{expression 
aliases the storage of local variable 'strings'}}
     strings.push_back("1"); // expected-note {{local variable 'strings' is 
invalidated here}}
   }
 
   void InvalidatedFieldByValueParamVector(std::vector<std::string> strings) {
-    FieldFromByValueParamVector = *strings.begin(); // expected-warning 
{{parameter 'strings' escapes to the field 'FieldFromByValueParamVector' and is 
later invalidated}}
+    FieldFromByValueParamVector = *strings.begin(); // expected-warning 
{{parameter 'strings' escapes to the field 'FieldFromByValueParamVector' and is 
later invalidated}} \
+                                                    // expected-note {{result 
of call to 'begin' aliases the storage of parameter 'strings'}} \
+                                                    // expected-note 
{{expression aliases the storage of parameter 'strings'}}
     strings.push_back("1"); // expected-note {{parameter 'strings' is 
invalidated here}}
   }
 
@@ -621,7 +626,7 @@ struct S {
 
   void InvalidatedFieldDelete() {
     int *p = new int; // expected-warning {{allocated object escapes to the 
field 'FieldFromNew' and is later invalidated}}
-    FieldFromNew = p;
+    FieldFromNew = p; // expected-note {{local variable 'p' aliases the 
storage of allocated object}}
     delete p; // expected-note {{allocated object is freed here}}
   }
 
@@ -654,7 +659,9 @@ struct S {
 
 void InvalidatedGlobalLocalVector() {
   std::vector<std::string> strings;
-  GlobalFromLocalVector = *strings.begin(); // expected-warning {{local 
variable 'strings' escapes to the global variable 'GlobalFromLocalVector' and 
is later invalidated}}
+  GlobalFromLocalVector = *strings.begin(); // expected-warning {{local 
variable 'strings' escapes to the global variable 'GlobalFromLocalVector' and 
is later invalidated}} \
+                                            // expected-note {{result of call 
to 'begin' aliases the storage of local variable 'strings'}} \
+                                            // expected-note {{expression 
aliases the storage of local variable 'strings'}}
   strings.push_back("1"); // expected-note {{local variable 'strings' is 
invalidated here}}
 }
 
@@ -670,7 +677,7 @@ void InvalidatedGlobalRefParamString(std::string &s) { // 
expected-warning {{par
 
 void InvalidatedGlobalDelete() {
   int *p = new int; // expected-warning {{allocated object escapes to the 
global variable 'GlobalFromNew' and is later invalidated}}
-  GlobalFromNew = p;
+  GlobalFromNew = p; // expected-note {{local variable 'p' aliases the storage 
of allocated object}}
   delete p; // expected-note {{allocated object is freed here}}
 }
 
diff --git a/clang/test/Sema/LifetimeSafety/nocfg.cpp 
b/clang/test/Sema/LifetimeSafety/nocfg.cpp
index b9a6150daf712..afab3509fd4c9 100644
--- a/clang/test/Sema/LifetimeSafety/nocfg.cpp
+++ b/clang/test/Sema/LifetimeSafety/nocfg.cpp
@@ -180,7 +180,8 @@ struct LifetimeBoundCtor {
 };
 
 auto lifetimebound_make_unique_single_param() {
-  return std::make_unique<LifetimeBoundCtor>(MyIntOwner{}); // tu-warning 
{{stack memory associated with temporary object is returned}} tu-note 
{{returned here}}
+  return std::make_unique<LifetimeBoundCtor>(MyIntOwner{}); // tu-warning 
{{stack memory associated with temporary object is returned}} tu-note 
{{returned here}} \
+                                                            // tu-note 
{{result of call to 'make_unique<LifetimeBoundCtor, MyIntOwner>' aliases the 
storage of temporary object}}
 }
 
 
@@ -257,14 +258,16 @@ std::string_view containerWithAnnotatedElements() {
 
   std::vector<std::string> local;
   return local.at(0); // expected-warning {{address of stack memory associated 
with local variable}} \
-                      // cfg-warning {{stack memory associated with local 
variable 'local' is returned}} cfg-note {{returned here}}
+                      // cfg-warning {{stack memory associated with local 
variable 'local' is returned}} cfg-note {{returned here}} \
+                      // cfg-note {{result of call to 'at' aliases the storage 
of local variable 'local'}}
 }
 
 std::string_view localUniquePtr(int i) {
   std::unique_ptr<std::string> c1;
   if (i)
     return *c1; // expected-warning {{address of stack memory associated with 
local variable}} \
-                // cfg-warning {{stack memory associated with local variable 
'c1' is returned}} cfg-note {{returned here}}
+                // cfg-warning {{stack memory associated with local variable 
'c1' is returned}} cfg-note {{returned here}} \
+                // cfg-note {{expression aliases the storage of local variable 
'c1'}}
   std::unique_ptr<std::string_view> c2;
   return *c2; // expect no-warning.
 }
@@ -273,7 +276,8 @@ std::string_view localOptional(int i) {
   std::optional<std::string> o;
   if (i)
     return o.value(); // expected-warning {{address of stack memory associated 
with local variable}} \
-                      // cfg-warning {{stack memory associated with local 
variable 'o' is returned}} cfg-note {{returned here}}
+                      // cfg-warning {{stack memory associated with local 
variable 'o' is returned}} cfg-note {{returned here}} \
+                      // cfg-note {{result of call to 'value' aliases the 
storage of local variable 'o'}}
   std::optional<std::string_view> abc;
   return abc.value(); // expect no warning
 }
@@ -297,14 +301,16 @@ int *danglingUniquePtrFromTemp2() {
 
 const int& danglingRefToOptionalFromTemp3() {
   return std::optional<int>().value(); // expected-warning {{returning 
reference to local temporary object}} \
-                                       // cfg-warning {{stack memory 
associated with temporary object is returned}} cfg-note {{returned here}}
+                                       // cfg-warning {{stack memory 
associated with temporary object is returned}} cfg-note {{returned here}} \
+                                       // cfg-note {{result of call to 'value' 
aliases the storage of temporary object}}
 }
 
 std::optional<std::string> getTempOptStr();
 
 std::string_view danglingRefToOptionalFromTemp4() {
   return getTempOptStr().value(); // expected-warning {{returning address of 
local temporary object}} \
-                                  // cfg-warning {{stack memory associated 
with temporary object is returned}} cfg-note {{returned here}}
+                                  // cfg-warning {{stack memory associated 
with temporary object is returned}} cfg-note {{returned here}} \
+                                  // cfg-note {{result of call to 'value' 
aliases the storage of temporary object}}
 }
 
 void danglingReferenceFromTempOwner() {
@@ -356,7 +362,8 @@ int &usedToBeFalsePositive(std::vector<int> &v) {
 int &doNotFollowReferencesForLocalOwner() {
 // Warning caught by CFG analysis.
   std::unique_ptr<int> localOwner;
-  int &p = *localOwner // cfg-warning {{stack memory associated with local 
variable 'localOwner' is returned}}
+  int &p = *localOwner // cfg-warning {{stack memory associated with local 
variable 'localOwner' is returned}} \
+                       // cfg-note {{result of call to 'get' aliases the 
storage of local variable 'localOwner'}}
             .get();
   return p; // cfg-note {{returned here}}
 }
@@ -368,8 +375,10 @@ const char *trackThroughMultiplePointer() {
 
 struct X {
   X(std::unique_ptr<int> up) :
-    pointee(*up),             // cfg-warning {{may have been moved.}}
-    pointee2(up.get()),       // cfg-warning {{may have been moved.}}
+    pointee(*up),             // cfg-warning {{may have been moved.}} \
+                              // cfg-note {{expression aliases the storage of 
parameter 'up'}}
+    pointee2(up.get()),       // cfg-warning {{may have been moved.}} \
+                              // cfg-note {{result of call to 'get' aliases 
the storage of parameter 'up'}}
     pointer(std::move(up)) {} // cfg-note 2 {{potentially moved here}}
   int &pointee;               // cfg-note {{this field dangles}}
   int *pointee2;              // cfg-note {{this field dangles}}
@@ -383,7 +392,8 @@ struct X2 {
   // A common usage that moves the passing owner to the class.
   // verify a strict warning on this case.
   X2(XOwner owner) :
-    pointee(owner.get()),       // cfg-warning {{may have been moved.}}
+    pointee(owner.get()),       // cfg-warning {{may have been moved.}} \
+                                // cfg-note {{result of call to 'get' aliases 
the storage of parameter 'owner'}}
     owner(std::move(owner)) {}  // cfg-note {{potentially moved here}}
   int* pointee;                 // cfg-note {{this field dangles}}
   XOwner owner;
@@ -457,11 +467,17 @@ std::vector<std::string_view> GetTemporaryView();
 
 std::string_view test_str_local() {
   std::vector<std::string> v;
-  return *std::find(v.begin(), // cfg-warning {{stack memory associated with 
local variable 'v' is returned}} cfg-note {{returned here}}
+  return *std::find(v.begin(), // cfg-warning {{stack memory associated with 
local variable 'v' is returned}} cfg-note {{returned here}} \
+                               // cfg-note {{result of call to 'begin' aliases 
the storage of local variable 'v'}} \
+                               // cfg-note {{result of call to 
'find<__gnu_cxx::basic_iterator<std::basic_string<char>>, char[3]>' aliases the 
storage of local variable 'v'}} \
+                               // cfg-note {{expression aliases the storage of 
local variable 'v'}}
                     v.end(), "42");
 }
 std::string_view test_str_temporary() {
-  return *std::find(GetTemporaryString().begin(), // cfg-warning {{stack 
memory associated with temporary object is returned}} cfg-note {{returned here}}
+  return *std::find(GetTemporaryString().begin(), // cfg-warning {{stack 
memory associated with temporary object is returned}} cfg-note {{returned 
here}} \
+                                                  // cfg-note {{result of call 
to 'begin' aliases the storage of temporary object}} \
+                                                  // cfg-note {{result of call 
to 'find<__gnu_cxx::basic_iterator<std::basic_string<char>>, char[3]>' aliases 
the storage of temporary object}} \
+                                                  // cfg-note {{expression 
aliases the storage of temporary object}}
                     GetTemporaryString().end(), "42");
 }
 std::string_view test_view() {
@@ -597,9 +613,11 @@ FooView test3(int i, std::optional<Foo> a) {
   if (i)
     return *a; // expected-warning {{address of stack memory}} \
                // cfg-warning {{stack memory associated with parameter 'a' is 
returned}} \
+               // cfg-note {{expression aliases the storage of parameter 'a'}} 
\
                // cfg-note {{returned here}}
   return a.value(); // expected-warning {{address of stack memory}} \
                     // cfg-warning {{stack memory associated with parameter 
'a' is returned}} \
+                    // cfg-note {{result of call to 'value' aliases the 
storage of parameter 'a'}} \
                     // cfg-note {{returned here}}
 }
 } // namespace GH93386
@@ -660,7 +678,8 @@ std::string_view test2() {
   std::string_view bad = StatusOr<Wrapper2<std::string_view>>().value(); // 
expected-warning {{temporary whose address is used as value of}}
   
   return k.value(); // expected-warning {{address of stack memory associated}} 
\
-                    // cfg-warning {{stack memory associated with local 
variable 'k' is returned}} cfg-note {{returned here}}
+                    // cfg-warning {{stack memory associated with local 
variable 'k' is returned}} cfg-note {{returned here}} \
+                    // cfg-note {{result of call to 'value' aliases the 
storage of local variable 'k'}}
 }
 } // namespace GH108272
 
@@ -812,7 +831,8 @@ std::vector<int*> test8(StatusOr<std::vector<int*>> aa) {
 // Pointer<Pointer> from Owner<Owner<Pointer>>
 Span<int*> test9(StatusOr<std::vector<int*>> aa) {
   return aa.valueLB(); // expected-warning {{address of stack memory 
associated}} \
-                       // cfg-warning {{stack memory associated with parameter 
'aa' is returned}} cfg-note {{returned here}}
+                       // cfg-warning {{stack memory associated with parameter 
'aa' is returned}} cfg-note {{returned here}} \
+                       // cfg-note {{result of call to 'valueLB' aliases the 
storage of parameter 'aa'}}
   return aa.valueNoLB(); // OK.
 }
 
@@ -821,7 +841,8 @@ Span<int*> test9(StatusOr<std::vector<int*>> aa) {
 // Pointer<Owner>> from Owner<Owner>
 Span<std::string> test10(StatusOr<std::vector<std::string>> aa) {
   return aa.valueLB(); // expected-warning {{address of stack memory}} \
-                       // cfg-warning {{stack memory associated with parameter 
'aa' is returned}} cfg-note {{returned here}}
+                       // cfg-warning {{stack memory associated with parameter 
'aa' is returned}} cfg-note {{returned here}} \
+                       // cfg-note {{result of call to 'valueLB' aliases the 
storage of parameter 'aa'}}
   return aa.valueNoLB(); // OK.
 }
 
@@ -879,7 +900,8 @@ std::string_view test1_1() {
                            // cfg-note {{result of call to 'Ref' aliases the 
storage of temporary object}}
   use(t1);                 // cfg-note {{later used here}}
   return Ref(std::string()); // expected-warning {{returning address}} \
-                             // cfg-warning {{stack memory associated with 
temporary object is returned}} cfg-note {{returned here}}
+                             // cfg-warning {{stack memory associated with 
temporary object is returned}} cfg-note {{returned here}} \
+                             // cfg-note {{result of call to 'Ref' aliases the 
storage of temporary object}}
 }
 
 std::string_view test1_2() {
@@ -933,7 +955,8 @@ std::string_view test2_1(Foo<std::string> r1, 
Foo<std::string_view> r2) {
                                  // cfg-note {{result of call to 'get' aliases 
the storage of temporary object}}
   use(t1);                       // cfg-note {{later used here}}
   return r1.get(); // expected-warning {{address of stack}} \
-                   // cfg-warning {{stack memory associated with parameter 
'r1' is returned}} cfg-note {{returned here}}
+                   // cfg-warning {{stack memory associated with parameter 
'r1' is returned}} cfg-note {{returned here}} \
+                   // cfg-note {{result of call to 'get' aliases the storage 
of parameter 'r1'}}
 }
 std::string_view test2_2(Foo<std::string> r1, Foo<std::string_view> r2) {
   std::string_view t2 = Foo<std::string_view>().get();
@@ -1000,15 +1023,19 @@ void test4() {
 
 namespace range_based_for_loop_variables {
 std::string_view test_view_loop_var(std::vector<std::string> strings) {
-  for (std::string_view s : strings) {  // cfg-warning {{stack memory 
associated with parameter 'strings' is returned}}
-    return s; //cfg-note {{returned here}}
+  for (std::string_view s : strings) {  // cfg-warning {{stack memory 
associated with parameter 'strings' is returned}} \
+                                        // cfg-note {{result of call to 
'begin' aliases the storage of parameter 'strings'}}
+    return s; // cfg-note {{returned here}} \
+              // cfg-note {{local variable 's' aliases the storage of 
parameter 'strings'}}
   }
   return "";
 }
 
 const char* test_view_loop_var_with_data(std::vector<std::string> strings) {
-  for (std::string_view s : strings) {  // cfg-warning {{stack memory 
associated with parameter 'strings' is returned}}
-    return s.data(); //cfg-note {{returned here}}
+  for (std::string_view s : strings) {  // cfg-warning {{stack memory 
associated with parameter 'strings' is returned}} \
+                                        // cfg-note {{result of call to 
'begin' aliases the storage of parameter 'strings'}}
+    return s.data(); // cfg-note {{returned here}} \
+                     // cfg-note {{local variable 's' aliases the storage of 
parameter 'strings'}}
   }
   return "";
 }
@@ -1021,15 +1048,20 @@ std::string_view 
test_no_error_for_views(std::vector<std::string_view> views) {
 }
 
 std::string_view test_string_ref_var(std::vector<std::string> strings) {
-  for (const std::string& s : strings) {  // cfg-warning {{stack memory 
associated with parameter 'strings' is returned}}
-    return s; //cfg-note {{returned here}}
+  for (const std::string& s : strings) {  // cfg-warning {{stack memory 
associated with parameter 'strings' is returned}} \
+                                          // cfg-note {{result of call to 
'begin' aliases the storage of parameter 'strings'}}
+    return s; // cfg-note {{returned here}} \
+              // cfg-note {{expression aliases the storage of parameter 
'strings'}}
   }
   return "";
 }
 
 std::string_view test_opt_strings(std::optional<std::vector<std::string>> 
strings_or) {
-  for (const std::string& s : *strings_or) {  // cfg-warning {{stack memory 
associated with parameter 'strings_or' is returned}}
-    return s; //cfg-note {{returned here}}
+  for (const std::string& s : *strings_or) {  // cfg-warning {{stack memory 
associated with parameter 'strings_or' is returned}} \
+                                              // cfg-note {{expression aliases 
the storage of parameter 'strings_or'}} \
+                                              // cfg-note {{result of call to 
'begin' aliases the storage of parameter 'strings_or'}}
+    return s; // cfg-note {{returned here}} \
+              // cfg-note {{expression aliases the storage of parameter 
'strings_or'}}
   }
   return "";
 }
@@ -1038,7 +1070,10 @@ std::string_view 
test_opt_strings(std::optional<std::vector<std::string>> string
 namespace iterator_arrow {
 std::string_view test() {
   std::vector<std::string> strings;
-  return strings.begin()->data(); // cfg-warning {{stack memory associated 
with local variable 'strings' is returned}} cfg-note {{returned here}}
+  return strings.begin()->data(); // cfg-warning {{stack memory associated 
with local variable 'strings' is returned}} cfg-note {{returned here}} \
+                                  // cfg-note {{result of call to 'begin' 
aliases the storage of local variable 'strings'}} \
+                                  // cfg-note {{expression aliases the storage 
of local variable 'strings'}} \
+                                  // cfg-note {{result of call to 'data' 
aliases the storage of local variable 'strings'}}
 }
 
 void operator_star_arrow_reference() {
@@ -1168,7 +1203,8 @@ struct Foo2 {
 };
 
 struct Test {
-  Test(Foo2 foo) : bar(foo.bar.get()),  // cfg-warning-re {{stack memory 
associated with parameter 'foo' may escape to the field 'bar' which will 
dangle. {{.*}} may have been moved}}
+  Test(Foo2 foo) : bar(foo.bar.get()),  // cfg-warning-re {{stack memory 
associated with parameter 'foo' may escape to the field 'bar' which will 
dangle. {{.*}} may have been moved}} \
+                                        // cfg-note {{result of call to 'get' 
aliases the storage of parameter 'foo'}}
       storage(std::move(foo.bar)) {};   // cfg-note {{potentially moved here}}
 
   Bar* bar; // cfg-note {{this field dangles}}
@@ -1187,7 +1223,8 @@ struct StatusOr {
 const char* foo() {
   StatusOr<std::string> s;
   return s->data(); // expected-warning {{address of stack memory associated 
with local variable}} \
-                    // cfg-warning {{stack memory associated with local 
variable 's' is returned}} cfg-note {{returned here}}
+                    // cfg-warning {{stack memory associated with local 
variable 's' is returned}} cfg-note {{returned here}} \
+                    // cfg-note {{expression aliases the storage of local 
variable 's'}}
 
   StatusOr<std::string_view> s2;
   return s2->data();
diff --git a/clang/test/Sema/LifetimeSafety/safety-c.c 
b/clang/test/Sema/LifetimeSafety/safety-c.c
index 42adbbb3f0628..ddab01d531ad5 100644
--- a/clang/test/Sema/LifetimeSafety/safety-c.c
+++ b/clang/test/Sema/LifetimeSafety/safety-c.c
@@ -181,7 +181,8 @@ void *void_pointer_dereference(void) {
 int *atomic_pointer_declref(void) {
   int value;
   _Atomic(int *) p = &value; // expected-warning {{stack memory associated 
with local variable 'value' is returned}}
-  return p;                  // expected-note {{returned here}}
+  return p;                  // expected-note {{returned here}} \
+                             // expected-note {{local variable 'p' aliases the 
storage of local variable 'value'}}
 }
 
 int *atomic_pointer_static(void) {
@@ -193,7 +194,8 @@ int *atomic_pointer_static(void) {
 int **atomic_pointer_multilevel(void) {
   int *inner;
   _Atomic(int **) p = &inner; // expected-warning {{stack memory associated 
with local variable 'inner' is returned}}
-  return p;                   // expected-note {{returned here}}
+  return p;                   // expected-note {{returned here}} \
+                              // expected-note {{local variable 'p' aliases 
the storage of local variable 'inner'}}
 }
 
 // In C, a pointer compound assignment is a prvalue; its result still carries
diff --git a/clang/test/Sema/LifetimeSafety/safety.cpp 
b/clang/test/Sema/LifetimeSafety/safety.cpp
index f3b042cce74b2..042138cb979d2 100644
--- a/clang/test/Sema/LifetimeSafety/safety.cpp
+++ b/clang/test/Sema/LifetimeSafety/safety.cpp
@@ -531,7 +531,8 @@ View conditional_assign_both_branches(const MyObj& safe, 
bool c) {
   else {
     p = safe;
   }
-  return p;     // expected-note {{returned here}}
+  return p;     // expected-note {{returned here}} \
+                // expected-note {{local variable 'p' aliases the storage of 
local variable 's'}}
 
 }
 
@@ -539,14 +540,16 @@ View reassign_safe_to_local(const MyObj& safe) {
   MyObj local;
   View p = safe;
   p = local;    // expected-warning {{stack memory associated with local 
variable 'local' is returned}}
-  return p;     // expected-note {{returned here}}
+  return p;     // expected-note {{returned here}} \
+                // expected-note {{local variable 'p' aliases the storage of 
local variable 'local'}}
 }
 
 View pointer_chain_to_local() {
   MyObj local;
   View p1 = local;     // expected-warning {{stack memory associated with 
local variable 'local' is returned}}
-  View p2 = p1; 
-  return p2;          // expected-note {{returned here}}
+  View p2 = p1;       // expected-note {{local variable 'p1' aliases the 
storage of local variable 'local'}}
+  return p2;          // expected-note {{returned here}} \
+                      // expected-note {{local variable 'p2' aliases the 
storage of local variable 'local'}}
 }
 
 View multiple_assign_multiple_return(const MyObj& safe, bool c1, bool c2) {
@@ -555,11 +558,13 @@ View multiple_assign_multiple_return(const MyObj& safe, 
bool c1, bool c2) {
   View p;
   if (c1) {
     p = local1;       // expected-warning {{stack memory associated with local 
variable 'local1' is returned}}
-    return p;         // expected-note {{returned here}}
+    return p;         // expected-note {{returned here}} \
+                      // expected-note {{local variable 'p' aliases the 
storage of local variable 'local1'}}
   }
   else if (c2) {
     p = local2;       // expected-warning {{stack memory associated with local 
variable 'local2' is returned}}
-    return p;         // expected-note {{returned here}}
+    return p;         // expected-note {{returned here}} \
+                      // expected-note {{local variable 'p' aliases the 
storage of local variable 'local2'}}
   }
   p = safe;
   return p;
@@ -578,7 +583,9 @@ View multiple_assign_single_return(const MyObj& safe, bool 
c1, bool c2) {
   else {
     p = safe;
   }
-  return p;         // expected-note 2 {{returned here}}
+  return p;         // expected-note 2 {{returned here}} \
+                    // expected-note {{local variable 'p' aliases the storage 
of local variable 'local1'}} \
+                    // expected-note {{local variable 'p' aliases the storage 
of local variable 'local2'}}
 }
 
 View direct_return_of_local() {
@@ -646,7 +653,8 @@ const int* return_pointer_to_parameter_via_reference(int a, 
int b, bool cond) {
 
 const int& return_pointer_to_parameter_via_reference_1(int a) {
     const int* d = &a; // expected-warning {{stack memory associated with 
parameter 'a' is returned}}
-    return *d;    // expected-note {{returned here}}
+    return *d;    // expected-note {{returned here}} \
+                  // expected-note {{local variable 'd' aliases the storage of 
parameter 'a'}}
 }
 
 const int& get_ref_to_local() {
@@ -680,7 +688,8 @@ struct PtrHolder {
 
 int* const& test_ref_to_ptr() {
   PtrHolder a;
-  int *const &ref = a.getRef();  // expected-warning {{stack memory associated 
with local variable 'a' is returned}}
+  int *const &ref = a.getRef();  // expected-warning {{stack memory associated 
with local variable 'a' is returned}} \
+                                 // expected-note {{result of call to 'getRef' 
aliases the storage of local variable 'a'}}
   return ref;  // expected-note {{returned here}}
 }
 int* const test_ref_to_ptr_no_error() {
@@ -741,7 +750,8 @@ View uar_before_uaf(const MyObj& safe, bool c) {
     MyObj local_obj; 
     p = local_obj;  // expected-warning {{stack memory associated with local 
variable 'local_obj' is returned}}
     if (c) {
-      return p;     // expected-note {{returned here}}
+      return p;     // expected-note {{returned here}} \
+                    // expected-note {{local variable 'p' aliases the storage 
of local variable 'local_obj'}}
     }
   }
   p.use();
@@ -1620,11 +1630,13 @@ void range_based_for_use_after_scope() {
 
 View range_based_for_use_after_return() {
   MyObjStorage s;
-  for (const MyObj &o : s) { // expected-warning {{stack memory associated 
with local variable 's' is returned}}
+  for (const MyObj &o : s) { // expected-warning {{stack memory associated 
with local variable 's' is returned}} \
+                             // expected-note {{local variable '__range1' 
aliases the storage of local variable 's'}}
     return o;  // expected-note {{returned here}}
   }
-  return *s.begin();  // expected-warning {{stack memory associated with local 
variable 's' is returned}}
-                      // expected-note@-1 {{returned here}}
+  return *s.begin();  // expected-warning {{stack memory associated with local 
variable 's' is returned}} \
+                      // expected-note {{result of call to 'begin' aliases the 
storage of local variable 's'}} \
+                      // expected-note {{returned here}}
 }
 
 void range_based_for_not_reference() {
@@ -1740,16 +1752,20 @@ T&& MaxT(T&& a [[clang::lifetimebound]], T&& b 
[[clang::lifetimebound]]);
 
 const MyObj& call_max_with_obj() {
   MyObj oa, ob;
-  return  MaxT(oa,    // expected-warning {{stack memory associated with local 
variable 'oa' is returned}}
-                      // expected-note@-1 2 {{returned here}}
+  return  MaxT(oa,    // expected-warning {{stack memory associated with local 
variable 'oa' is returned}} \
+                      // expected-note {{result of call to 'MaxT<MyObj &>' 
aliases the storage of local variable 'oa'}} \
+                      // expected-note {{result of call to 'MaxT<MyObj &>' 
aliases the storage of local variable 'ob'}} \
+                      // expected-note 2 {{returned here}}
                ob);   // expected-warning {{stack memory associated with local 
variable 'ob' is returned}}
                     
 }
 
 MyObj* call_max_with_obj_error() {
   MyObj oa, ob;
-  return  &MaxT(oa,   // expected-warning {{stack memory associated with local 
variable 'oa' is returned}}
-                      // expected-note@-1 2 {{returned here}}
+  return  &MaxT(oa,   // expected-warning {{stack memory associated with local 
variable 'oa' is returned}} \
+                      // expected-note {{result of call to 'MaxT<MyObj &>' 
aliases the storage of local variable 'oa'}} \
+                      // expected-note {{result of call to 'MaxT<MyObj &>' 
aliases the storage of local variable 'ob'}} \
+                      // expected-note 2 {{returned here}}
                 ob);  // expected-warning {{stack memory associated with local 
variable 'ob' is returned}}
 }
 
@@ -1757,7 +1773,9 @@ const MyObj* call_max_with_ref_obj_error() {
   MyObj oa, ob;
   const MyObj& refa = oa;     // expected-warning {{stack memory associated 
with local variable 'oa' is returned}}
   const MyObj& refb = ob;     // expected-warning {{stack memory associated 
with local variable 'ob' is returned}}
-  return  &MaxT(refa, refb);  // expected-note 2 {{returned here}}
+  return  &MaxT(refa, refb);  // expected-note 2 {{returned here}} \
+                              // expected-note {{result of call to 'MaxT<const 
MyObj &>' aliases the storage of local variable 'oa'}} \
+                              // expected-note {{result of call to 'MaxT<const 
MyObj &>' aliases the storage of local variable 'ob'}}
 }
 const MyObj& call_max_with_ref_obj_return_ref_error() {
   MyObj oa, ob;
@@ -1777,8 +1795,10 @@ const MyObj& call_max_with_ref_obj_no_error(const MyObj& 
a, const MyObj& b) {
 
 const View& call_max_with_view_with_error() {
   View va, vb;
-  return MaxT(va,   // expected-warning {{stack memory associated with local 
variable 'va' is returned}}
-                    // expected-note@-1 2 {{returned here}}
+  return MaxT(va,   // expected-warning {{stack memory associated with local 
variable 'va' is returned}} \
+                    // expected-note {{result of call to 'MaxT<View &>' 
aliases the storage of local variable 'va'}} \
+                    // expected-note {{result of call to 'MaxT<View &>' 
aliases the storage of local variable 'vb'}} \
+                    // expected-note 2 {{returned here}}
               vb);  // expected-warning {{stack memory associated with local 
variable 'vb' is returned}}
 }
 
@@ -1786,8 +1806,10 @@ struct [[gsl::Pointer]] NonTrivialPointer  { 
~NonTrivialPointer(); };
 
 const NonTrivialPointer& call_max_with_non_trivial_view_with_error() {
   NonTrivialPointer va, vb;
-  return MaxT(va,   // expected-warning {{stack memory associated with local 
variable 'va' is returned}}
-                    // expected-note@-1 2 {{returned here}}
+  return MaxT(va,   // expected-warning {{stack memory associated with local 
variable 'va' is returned}} \
+                    // expected-note {{result of call to 
'MaxT<MaxFnLifetimeBound::NonTrivialPointer &>' aliases the storage of local 
variable 'va'}} \
+                    // expected-note {{result of call to 
'MaxT<MaxFnLifetimeBound::NonTrivialPointer &>' aliases the storage of local 
variable 'vb'}} \
+                    // expected-note 2 {{returned here}}
               vb);  // expected-warning {{stack memory associated with local 
variable 'vb' is returned}}
 }
 
@@ -1949,24 +1971,32 @@ void bar() {
 namespace DereferenceViews {
 const MyObj& testDeref(MyObj obj) {
   View v = obj; // expected-warning {{stack memory associated with parameter 
'obj' is returned}}
-  return *v;    // expected-note {{returned here}}
+  return *v;    // expected-note {{returned here}} \
+                // expected-note {{local variable 'v' aliases the storage of 
parameter 'obj'}}
 }
 const MyObj* testDerefAddr(MyObj obj) {
   View v = obj; // expected-warning {{stack memory associated with parameter 
'obj' is returned}}
-  return &*v;   // expected-note {{returned here}}
+  return &*v;   // expected-note {{returned here}} \
+                // expected-note {{local variable 'v' aliases the storage of 
parameter 'obj'}} \
+                // expected-note {{expression aliases the storage of parameter 
'obj'}}
 }
 const MyObj* testData(MyObj obj) {
   View v = obj;     // expected-warning {{stack memory associated with 
parameter 'obj' is returned}}
-  return v.data();  // expected-note {{returned here}}
+  return v.data();  // expected-note {{returned here}} \
+                    // expected-note {{local variable 'v' aliases the storage 
of parameter 'obj'}}
 }
 const int* testLifetimeboundAccessorOfMyObj(MyObj obj) {
   View v = obj;           // expected-warning {{stack memory associated with 
parameter 'obj' is returned}}
-  const MyObj* ptr = v.data();
-  return ptr->getData();  // expected-note {{returned here}}
+  const MyObj* ptr = v.data(); // expected-note {{local variable 'v' aliases 
the storage of parameter 'obj'}} \
+                               // expected-note {{result of call to 'data' 
aliases the storage of parameter 'obj'}}
+  return ptr->getData();  // expected-note {{returned here}} \
+                          // expected-note {{local variable 'ptr' aliases the 
storage of parameter 'obj'}}
 }
 const int* testLifetimeboundAccessorOfMyObjThroughDeref(MyObj obj) {
   View v = obj;         // expected-warning {{stack memory associated with 
parameter 'obj' is returned}}
-  return v->getData();  // expected-note {{returned here}}
+  return v->getData();  // expected-note {{returned here}} \
+                        // expected-note {{local variable 'v' aliases the 
storage of parameter 'obj'}} \
+                        // expected-note {{expression aliases the storage of 
parameter 'obj'}}
 }
 } // namespace DereferenceViews
 
@@ -1989,18 +2019,22 @@ It end() const [[clang::lifetimebound]];
 MyObj Global;
 
 const MyObj& ContainerMyObjReturnRef(Container<MyObj> c) {
-  for (const MyObj& x : c) {  // expected-warning {{stack memory associated 
with parameter 'c' is returned}}
+  for (const MyObj& x : c) {  // expected-warning {{stack memory associated 
with parameter 'c' is returned}} \
+                              // expected-note {{local variable '__range1' 
aliases the storage of parameter 'c'}}
     return x;                 // expected-note {{returned here}}
   }
   return Global;
 }
 
 View ContainerMyObjReturnView(Container<MyObj> c) {
-  for (const MyObj& x : c) {  // expected-warning {{stack memory associated 
with parameter 'c' is returned}}
+  for (const MyObj& x : c) {  // expected-warning {{stack memory associated 
with parameter 'c' is returned}} \
+                              // expected-note {{local variable '__range1' 
aliases the storage of parameter 'c'}}
     return x;                 // expected-note {{returned here}}
   }
-  for (View x : c) {  // expected-warning {{stack memory associated with 
parameter 'c' is returned}}
-    return x;         // expected-note {{returned here}}
+  for (View x : c) {  // expected-warning {{stack memory associated with 
parameter 'c' is returned}} \
+                      // expected-note {{local variable '__range1' aliases the 
storage of parameter 'c'}}
+    return x;         // expected-note {{returned here}} \
+                      // expected-note {{local variable 'x' aliases the 
storage of parameter 'c'}}
   }
   return Global;
 }
@@ -2135,7 +2169,8 @@ struct RefMember {
 
 std::string_view refMemberReturnView1(RefMember a) { return a.str_ref; }
 std::string_view refMemberReturnView2(RefMember a) { return *a.str_ptr; }
-std::string_view refMemberReturnView3(RefMember a) { return a.str; } // 
expected-warning {{stack memory associated with parameter 'a' is returned}} 
expected-note {{returned here}}
+std::string_view refMemberReturnView3(RefMember a) { return a.str; } // 
expected-warning {{stack memory associated with parameter 'a' is returned}} 
expected-note {{returned here}} \
+                                                                     // 
expected-note {{expression aliases the storage of parameter 'a'}}
 std::string& refMemberReturnRef1(RefMember a) { return a.str_ref; }
 std::string& refMemberReturnRef2(RefMember a) { return *a.str_ptr; }
 std::string& refMemberReturnRef3(RefMember a) { return a.str; } // 
expected-warning {{stack memory associated with parameter 'a' is returned}} 
expected-note {{returned here}}
@@ -2262,7 +2297,8 @@ View test1(std::string a) {
 
 View test2(std::string a) {
   View b = View(a); // expected-warning {{stack memory associated with 
parameter 'a' is returned}}
-  return b;         // expected-note {{returned here}}
+  return b;         // expected-note {{returned here}} \
+                    // expected-note {{local variable 'b' aliases the storage 
of parameter 'a'}}
 }
 
 View test3(std::string a) {
@@ -2319,7 +2355,8 @@ namespace lambda_captures {
 auto return_ref_capture() {
   int local = 1;
   auto lambda = [&local]() { return local; }; // expected-warning {{stack 
memory associated with local variable 'local' is returned}}
-  return lambda; // expected-note {{returned here}}
+  return lambda; // expected-note {{returned here}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'local'}}
 }
 
 void safe_ref_capture() {
@@ -2337,8 +2374,9 @@ auto capture_int_by_value() {
 auto capture_view_by_value() {
   MyObj obj;
   View v(obj); // expected-warning {{stack memory associated with local 
variable 'obj' is returned}}
-  auto lambda = [v]() { return v; };
-  return lambda; // expected-note {{returned here}}
+  auto lambda = [v]() { return v; }; // expected-note {{local variable 'v' 
aliases the storage of local variable 'obj'}}
+  return lambda; // expected-note {{returned here}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'obj'}}
 }
 
 void capture_view_by_value_safe() {
@@ -2352,7 +2390,8 @@ auto capture_pointer_by_ref() {
   MyObj obj;
   MyObj* p = &obj;
   auto lambda = [&p]() { return p; }; // expected-warning {{stack memory 
associated with local variable 'p' is returned}}
-  return lambda; // expected-note {{returned here}}
+  return lambda; // expected-note {{returned here}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'p'}}
 }
 
 auto capture_multiple() {
@@ -2361,48 +2400,56 @@ auto capture_multiple() {
     &a,  // expected-warning {{stack memory associated with local variable 'a' 
is returned}}
     &b   // expected-warning {{stack memory associated with local variable 'b' 
is returned}}
   ]() { return a + b; };
-  return lambda; // expected-note 2 {{returned here}}
+  return lambda; // expected-note 2 {{returned here}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'a'}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'b'}}
 }
 
 auto capture_raw_pointer_by_value() {
   int x;
   int* p = &x; // expected-warning {{stack memory associated with local 
variable 'x' is returned}}
-  auto lambda = [p]() { return p; };
-  return lambda; // expected-note {{returned here}}
+  auto lambda = [p]() { return p; }; // expected-note {{local variable 'p' 
aliases the storage of local variable 'x'}}
+  return lambda; // expected-note {{returned here}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'x'}}
 }
 
 auto capture_raw_pointer_init_capture() {
   int x;
   int* p = &x; // expected-warning {{stack memory associated with local 
variable 'x' is returned}}
-  auto lambda = [q = p]() { return q; };
-  return lambda; // expected-note {{returned here}}
+  auto lambda = [q = p]() { return q; }; // expected-note {{local variable 'p' 
aliases the storage of local variable 'x'}}
+  return lambda; // expected-note {{returned here}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'x'}}
 }
 
 auto capture_view_init_capture() {
   MyObj obj;
   View v(obj); // expected-warning {{stack memory associated with local 
variable 'obj' is returned}}
-  auto lambda = [w = v]() { return w; };
-  return lambda; // expected-note {{returned here}}
+  auto lambda = [w = v]() { return w; }; // expected-note {{local variable 'v' 
aliases the storage of local variable 'obj'}}
+  return lambda; // expected-note {{returned here}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'obj'}}
 }
 
 auto capture_lambda() {
   int x;
   auto inner = [&x]() { return x; }; // expected-warning {{stack memory 
associated with local variable 'x' is returned}}
-  auto outer = [inner]() { return inner(); };
-  return outer; // expected-note {{returned here}}
+  auto outer = [inner]() { return inner(); }; // expected-note {{local 
variable 'inner' aliases the storage of local variable 'x'}}
+  return outer; // expected-note {{returned here}} \
+                // expected-note {{local variable 'outer' aliases the storage 
of local variable 'x'}}
 }
 
 auto return_copied_lambda() {
   int local = 1;
   auto lambda = [&local]() { return local; }; // expected-warning {{stack 
memory associated with local variable 'local' is returned}}
-  auto lambda_copy = lambda;
-  return lambda_copy; // expected-note {{returned here}}
+  auto lambda_copy = lambda; // expected-note {{local variable 'lambda' 
aliases the storage of local variable 'local'}}
+  return lambda_copy; // expected-note {{returned here}} \
+                      // expected-note {{local variable 'lambda_copy' aliases 
the storage of local variable 'local'}}
 }
 
 auto implicit_ref_capture() {
   int local = 1;
   auto lambda = [&]() { return local; }; // expected-warning {{stack memory 
associated with local variable 'local' is returned}}
-  return lambda; // expected-note {{returned here}}
+  return lambda; // expected-note {{returned here}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'local'}}
 }
 
 // TODO: Include the name of the variable in the diagnostic to improve
@@ -2411,14 +2458,17 @@ auto implicit_ref_capture() {
 auto implicit_ref_capture_multiple() {
   int local = 1, local2 = 2;
   auto lambda = [&]() { return local + local2; }; // expected-warning {{stack 
memory associated with local variable 'local2' is returned}} expected-warning 
{{stack memory associated with local variable 'local' is returned}}
-  return lambda; // expected-note 2 {{returned here}}
+  return lambda; // expected-note 2 {{returned here}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'local2'}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'local'}}
 }
 
 auto implicit_value_capture() {
   MyObj obj;
   View v(obj); // expected-warning {{stack memory associated with local 
variable 'obj' is returned}}
-  auto lambda = [=]() { return v; };
-  return lambda; // expected-note {{returned here}}
+  auto lambda = [=]() { return v; }; // expected-note {{local variable 'v' 
aliases the storage of local variable 'obj'}}
+  return lambda; // expected-note {{returned here}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'obj'}}
 }
 
 auto* pointer_to_lambda_outlives() {
@@ -2449,7 +2499,8 @@ auto capture_static_address_by_ref() {
   static int local = 1;
   int* p = &local;
   auto lambda = [&p]() { return p; }; // expected-warning {{stack memory 
associated with local variable 'p' is returned}}
-  return lambda; // expected-note {{returned here}}
+  return lambda; // expected-note {{returned here}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'p'}}
 }
 
 auto capture_multilevel_pointer() {
@@ -2457,8 +2508,13 @@ auto capture_multilevel_pointer() {
   int *p = &x; // expected-warning {{stack memory associated with local 
variable 'x' is returned}}
   int **q = &p; // expected-warning {{stack memory associated with local 
variable 'p' is returned}}
   int ***r = &q; // expected-warning {{stack memory associated with local 
variable 'q' is returned}}
-  auto lambda = [=]() { return *p + **q + ***r; };
-  return lambda; // expected-note 3 {{returned here}}
+  auto lambda = [=]() { return *p + **q + ***r; }; // expected-note {{local 
variable 'p' aliases the storage of local variable 'x'}} \
+                                                   // expected-note {{local 
variable 'q' aliases the storage of local variable 'p'}} \
+                                                   // expected-note {{local 
variable 'r' aliases the storage of local variable 'q'}}
+  return lambda; // expected-note 3 {{returned here}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'x'}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'p'}} \
+                 // expected-note {{local variable 'lambda' aliases the 
storage of local variable 'q'}}
 }
 } // namespace lambda_captures
 
@@ -2775,9 +2831,11 @@ void same_scope() {
 
 S copy_propagation() {
   std::string str{"abc"};
-  S a = getS(str); // expected-warning {{stack memory associated with local 
variable 'str' is returned}}
-  S b = a;
-  return b; // expected-note {{returned here}}
+  S a = getS(str); // expected-warning {{stack memory associated with local 
variable 'str' is returned}} \
+                   // expected-note {{result of call to 'getS' aliases the 
storage of local variable 'str'}}
+  S b = a;  // expected-note {{local variable 'a' aliases the storage of local 
variable 'str'}}
+  return b; // expected-note {{returned here}} \
+            // expected-note {{local variable 'b' aliases the storage of local 
variable 'str'}}
 }
 
 void assignment_propagation() {
@@ -2826,9 +2884,11 @@ S multiple_lifetimebound_params() {
   S s = getS2(str, std::string("temp")); // expected-warning {{stack memory 
associated with local variable 'str' is returned}} \
                                          // expected-warning {{temporary 
object does not live long enough}} \
                                          // expected-note {{result of call to 
'getS2' aliases the storage of temporary object}} \
+                                         // expected-note {{result of call to 
'getS2' aliases the storage of local variable 'str'}} \
                                          // expected-note {{temporary object 
is destroyed here}}
   return s;                              // expected-note {{returned here}} \
-                                         // expected-note {{later used here}}
+                                         // expected-note {{later used here}} \
+                                         // expected-note {{local variable 's' 
aliases the storage of local variable 'str'}}
 }
 
 // TODO: Diagnose [[clang::lifetimebound]] on functions whose return value
@@ -2852,7 +2912,8 @@ void from_template_instantiation() {
 
 struct FieldInitFromLifetimebound {
   S value; // expected-note {{this field dangles}}
-  FieldInitFromLifetimebound() : value(getS(std::string("temp"))) {} // 
expected-warning {{stack memory associated with temporary object escapes to the 
field 'value' which will dangle}}
+  FieldInitFromLifetimebound() : value(getS(std::string("temp"))) {} // 
expected-warning {{stack memory associated with temporary object escapes to the 
field 'value' which will dangle}} \
+                                                                     // 
expected-note {{result of call to 'getS' aliases the storage of temporary 
object}}
 };
 
 S S::return_self_after_registration() const {
@@ -2944,9 +3005,11 @@ DefaultedOuter getDefaultedOuter(const std::string &s 
[[clang::lifetimebound]]);
 // pattern does not fit the ownership model this analysis supports.
 DefaultedOuter nested_defaulted_outer_with_user_defined_inner() {
   std::string str{"abc"};
-  DefaultedOuter o = getDefaultedOuter(str); // expected-warning {{stack 
memory associated with local variable 'str' is returned}}
-  DefaultedOuter copy = o;
-  return copy; // expected-note {{returned here}}
+  DefaultedOuter o = getDefaultedOuter(str); // expected-warning {{stack 
memory associated with local variable 'str' is returned}} \
+                                             // expected-note {{result of call 
to 'getDefaultedOuter' aliases the storage of local variable 'str'}}
+  DefaultedOuter copy = o; // expected-note {{local variable 'o' aliases the 
storage of local variable 'str'}}
+  return copy; // expected-note {{returned here}} \
+               // expected-note {{local variable 'copy' aliases the storage of 
local variable 'str'}}
 }
 
 std::string_view getSV(S s [[clang::lifetimebound]]);
@@ -2992,9 +3055,12 @@ void owner_return_unique_ptr_s() {
 std::string_view return_dangling_view_through_owner() {
   std::string local;
   auto ups = getUniqueS(local);
-  S* s = ups.get(); // expected-warning {{stack memory associated with local 
variable 'ups' is returned}}
-  std::string_view sv = s->getData();
-  return sv; // expected-note {{returned here}}
+  S* s = ups.get(); // expected-warning {{stack memory associated with local 
variable 'ups' is returned}} \
+                    // expected-note {{result of call to 'get' aliases the 
storage of local variable 'ups'}}
+  std::string_view sv = s->getData(); // expected-note {{local variable 's' 
aliases the storage of local variable 'ups'}} \
+                                      // expected-note {{result of call to 
'getData' aliases the storage of local variable 'ups'}}
+  return sv; // expected-note {{returned here}} \
+             // expected-note {{local variable 'sv' aliases the storage of 
local variable 'ups'}}
 }
 
 void owner_outlives_lifetimebound_source() {
@@ -3082,7 +3148,8 @@ void binary_conditional_throw_void(int *in) {
 int *binary_conditional_throw_dangling() {
   int x;
   int *p = &x; // expected-warning {{stack memory associated with local 
variable 'x' is returned}}
-  return p ?: throw 1; // expected-note {{returned here}}
+  return p ?: throw 1; // expected-note {{returned here}} \
+                       // expected-note {{local variable 'p' aliases the 
storage of local variable 'x'}}
 }
 
 #endif
@@ -3106,12 +3173,14 @@ int *constexpr_dead_nested(int *num) {
 
 int *constexpr_live_false(int *num) {
   int local = 0;
-  return kFalse ? num : f(&local); // expected-warning {{stack memory 
associated with local variable 'local' is returned}} // expected-note 
{{returned here}}
+  return kFalse ? num : f(&local); // expected-warning {{stack memory 
associated with local variable 'local' is returned}} // expected-note 
{{returned here}} \
+                                   // expected-note {{result of call to 'f' 
aliases the storage of local variable 'local'}}
 }
 
 int *constexpr_live_nested(int *num) {
   int local = 0;
-  return kTrue ? (kFalse ? num : f(&local)) : num; // expected-warning {{stack 
memory associated with local variable 'local' is returned}} // expected-note 
{{returned here}}
+  return kTrue ? (kFalse ? num : f(&local)) : num; // expected-warning {{stack 
memory associated with local variable 'local' is returned}} // expected-note 
{{returned here}} \
+                                                   // expected-note {{result 
of call to 'f' aliases the storage of local variable 'local'}}
 }
 int *noreturn_dead_false(bool cond, int *num) {
   int local = 0;
@@ -3720,16 +3789,18 @@ std::function<void()> direct_return() {
 std::function<void()> copy_function() {
   int x;
   std::function<void()> f = [&x]() { (void)x; }; // expected-warning {{stack 
memory associated with local variable 'x' is returned}}
-  std::function<void()> f2 = f;
-  return f2; // expected-note {{returned here}}
+  std::function<void()> f2 = f; // expected-note {{local variable 'f' aliases 
the storage of local variable 'x'}}
+  return f2; // expected-note {{returned here}} \
+             // expected-note {{local variable 'f2' aliases the storage of 
local variable 'x'}}
 }
 
 std::function<void()> copy_assign() {
   int x;
   std::function<void()> f = [&x]() { (void)x; }; // expected-warning {{stack 
memory associated with local variable 'x' is returned}}
   std::function<void()> f2 = []() {};
-  f2 = f;
-  return f2; // expected-note {{returned here}}
+  f2 = f;    // expected-note {{local variable 'f' aliases the storage of 
local variable 'x'}}
+  return f2; // expected-note {{returned here}} \
+             // expected-note {{local variable 'f2' aliases the storage of 
local variable 'x'}}
 }
 
 std::function<void()> chained_copy_assign() {
@@ -3737,16 +3808,19 @@ std::function<void()> chained_copy_assign() {
   std::function<void()> f = [&x]() { (void)x; }; // expected-warning {{stack 
memory associated with local variable 'x' is returned}}
   std::function<void()> f2 = []() {};
   std::function<void()> f3 = []() {};
-  f3 = f2 = f;
-  return f3; // expected-note {{returned here}}
+  f3 = f2 = f; // expected-note {{local variable 'f' aliases the storage of 
local variable 'x'}} \
+               // expected-note {{expression aliases the storage of local 
variable 'x'}}
+  return f3;   // expected-note {{returned here}} \
+               // expected-note {{local variable 'f3' aliases the storage of 
local variable 'x'}}
 }
 
 std::function<void()> move_assign() {
   int x;
   std::function<void()> f = [&x]() { (void)x; }; // expected-warning {{stack 
memory associated with local variable 'x' is returned}}
   std::function<void()> f2 = []() {};
-  f2 = std::move(f);
-  return f2; // expected-note {{returned here}}
+  f2 = std::move(f); // expected-note {{result of call to 
'move<std::function<void ()> &>' aliases the storage of local variable 'x'}}
+  return f2; // expected-note {{returned here}} \
+             // expected-note {{local variable 'f2' aliases the storage of 
local variable 'x'}}
 }
 
 std::function<void()> reassign_safe_then_unsafe() {
@@ -3754,7 +3828,8 @@ std::function<void()> reassign_safe_then_unsafe() {
   int local = 2;
   std::function<void()> f = []() { (void)safe; };
   f = [&local]() { (void)local; }; // expected-warning {{stack memory 
associated with local variable 'local' is returned}}
-  return f; // expected-note {{returned here}}
+  return f; // expected-note {{returned here}} \
+            // expected-note {{local variable 'f' aliases the storage of local 
variable 'local'}}
 }
 
 std::function<void()> reassign_unsafe_then_safe() {
@@ -3841,18 +3916,21 @@ struct [[gsl::Owner]] optional : 
__optional_storage_base<T> {
 const MyObj& return_optional_deref() {
   optional<MyObj> opt;
   return *opt; // expected-warning {{stack memory associated with local 
variable 'opt' is returned}} \
+               // expected-note {{expression aliases the storage of local 
variable 'opt'}} \
                // expected-note {{returned here}}
 }
 
 const MyObj& return_optional_value() {
   optional<MyObj> opt;
   return opt.value(); // expected-warning {{stack memory associated with local 
variable 'opt' is returned}} \
+                      // expected-note {{result of call to 'value' aliases the 
storage of local variable 'opt'}} \
                       // expected-note {{returned here}}
 }
 
 const int* return_optional_arrow() {
   optional<MyObj> opt;
   return &opt->id; // expected-warning {{stack memory associated with local 
variable 'opt' is returned}} \
+                   // expected-note {{expression aliases the storage of local 
variable 'opt'}} \
                    // expected-note {{returned here}}
 }
 
@@ -3873,27 +3951,30 @@ namespace GH191954 {
     int x;
     int* f = &x; // expected-warning {{stack memory associated with local 
variable 'x' is returned}}
     int* a;
-    a = std::move(f);
+    a = std::move(f); // expected-note {{result of call to 'move<int *&>' 
aliases the storage of local variable 'x'}}
     return a; // expected-note {{returned here}}
   }
 
   int* return_moved_pointer2() {
     int x;
     int* f = &x;         // expected-warning {{stack memory associated with 
local variable 'x' is returned}}
-    return std::move(f); // expected-note {{returned here}}
+    return std::move(f); // expected-note {{returned here}} \
+                         // expected-note {{result of call to 'move<int *&>' 
aliases the storage of local variable 'x'}}
   }
 
   View return_moved_view() {
     MyObj o;
     View v(o); // expected-warning {{stack memory associated with local 
variable 'o' is returned}}
-    View v2 = std::move(v);
-    return v2; // expected-note {{returned here}}
+    View v2 = std::move(v); // expected-note {{result of call to 'move<View 
&>' aliases the storage of local variable 'o'}}
+    return v2; // expected-note {{returned here}} \
+               // expected-note {{local variable 'v2' aliases the storage of 
local variable 'o'}}
   }
 
   int* return_forwarded_pointer() {
     int x;
     int* f = &x;                  // expected-warning {{stack memory 
associated with local variable 'x' is returned}}
-    return std::forward<int*>(f); // expected-note {{returned here}}
+    return std::forward<int*>(f); // expected-note {{returned here}} \
+                                  // expected-note {{result of call to 
'forward<int *>' aliases the storage of local variable 'x'}}
   }
 
   int g;
@@ -3922,7 +4003,8 @@ View use_after_return_capture_by() {
   MyObj a;
   View res;
   setCaptureBy(res, a);   // expected-warning {{stack memory associated with 
local variable 'a' is returned}}
-  return res;     // expected-note {{returned here}}  
+  return res;     // expected-note {{returned here}} \
+                  // expected-note {{local variable 'res' aliases the storage 
of local variable 'a'}}
                    
 }
 

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

Reply via email to