[llvm-branch-commits] [clang] [analyzer] Turn on CFGLifetimeEnds elements by default (PR #228228)

Benedek Kaibas via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Oct 13 05:56:12 PDT 2026


https://github.com/benedekaibas updated https://github.com/llvm/llvm-project/pull/228228

>From 03c4f45b45acc38218e446a944fd05df2042219b Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Thu, 1 Oct 2026 13:36:02 +0200
Subject: [PATCH 1/3] [analyzer] Enable CFG::LifetimeEnd elements by default

---
 .../clang/StaticAnalyzer/Checkers/Checkers.td |   6 +
 .../StaticAnalyzer/Core/AnalyzerOptions.def   |   2 +-
 .../Checkers/AnalysisOrderChecker.cpp         |   9 +-
 .../Inputs/expected-plists/objc-arc.m.plist   |   3 +
 .../retain-release.m.objc.plist               |  47 +-
 .../retain-release.m.objcpp.plist             |  47 +-
 clang/test/Analysis/aggrinit-cfg-output.cpp   |   1 +
 clang/test/Analysis/analyzer-config.c         |   3 +-
 clang/test/Analysis/analyzer-stats.c          |   2 +-
 clang/test/Analysis/anonymous-decls.cpp       |  19 +-
 .../Analysis/auto-obj-dtors-cfg-output.cpp    | 491 ++++++++++-------
 clang/test/Analysis/blocks.mm                 |   1 +
 clang/test/Analysis/cfg-openmp.cpp            |   9 +-
 clang/test/Analysis/cfg-rich-constructors.cpp | 312 +++++++----
 clang/test/Analysis/cfg-rich-constructors.mm  |   9 +-
 clang/test/Analysis/cfg.cpp                   |  20 +
 clang/test/Analysis/cxx20-range-for-cfg.cpp   |   6 +-
 .../diagnostics/track_subexpressions.cpp      |   4 +-
 clang/test/Analysis/domtest.cpp               |  30 +-
 .../Analysis/end-function-return-stmt.cpp     |   2 +-
 .../test/Analysis/initializers-cfg-output.cpp |   2 +
 clang/test/Analysis/loop-widening-notes.cpp   |   4 +-
 clang/test/Analysis/loopexit-cfg-output.cpp   |  17 +-
 .../test/Analysis/missing-bind-temporary.cpp  |  18 +-
 clang/test/Analysis/scopes-cfg-output.cpp     | 495 +++++++++++-------
 .../Analysis/temp-obj-dtors-cfg-output.cpp    | 225 +++++---
 clang/test/Analysis/unreachable-code-path.c   |   4 +-
 27 files changed, 1156 insertions(+), 632 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e1a1046efab430..eb59279270dc85 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -1481,6 +1481,12 @@ def AnalysisOrderChecker : Checker<"AnalysisOrder">,
                   "false",
                   Released,
                   Hide>,
+    CmdLineOption<Boolean,
+                  "LifetimeEnd",
+                  "",
+                  "false",
+                  Released,
+                  Hide>,
     CmdLineOption<Boolean,
                   "RegionChanges",
                   "",
diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
index 90b80e5201aa82..290a96e0bdfe3f 100644
--- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
+++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
@@ -98,7 +98,7 @@ ANALYZER_OPTION(bool, ShouldIncludeTemporaryDtorsInCFG, "cfg-temporary-dtors",
 ANALYZER_OPTION(
     bool, ShouldIncludeLifetimeInCFG, "cfg-lifetime",
     "Whether or not end-of-lifetime information should be included in the CFG.",
-    false)
+    true)
 
 ANALYZER_OPTION(bool, ShouldIncludeLoopExitInCFG, "cfg-loopexit",
                 "Whether or not the end of the loop information should "
diff --git a/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
index d3e4a3a6347641..78bbe8fb826df6 100644
--- a/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
@@ -37,7 +37,7 @@ class AnalysisOrderChecker
           check::PostStmt<OffsetOfExpr>, check::PreCall, check::PostCall,
           check::EndFunction, check::EndAnalysis, check::NewAllocator,
           check::Bind, check::PointerEscape, check::RegionChanges,
-          check::LiveSymbols, eval::Call> {
+          check::LiveSymbols, check::LifetimeEnd, eval::Call> {
 
   bool isCallbackEnabled(const AnalyzerOptions &Opts,
                          StringRef CallbackName) const {
@@ -170,6 +170,8 @@ class AnalysisOrderChecker
         llvm::errs() << "CFGStmt\n";
       else if (LastElement.getAs<CFGAutomaticObjDtor>())
         llvm::errs() << "CFGAutomaticObjDtor\n";
+      else if (LastElement.getAs<CFGLifetimeEnds>())
+        llvm::errs() << "CFGLifetimeEnds\n";
     }
   }
 
@@ -196,6 +198,11 @@ class AnalysisOrderChecker
       llvm::errs() << "LiveSymbols\n";
   }
 
+  void checkLifetimeEnd(const VarDecl *VD, CheckerContext &C) const {
+    if (isCallbackEnabled(C, "LifetimeEnd"))
+      llvm::errs() << "LifetimeEnd\n";
+  }
+
   ProgramStateRef
   checkRegionChanges(ProgramStateRef State,
                      const InvalidatedSymbols *Invalidated,
diff --git a/clang/test/Analysis/Inputs/expected-plists/objc-arc.m.plist b/clang/test/Analysis/Inputs/expected-plists/objc-arc.m.plist
index b8bc7361111108..e7b4f02ea5de06 100644
--- a/clang/test/Analysis/Inputs/expected-plists/objc-arc.m.plist
+++ b/clang/test/Analysis/Inputs/expected-plists/objc-arc.m.plist
@@ -1751,15 +1751,18 @@
    <key>0</key>
    <array>
     <integer>176</integer>
+    <integer>177</integer>
     <integer>178</integer>
     <integer>179</integer>
     <integer>180</integer>
     <integer>181</integer>
+    <integer>184</integer>
     <integer>185</integer>
     <integer>186</integer>
     <integer>187</integer>
     <integer>188</integer>
     <integer>189</integer>
+    <integer>192</integer>
     <integer>193</integer>
     <integer>194</integer>
     <integer>195</integer>
diff --git a/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist b/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist
index 5c4ea431696f15..12582f1effcf22 100644
--- a/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist
+++ b/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist
@@ -11479,9 +11479,9 @@
      </array>
      <key>depth</key><integer>0</integer>
      <key>extended_message</key>
-     <string>Assuming the condition is false</string>
+     <string>Assuming the condition is true</string>
      <key>message</key>
-     <string>Assuming the condition is false</string>
+     <string>Assuming the condition is true</string>
     </dict>
     <dict>
      <key>kind</key><string>control</string>
@@ -11504,13 +11504,13 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>851</integer>
-           <key>col</key><integer>1</integer>
+           <key>line</key><integer>850</integer>
+           <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>851</integer>
-           <key>col</key><integer>1</integer>
+           <key>line</key><integer>850</integer>
+           <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
          </array>
@@ -11521,10 +11521,25 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>851</integer>
-      <key>col</key><integer>1</integer>
+      <key>line</key><integer>850</integer>
+      <key>col</key><integer>4</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+     <array>
+     <dict>
+      <key>line</key><integer>850</integer>
+      <key>col</key><integer>4</integer>
       <key>file</key><integer>0</integer>
      </dict>
+     <dict>
+      <key>line</key><integer>850</integer>
+      <key>col</key><integer>8</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     </array>
+     </array>
      <key>depth</key><integer>0</integer>
      <key>extended_message</key>
      <string>Object leaked: object allocated and stored into 'dict' is not referenced later in this execution path and has a retain count of +1</string>
@@ -11543,8 +11558,8 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>851</integer>
-   <key>col</key><integer>1</integer>
+   <key>line</key><integer>850</integer>
+   <key>col</key><integer>4</integer>
    <key>file</key><integer>0</integer>
   </dict>
   <key>ExecutedLines</key>
@@ -11554,7 +11569,7 @@
     <integer>847</integer>
     <integer>848</integer>
     <integer>849</integer>
-    <integer>851</integer>
+    <integer>850</integer>
    </array>
   </dict>
   </dict>
@@ -21050,6 +21065,7 @@
    <key>0</key>
    <array>
     <integer>2034</integer>
+    <integer>2035</integer>
     <integer>2036</integer>
     <integer>2037</integer>
     <integer>2038</integer>
@@ -21459,11 +21475,13 @@
    <key>0</key>
    <array>
     <integer>2034</integer>
+    <integer>2035</integer>
     <integer>2036</integer>
     <integer>2037</integer>
     <integer>2038</integer>
     <integer>2039</integer>
     <integer>2040</integer>
+    <integer>2043</integer>
     <integer>2044</integer>
     <integer>2045</integer>
     <integer>2046</integer>
@@ -21832,17 +21850,20 @@
    <key>0</key>
    <array>
     <integer>2034</integer>
+    <integer>2035</integer>
     <integer>2036</integer>
     <integer>2037</integer>
     <integer>2038</integer>
     <integer>2039</integer>
     <integer>2040</integer>
+    <integer>2043</integer>
     <integer>2044</integer>
     <integer>2045</integer>
     <integer>2046</integer>
     <integer>2047</integer>
     <integer>2048</integer>
     <integer>2049</integer>
+    <integer>2052</integer>
     <integer>2053</integer>
     <integer>2054</integer>
     <integer>2055</integer>
@@ -22387,22 +22408,26 @@
    <key>0</key>
    <array>
     <integer>2034</integer>
+    <integer>2035</integer>
     <integer>2036</integer>
     <integer>2037</integer>
     <integer>2038</integer>
     <integer>2039</integer>
     <integer>2040</integer>
+    <integer>2043</integer>
     <integer>2044</integer>
     <integer>2045</integer>
     <integer>2046</integer>
     <integer>2047</integer>
     <integer>2048</integer>
     <integer>2049</integer>
+    <integer>2052</integer>
     <integer>2053</integer>
     <integer>2054</integer>
     <integer>2055</integer>
     <integer>2056</integer>
     <integer>2057</integer>
+    <integer>2060</integer>
     <integer>2061</integer>
     <integer>2062</integer>
     <integer>2063</integer>
diff --git a/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist b/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist
index ccf7849e5fab69..84aaae21ff7f30 100644
--- a/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist
+++ b/clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist
@@ -11479,9 +11479,9 @@
      </array>
      <key>depth</key><integer>0</integer>
      <key>extended_message</key>
-     <string>Assuming the condition is false</string>
+     <string>Assuming the condition is true</string>
      <key>message</key>
-     <string>Assuming the condition is false</string>
+     <string>Assuming the condition is true</string>
     </dict>
     <dict>
      <key>kind</key><string>control</string>
@@ -11504,13 +11504,13 @@
         <key>end</key>
          <array>
           <dict>
-           <key>line</key><integer>851</integer>
-           <key>col</key><integer>1</integer>
+           <key>line</key><integer>850</integer>
+           <key>col</key><integer>4</integer>
            <key>file</key><integer>0</integer>
           </dict>
           <dict>
-           <key>line</key><integer>851</integer>
-           <key>col</key><integer>1</integer>
+           <key>line</key><integer>850</integer>
+           <key>col</key><integer>8</integer>
            <key>file</key><integer>0</integer>
           </dict>
          </array>
@@ -11521,10 +11521,25 @@
      <key>kind</key><string>event</string>
      <key>location</key>
      <dict>
-      <key>line</key><integer>851</integer>
-      <key>col</key><integer>1</integer>
+      <key>line</key><integer>850</integer>
+      <key>col</key><integer>4</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     <key>ranges</key>
+     <array>
+     <array>
+     <dict>
+      <key>line</key><integer>850</integer>
+      <key>col</key><integer>4</integer>
       <key>file</key><integer>0</integer>
      </dict>
+     <dict>
+      <key>line</key><integer>850</integer>
+      <key>col</key><integer>8</integer>
+      <key>file</key><integer>0</integer>
+     </dict>
+     </array>
+     </array>
      <key>depth</key><integer>0</integer>
      <key>extended_message</key>
      <string>Object leaked: object allocated and stored into 'dict' is not referenced later in this execution path and has a retain count of +1</string>
@@ -11543,8 +11558,8 @@
   <key>issue_hash_function_offset</key><string>1</string>
   <key>location</key>
   <dict>
-   <key>line</key><integer>851</integer>
-   <key>col</key><integer>1</integer>
+   <key>line</key><integer>850</integer>
+   <key>col</key><integer>4</integer>
    <key>file</key><integer>0</integer>
   </dict>
   <key>ExecutedLines</key>
@@ -11554,7 +11569,7 @@
     <integer>847</integer>
     <integer>848</integer>
     <integer>849</integer>
-    <integer>851</integer>
+    <integer>850</integer>
    </array>
   </dict>
   </dict>
@@ -21119,6 +21134,7 @@
    <key>0</key>
    <array>
     <integer>2034</integer>
+    <integer>2035</integer>
     <integer>2036</integer>
     <integer>2037</integer>
     <integer>2038</integer>
@@ -21528,11 +21544,13 @@
    <key>0</key>
    <array>
     <integer>2034</integer>
+    <integer>2035</integer>
     <integer>2036</integer>
     <integer>2037</integer>
     <integer>2038</integer>
     <integer>2039</integer>
     <integer>2040</integer>
+    <integer>2043</integer>
     <integer>2044</integer>
     <integer>2045</integer>
     <integer>2046</integer>
@@ -21901,17 +21919,20 @@
    <key>0</key>
    <array>
     <integer>2034</integer>
+    <integer>2035</integer>
     <integer>2036</integer>
     <integer>2037</integer>
     <integer>2038</integer>
     <integer>2039</integer>
     <integer>2040</integer>
+    <integer>2043</integer>
     <integer>2044</integer>
     <integer>2045</integer>
     <integer>2046</integer>
     <integer>2047</integer>
     <integer>2048</integer>
     <integer>2049</integer>
+    <integer>2052</integer>
     <integer>2053</integer>
     <integer>2054</integer>
     <integer>2055</integer>
@@ -22456,22 +22477,26 @@
    <key>0</key>
    <array>
     <integer>2034</integer>
+    <integer>2035</integer>
     <integer>2036</integer>
     <integer>2037</integer>
     <integer>2038</integer>
     <integer>2039</integer>
     <integer>2040</integer>
+    <integer>2043</integer>
     <integer>2044</integer>
     <integer>2045</integer>
     <integer>2046</integer>
     <integer>2047</integer>
     <integer>2048</integer>
     <integer>2049</integer>
+    <integer>2052</integer>
     <integer>2053</integer>
     <integer>2054</integer>
     <integer>2055</integer>
     <integer>2056</integer>
     <integer>2057</integer>
+    <integer>2060</integer>
     <integer>2061</integer>
     <integer>2062</integer>
     <integer>2063</integer>
diff --git a/clang/test/Analysis/aggrinit-cfg-output.cpp b/clang/test/Analysis/aggrinit-cfg-output.cpp
index 682399399d21df..2b0f8c31bbaab8 100644
--- a/clang/test/Analysis/aggrinit-cfg-output.cpp
+++ b/clang/test/Analysis/aggrinit-cfg-output.cpp
@@ -23,6 +23,7 @@ int main() {
 // CHECK-NEXT:   7: StringRef s{a};
 // CHECK-NEXT:   8: s
 // CHECK-NEXT:   9: (void)[B1.8] (CStyleCastExpr, ToVoid, void)
+// CHECK-NEXT:   10: [B1.7] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B2
 // CHECK-NEXT:   Succs (1): B0
 
diff --git a/clang/test/Analysis/analyzer-config.c b/clang/test/Analysis/analyzer-config.c
index 6715688ac56ecf..346b58ac387799 100644
--- a/clang/test/Analysis/analyzer-config.c
+++ b/clang/test/Analysis/analyzer-config.c
@@ -24,7 +24,7 @@
 // CHECK-NEXT: cfg-conditional-static-initializers = true
 // CHECK-NEXT: cfg-expand-default-aggr-inits = false
 // CHECK-NEXT: cfg-implicit-dtors = true
-// CHECK-NEXT: cfg-lifetime = false
+// CHECK-NEXT: cfg-lifetime = true
 // CHECK-NEXT: cfg-loopexit = false
 // CHECK-NEXT: cfg-rich-constructors = true
 // CHECK-NEXT: cfg-scopes = false
@@ -61,6 +61,7 @@
 // CHECK-NEXT: debug.AnalysisOrder:EndAnalysis = false
 // CHECK-NEXT: debug.AnalysisOrder:EndFunction = false
 // CHECK-NEXT: debug.AnalysisOrder:EvalCall = false
+// CHECK-NEXT: debug.AnalysisOrder:LifetimeEnd = false
 // CHECK-NEXT: debug.AnalysisOrder:LiveSymbols = false
 // CHECK-NEXT: debug.AnalysisOrder:NewAllocator = false
 // CHECK-NEXT: debug.AnalysisOrder:PointerEscape = false
diff --git a/clang/test/Analysis/analyzer-stats.c b/clang/test/Analysis/analyzer-stats.c
index 7e2e9164ff35d4..6855f039c185cb 100644
--- a/clang/test/Analysis/analyzer-stats.c
+++ b/clang/test/Analysis/analyzer-stats.c
@@ -22,7 +22,7 @@ int sink(void) // expected-warning-re{{sink -> Total CFGBlocks: {{[0-9]+}} | Unr
   return 0;
 }
 
-int emptyConditionLoop(void) // expected-warning-re{{emptyConditionLoop -> Total CFGBlocks: {{[0-9]+}} | Unreachable CFGBlocks: 0 | Exhausted Block: yes | Empty WorkList: yes}}
+int emptyConditionLoop(void) // expected-warning-re{{emptyConditionLoop -> Total CFGBlocks: {{[0-9]+}} | Unreachable CFGBlocks: 1 | Exhausted Block: yes | Empty WorkList: yes}}
 {
   int num = 1;
   for (;;)
diff --git a/clang/test/Analysis/anonymous-decls.cpp b/clang/test/Analysis/anonymous-decls.cpp
index 88aa569a1212b3..a1241be2126dee 100644
--- a/clang/test/Analysis/anonymous-decls.cpp
+++ b/clang/test/Analysis/anonymous-decls.cpp
@@ -67,21 +67,22 @@ int main() {
 // FIXME: On steps 8 and 14, a decomposition is referred by name, which they never have.
 
 // CHECK-LABEL: int main()
-// CHECK:      [B3]
+// CHECK:      [B4]
 // CHECK-NEXT:   1: operator*
-// CHECK-NEXT:   2: [B3.1] (ImplicitCastExpr, FunctionToPointerDecay, iterator_traits<pair<int, int> *>::reference (*)(void))
+// CHECK-NEXT:   2: [B4.1] (ImplicitCastExpr, FunctionToPointerDecay, iterator_traits<pair<int, int> *>::reference (*)(void))
 // CHECK-NEXT:   3: __begin1
-// CHECK-NEXT:   4: * [B3.3] (OperatorCall)
+// CHECK-NEXT:   4: * [B4.3] (OperatorCall)
 // CHECK-NEXT:   5: auto &{{.*}};
 // CHECK-NEXT:   6: get<0UL>
-// CHECK-NEXT:   7: [B3.6] (ImplicitCastExpr, FunctionToPointerDecay, tuple_element<0L, pair<int, int> >::type (*)(pair<int, int> &))
+// CHECK-NEXT:   7: [B4.6] (ImplicitCastExpr, FunctionToPointerDecay, tuple_element<0L, pair<int, int> >::type (*)(pair<int, int> &))
 // CHECK-NEXT:   8: decomposition-a-b
-// CHECK-NEXT:   9: [B3.7]([B3.8])
+// CHECK-NEXT:   9: [B4.7]([B4.8])
 // CHECK-NEXT:  10: std::tuple_element<0UL, std::pair<int, int>>::type a = get<0UL>(decomposition-a-b);
 // CHECK-NEXT:  11: get<1UL>
-// CHECK-NEXT:  12: [B3.11] (ImplicitCastExpr, FunctionToPointerDecay, tuple_element<1L, pair<int, int> >::type (*)(pair<int, int> &))
+// CHECK-NEXT:  12: [B4.11] (ImplicitCastExpr, FunctionToPointerDecay, tuple_element<1L, pair<int, int> >::type (*)(pair<int, int> &))
 // CHECK-NEXT:  13: decomposition-a-b
-// CHECK-NEXT:  14: [B3.12]([B3.13])
+// CHECK-NEXT:  14: [B4.12]([B4.13])
 // CHECK-NEXT:  15: std::tuple_element<1UL, std::pair<int, int>>::type b = get<1UL>(decomposition-a-b);
-// CHECK-NEXT:   Preds (1): B1
-// CHECK-NEXT:   Succs (1): B2
+// CHECK-NEXT:  16: [B4.5] (Lifetime ends)
+// CHECK-NEXT:   Preds (1): B2
+// CHECK-NEXT:   Succs (1): B3
diff --git a/clang/test/Analysis/auto-obj-dtors-cfg-output.cpp b/clang/test/Analysis/auto-obj-dtors-cfg-output.cpp
index 96b9a5508cc084..0705082c926292 100644
--- a/clang/test/Analysis/auto-obj-dtors-cfg-output.cpp
+++ b/clang/test/Analysis/auto-obj-dtors-cfg-output.cpp
@@ -62,7 +62,10 @@ extern const bool UV;
 // CHECK-NEXT:   9: [B1.8]
 // CHECK:       10: const A &c = A();
 // CHECK:       11: [B1.10].~A() (Implicit destructor)
-// CHECK:       12: [B1.2].~A() (Implicit destructor)
+// CHECK:       12: [B1.10] (Lifetime ends)
+// CHECK:       13: [B1.2].~A() (Implicit destructor)
+// CHECK:       14: [B1.2] (Lifetime ends)
+// CHECK-NEXT:  15: [B1.5] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B2
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B0 (EXIT)]
@@ -84,11 +87,13 @@ void test_const_ref() {
 // CXX98-NEXT:   4: [B1.3]
 // CXX98-NEXT:   5: const int &x = A().x;
 // CXX98-NEXT:   6: [B1.5].~A() (Implicit destructor)
+// CXX98-NEXT:   7: [B1.5] (Lifetime ends)
 // CXX11-NEXT:   3: [B1.2]
 // CXX11-NEXT:   4: [B1.3].x
 // CXX11-NEXT:   5: [B1.4] (ImplicitCastExpr, NoOp, const int)
 // CXX11-NEXT:   6: const int &x = A().x;
 // CXX11-NEXT:   7: [B1.6].~A() (Implicit destructor)
+// CXX11-NEXT:   8: [B1.6] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B2
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B0 (EXIT)]
@@ -110,6 +115,7 @@ void test_const_ref_to_field() {
 // CXX98-NEXT:     6: [B1.5]
 // CXX98-NEXT:     7: const int &x = A() .* &A::x;
 // CXX98-NEXT:     8: [B1.7].~A() (Implicit destructor)
+// CXX98-NEXT:     9: [B1.7] (Lifetime ends)
 // CXX11-NEXT:     3: [B1.2]
 // CXX11-NEXT:     4: A::x
 // CXX11-NEXT:     5: &[B1.4]
@@ -117,6 +123,7 @@ void test_const_ref_to_field() {
 // CXX11-NEXT:     7: [B1.6] (ImplicitCastExpr, NoOp, const int)
 // CXX11-NEXT:     8: const int &x = A() .* &A::x;
 // CXX11-NEXT:     9: [B1.8].~A() (Implicit destructor)
+// CXX11-NEXT:     10: [B1.8] (Lifetime ends)
 // CHECK-NEXT:     Preds (1): B2
 // CHECK-NEXT:     Succs (1): B0
 // CHECK:        [B0 (EXIT)]
@@ -150,6 +157,8 @@ void test_pointer_to_member() {
 // CHECK-NEXT:    16: {[B1.15]}
 // CHECK-NEXT:    17: {[B1.10], [B1.15]}
 // CHECK-NEXT:    18: B bb[2] = {A(), A()};
+// CHECK-NEXT:    19: [B1.18] (Lifetime ends)
+// CHECK-NEXT:    20: [B1.6] (Lifetime ends)
 // CHECK-NEXT:     Preds (1): B2
 // CHECK-NEXT:     Succs (1): B0
 // CHECK:        [B0 (EXIT)]
@@ -188,50 +197,54 @@ void test_aggregate_lifetime_extension() {
 // CXX11-NEXT:    14: {[B1.13]}
 // Double curly braces trigger regexps, escape as per FileCheck manual.
 // CXX11-NEXT:    15: C c = {{[{][{]}}A(), A(){{[}][}]}};
-// CXX11-NEXT:    16: ~A() (Temporary object destructor)
+// CXX11-NEXT:    16: (FullExprCleanup collected 2 MTEs: [B1.3], [B1.8])
 // CXX11-NEXT:    17: ~A() (Temporary object destructor)
-// CXX11-WARNINGS-NEXT:    18: A() (CXXConstructExpr, A)
-// CXX11-ANALYZER-NEXT:    18: A() (CXXConstructExpr, [B1.19], [B1.21], A)
-// CXX11-NEXT:    19: [B1.18] (BindTemporary)
-// CXX11-NEXT:    20: [B1.19] (ImplicitCastExpr, NoOp, const A)
-// CXX11-NEXT:    21: [B1.20]
-// CXX11-NEXT:    22: [B1.21] (CXXConstructExpr, const A)
-// CXX11-WARNINGS-NEXT:    23: A() (CXXConstructExpr, A)
-// CXX11-ANALYZER-NEXT:    23: A() (CXXConstructExpr, [B1.24], [B1.26], A)
-// CXX11-NEXT:    24: [B1.23] (BindTemporary)
-// CXX11-NEXT:    25: [B1.24] (ImplicitCastExpr, NoOp, const A)
-// CXX11-NEXT:    26: [B1.25]
-// CXX11-NEXT:    27: [B1.26] (CXXConstructExpr, const A)
+// CXX11-NEXT:    18: ~A() (Temporary object destructor)
+// CXX11-WARNINGS-NEXT:    19: A() (CXXConstructExpr, A)
+// CXX11-ANALYZER-NEXT:    19: A() (CXXConstructExpr, [B1.20], [B1.22], A)
+// CXX11-NEXT:    20: [B1.19] (BindTemporary)
+// CXX11-NEXT:    21: [B1.20] (ImplicitCastExpr, NoOp, const A)
+// CXX11-NEXT:    22: [B1.21]
+// CXX11-NEXT:    23: [B1.22] (CXXConstructExpr, const A)
+// CXX11-WARNINGS-NEXT:    24: A() (CXXConstructExpr, A)
+// CXX11-ANALYZER-NEXT:    24: A() (CXXConstructExpr, [B1.25], [B1.27], A)
+// CXX11-NEXT:    25: [B1.24] (BindTemporary)
+// CXX11-NEXT:    26: [B1.25] (ImplicitCastExpr, NoOp, const A)
+// CXX11-NEXT:    27: [B1.26]
+// CXX11-NEXT:    28: [B1.27] (CXXConstructExpr, const A)
 // FIXME: Why does it look as if the initializer list consumes uncopied objects?
-// CXX11-NEXT:    28: {[B1.19], [B1.24]}
-// CXX11-NEXT:    29: [B1.28] (BindTemporary)
-// CXX11-NEXT:    30: [B1.29]
-// CXX11-NEXT:    31: {[B1.30]}
-// CXX11-WARNINGS-NEXT:    32: A() (CXXConstructExpr, A)
-// CXX11-ANALYZER-NEXT:    32: A() (CXXConstructExpr, [B1.33], [B1.35], A)
-// CXX11-NEXT:    33: [B1.32] (BindTemporary)
-// CXX11-NEXT:    34: [B1.33] (ImplicitCastExpr, NoOp, const A)
-// CXX11-NEXT:    35: [B1.34]
-// CXX11-NEXT:    36: [B1.35] (CXXConstructExpr, const A)
-// CXX11-WARNINGS-NEXT:    37: A() (CXXConstructExpr, A)
-// CXX11-ANALYZER-NEXT:    37: A() (CXXConstructExpr, [B1.38], [B1.40], A)
-// CXX11-NEXT:    38: [B1.37] (BindTemporary)
-// CXX11-NEXT:    39: [B1.38] (ImplicitCastExpr, NoOp, const A)
-// CXX11-NEXT:    40: [B1.39]
-// CXX11-NEXT:    41: [B1.40] (CXXConstructExpr, const A)
+// CXX11-NEXT:    29: {[B1.20], [B1.25]}
+// CXX11-NEXT:    30: [B1.29] (BindTemporary)
+// CXX11-NEXT:    31: [B1.30]
+// CXX11-NEXT:    32: {[B1.31]}
+// CXX11-WARNINGS-NEXT:    33: A() (CXXConstructExpr, A)
+// CXX11-ANALYZER-NEXT:    33: A() (CXXConstructExpr, [B1.34], [B1.36], A)
+// CXX11-NEXT:    34: [B1.33] (BindTemporary)
+// CXX11-NEXT:    35: [B1.34] (ImplicitCastExpr, NoOp, const A)
+// CXX11-NEXT:    36: [B1.35]
+// CXX11-NEXT:    37: [B1.36] (CXXConstructExpr, const A)
+// CXX11-WARNINGS-NEXT:    38: A() (CXXConstructExpr, A)
+// CXX11-ANALYZER-NEXT:    38: A() (CXXConstructExpr, [B1.39], [B1.41], A)
+// CXX11-NEXT:    39: [B1.38] (BindTemporary)
+// CXX11-NEXT:    40: [B1.39] (ImplicitCastExpr, NoOp, const A)
+// CXX11-NEXT:    41: [B1.40]
+// CXX11-NEXT:    42: [B1.41] (CXXConstructExpr, const A)
 // FIXME: Why does it look as if the initializer list consumes uncopied objects?
-// CXX11-NEXT:    42: {[B1.33], [B1.38]}
-// CXX11-NEXT:    43: [B1.42] (BindTemporary)
-// CXX11-NEXT:    44: [B1.43]
-// CXX11-NEXT:    45: {[B1.44]}
+// CXX11-NEXT:    43: {[B1.34], [B1.39]}
+// CXX11-NEXT:    44: [B1.43] (BindTemporary)
+// CXX11-NEXT:    45: [B1.44]
+// CXX11-NEXT:    46: {[B1.45]}
 // Double curly braces trigger regexps, escape as per FileCheck manual.
-// CXX11-NEXT:    46: {{[{][{]}}[B1.30]}, {[B1.44]{{[}][}]}}
+// CXX11-NEXT:    47: {{[{][{]}}[B1.31]}, {[B1.45]{{[}][}]}}
 // Double curly braces trigger regexps, escape as per FileCheck manual.
-// CXX11-NEXT:    47: C cc[2] = {{[{][{][{]}}A(), A(){{[}][}]}}, {{[{][{]}}A(), A(){{[}][}][}]}};
-// CXX11-NEXT:    48: ~A() (Temporary object destructor)
-// CXX11-NEXT:    49: ~A() (Temporary object destructor)
+// CXX11-NEXT:    48: C cc[2] = {{[{][{][{]}}A(), A(){{[}][}]}}, {{[{][{]}}A(), A(){{[}][}][}]}};
+// CXX11-NEXT:    49: (FullExprCleanup collected 4 MTEs: [B1.21], [B1.26], [B1.35], [B1.40])
 // CXX11-NEXT:    50: ~A() (Temporary object destructor)
 // CXX11-NEXT:    51: ~A() (Temporary object destructor)
+// CXX11-NEXT:    52: ~A() (Temporary object destructor)
+// CXX11-NEXT:    53: ~A() (Temporary object destructor)
+// CXX11-NEXT:    54: [B1.48] (Lifetime ends)
+// CXX11-NEXT:    55: [B1.15] (Lifetime ends)
 // CXX11-NEXT:     Preds (1): B2
 // CXX11-NEXT:     Succs (1): B0
 // CXX11:        [B0 (EXIT)]
@@ -277,65 +290,69 @@ void test_aggregate_array_lifetime_extension() {
 // FIXME: Why does it look as if the initializer list consumes uncopied objects?
 // CHECK-NEXT:    17: {[B1.2], {[B1.7], [B1.12]}}
 // CHECK-NEXT:    18: D d = {A(), {A(), A()}};
-// CHECK-NEXT:    19: ~A() (Temporary object destructor)
+// CHECK-NEXT:    19: (FullExprCleanup collected 3 MTEs: [B1.3], [B1.8], [B1.13])
 // CHECK-NEXT:    20: ~A() (Temporary object destructor)
 // CHECK-NEXT:    21: ~A() (Temporary object destructor)
-// WARNINGS-NEXT:    22: A() (CXXConstructExpr, A)
-// ANALYZER-NEXT:    22: A() (CXXConstructExpr, [B1.23], [B1.25], A)
-// CHECK-NEXT:    23: [B1.22] (BindTemporary)
-// CHECK-NEXT:    24: [B1.23] (ImplicitCastExpr, NoOp, const A)
-// CHECK-NEXT:    25: [B1.24]
-// CHECK-NEXT:    26: [B1.25] (CXXConstructExpr, A)
-// WARNINGS-NEXT:    27: A() (CXXConstructExpr, A)
-// ANALYZER-NEXT:    27: A() (CXXConstructExpr, [B1.28], [B1.30], A)
-// CHECK-NEXT:    28: [B1.27] (BindTemporary)
-// CHECK-NEXT:    29: [B1.28] (ImplicitCastExpr, NoOp, const A)
-// CHECK-NEXT:    30: [B1.29]
-// CHECK-NEXT:    31: [B1.30] (CXXConstructExpr, A)
-// WARNINGS-NEXT:    32: A() (CXXConstructExpr, A)
-// ANALYZER-NEXT:    32: A() (CXXConstructExpr, [B1.33], [B1.35], A)
-// CHECK-NEXT:    33: [B1.32] (BindTemporary)
-// CHECK-NEXT:    34: [B1.33] (ImplicitCastExpr, NoOp, const A)
-// CHECK-NEXT:    35: [B1.34]
-// CHECK-NEXT:    36: [B1.35] (CXXConstructExpr, A)
+// CHECK-NEXT:    22: ~A() (Temporary object destructor)
+// WARNINGS-NEXT:    23: A() (CXXConstructExpr, A)
+// ANALYZER-NEXT:    23: A() (CXXConstructExpr, [B1.24], [B1.26], A)
+// CHECK-NEXT:    24: [B1.23] (BindTemporary)
+// CHECK-NEXT:    25: [B1.24] (ImplicitCastExpr, NoOp, const A)
+// CHECK-NEXT:    26: [B1.25]
+// CHECK-NEXT:    27: [B1.26] (CXXConstructExpr, A)
+// WARNINGS-NEXT:    28: A() (CXXConstructExpr, A)
+// ANALYZER-NEXT:    28: A() (CXXConstructExpr, [B1.29], [B1.31], A)
+// CHECK-NEXT:    29: [B1.28] (BindTemporary)
+// CHECK-NEXT:    30: [B1.29] (ImplicitCastExpr, NoOp, const A)
+// CHECK-NEXT:    31: [B1.30]
+// CHECK-NEXT:    32: [B1.31] (CXXConstructExpr, A)
+// WARNINGS-NEXT:    33: A() (CXXConstructExpr, A)
+// ANALYZER-NEXT:    33: A() (CXXConstructExpr, [B1.34], [B1.36], A)
+// CHECK-NEXT:    34: [B1.33] (BindTemporary)
+// CHECK-NEXT:    35: [B1.34] (ImplicitCastExpr, NoOp, const A)
+// CHECK-NEXT:    36: [B1.35]
+// CHECK-NEXT:    37: [B1.36] (CXXConstructExpr, A)
 // FIXME: Why does it look as if the initializer list consumes uncopied objects?
-// CHECK-NEXT:    37: {[B1.28], [B1.33]}
+// CHECK-NEXT:    38: {[B1.29], [B1.34]}
 // FIXME: Why does it look as if the initializer list consumes uncopied objects?
-// CHECK-NEXT:    38: {[B1.23], {[B1.28], [B1.33]}}
-// WARNINGS-NEXT:    39: A() (CXXConstructExpr, A)
-// ANALYZER-NEXT:    39: A() (CXXConstructExpr, [B1.40], [B1.42], A)
-// CHECK-NEXT:    40: [B1.39] (BindTemporary)
-// CHECK-NEXT:    41: [B1.40] (ImplicitCastExpr, NoOp, const A)
-// CHECK-NEXT:    42: [B1.41]
-// CHECK-NEXT:    43: [B1.42] (CXXConstructExpr, A)
-// WARNINGS-NEXT:    44: A() (CXXConstructExpr, A)
-// ANALYZER-NEXT:    44: A() (CXXConstructExpr, [B1.45], [B1.47], A)
-// CHECK-NEXT:    45: [B1.44] (BindTemporary)
-// CHECK-NEXT:    46: [B1.45] (ImplicitCastExpr, NoOp, const A)
-// CHECK-NEXT:    47: [B1.46]
-// CHECK-NEXT:    48: [B1.47] (CXXConstructExpr, A)
-// WARNINGS-NEXT:    49: A() (CXXConstructExpr, A)
-// ANALYZER-NEXT:    49: A() (CXXConstructExpr, [B1.50], [B1.52], A)
-// CHECK-NEXT:    50: [B1.49] (BindTemporary)
-// CHECK-NEXT:    51: [B1.50] (ImplicitCastExpr, NoOp, const A)
-// CHECK-NEXT:    52: [B1.51]
-// CHECK-NEXT:    53: [B1.52] (CXXConstructExpr, A)
+// CHECK-NEXT:    39: {[B1.24], {[B1.29], [B1.34]}}
+// WARNINGS-NEXT:    40: A() (CXXConstructExpr, A)
+// ANALYZER-NEXT:    40: A() (CXXConstructExpr, [B1.41], [B1.43], A)
+// CHECK-NEXT:    41: [B1.40] (BindTemporary)
+// CHECK-NEXT:    42: [B1.41] (ImplicitCastExpr, NoOp, const A)
+// CHECK-NEXT:    43: [B1.42]
+// CHECK-NEXT:    44: [B1.43] (CXXConstructExpr, A)
+// WARNINGS-NEXT:    45: A() (CXXConstructExpr, A)
+// ANALYZER-NEXT:    45: A() (CXXConstructExpr, [B1.46], [B1.48], A)
+// CHECK-NEXT:    46: [B1.45] (BindTemporary)
+// CHECK-NEXT:    47: [B1.46] (ImplicitCastExpr, NoOp, const A)
+// CHECK-NEXT:    48: [B1.47]
+// CHECK-NEXT:    49: [B1.48] (CXXConstructExpr, A)
+// WARNINGS-NEXT:    50: A() (CXXConstructExpr, A)
+// ANALYZER-NEXT:    50: A() (CXXConstructExpr, [B1.51], [B1.53], A)
+// CHECK-NEXT:    51: [B1.50] (BindTemporary)
+// CHECK-NEXT:    52: [B1.51] (ImplicitCastExpr, NoOp, const A)
+// CHECK-NEXT:    53: [B1.52]
+// CHECK-NEXT:    54: [B1.53] (CXXConstructExpr, A)
 // FIXME: Why does it look as if the initializer list consumes uncopied objects?
-// CHECK-NEXT:    54: {[B1.45], [B1.50]}
+// CHECK-NEXT:    55: {[B1.46], [B1.51]}
 // FIXME: Why does it look as if the initializer list consumes uncopied objects?
-// CHECK-NEXT:    55: {[B1.40], {[B1.45], [B1.50]}}
+// CHECK-NEXT:    56: {[B1.41], {[B1.46], [B1.51]}}
 // Double curly braces trigger regexps, escape as per FileCheck manual.
-// CHECK-NEXT:    56: {{[{][{]}}[B1.23], {[B1.28], [B1.33]{{[}][}]}}, {[B1.40], {[B1.45], [B1.50]{{[}][}][}]}}
+// CHECK-NEXT:    57: {{[{][{]}}[B1.24], {[B1.29], [B1.34]{{[}][}]}}, {[B1.41], {[B1.46], [B1.51]{{[}][}][}]}}
 // Double curly braces trigger regexps, escape as per FileCheck manual.
-// CHECK-NEXT:    57: D dd[2] = {{[{][{]}}A(), {A(), A(){{[}][}]}}, {A(), {A(), A(){{[}][}][}]}};
-// CHECK-NEXT:    58: ~A() (Temporary object destructor)
-// CHECK-NEXT:    59: ~A() (Temporary object destructor)
+// CHECK-NEXT:    58: D dd[2] = {{[{][{]}}A(), {A(), A(){{[}][}]}}, {A(), {A(), A(){{[}][}][}]}};
+// CHECK-NEXT:    59: (FullExprCleanup collected 6 MTEs: [B1.25], [B1.30], [B1.35], [B1.42], [B1.47], [B1.52])
 // CHECK-NEXT:    60: ~A() (Temporary object destructor)
 // CHECK-NEXT:    61: ~A() (Temporary object destructor)
 // CHECK-NEXT:    62: ~A() (Temporary object destructor)
 // CHECK-NEXT:    63: ~A() (Temporary object destructor)
-// CHECK-NEXT:    64: [B1.57].~D[2]() (Implicit destructor)
-// CHECK-NEXT:    65: [B1.18].~D() (Implicit destructor)
+// CHECK-NEXT:    64: ~A() (Temporary object destructor)
+// CHECK-NEXT:    65: ~A() (Temporary object destructor)
+// CHECK-NEXT:    66: [B1.58].~D[2]() (Implicit destructor)
+// CHECK-NEXT:    67: [B1.58] (Lifetime ends)
+// CHECK-NEXT:    68: [B1.18].~D() (Implicit destructor)
+// CHECK-NEXT:    69: [B1.18] (Lifetime ends)
 // CHECK-NEXT:     Preds (1): B2
 // CHECK-NEXT:     Succs (1): B0
 // CHECK:        [B0 (EXIT)]
@@ -364,6 +381,8 @@ void test_aggregate_with_nontrivial_own_destructor() {
 // ANALYZER-NEXT:   3:  (CXXConstructExpr, [B1.4], A[0])
 // CHECK-NEXT:   4: A b[0];
 // CHECK-NEXT:   5: [B1.2].~A[2]() (Implicit destructor)
+// CHECK-NEXT:   6: [B1.2] (Lifetime ends)
+// CHECK-NEXT:   7: [B1.4] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B2
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B0 (EXIT)]
@@ -386,12 +405,16 @@ void test_array() {
 // ANALYZER-NEXT:   5:  (CXXConstructExpr, [B1.6], A)
 // CHECK-NEXT:   6: A d;
 // CHECK-NEXT:   7: [B1.6].~A() (Implicit destructor)
-// CHECK-NEXT:   8: [B1.4].~A() (Implicit destructor)
-// WARNINGS-NEXT:   9:  (CXXConstructExpr, A)
-// ANALYZER-NEXT:   9:  (CXXConstructExpr, [B1.10], A)
-// CHECK:       10: A b;
-// CHECK:       11: [B1.10].~A() (Implicit destructor)
-// CHECK:       12: [B1.2].~A() (Implicit destructor)
+// CHECK-NEXT:   8: [B1.6] (Lifetime ends)
+// CHECK-NEXT:   9: [B1.4].~A() (Implicit destructor)
+// CHECK-NEXT:   10: [B1.4] (Lifetime ends)
+// WARNINGS-NEXT:   11:  (CXXConstructExpr, A)
+// ANALYZER-NEXT:   11:  (CXXConstructExpr, [B1.12], A)
+// CHECK:       12: A b;
+// CHECK:       13: [B1.12].~A() (Implicit destructor)
+// CHECK-NEXT:   14: [B1.12] (Lifetime ends)
+// CHECK:       15: [B1.2].~A() (Implicit destruct
+// CHECK-NEXT:   16: [B1.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B2
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B0 (EXIT)]
@@ -411,14 +434,19 @@ void test_scope() {
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B1.2], A)
 // CHECK-NEXT:   2: A c;
 // CHECK-NEXT:   3: [B1.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B3.4].~A() (Implicit destructor)
-// CHECK-NEXT:   5: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B1.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B3.4].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B3.4] (Lifetime ends)
+// CHECK-NEXT:   7: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT:   8: [B3.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B3
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
 // CHECK-NEXT:   1: return;
 // CHECK-NEXT:   2: [B3.4].~A() (Implicit destructor)
-// CHECK-NEXT:   3: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT:   3: [B3.4] (Lifetime ends)
+// CHECK-NEXT:   4: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B3.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B3
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B3]
@@ -450,8 +478,11 @@ void test_return() {
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B1.2], A)
 // CHECK-NEXT:   2: A c;
 // CHECK-NEXT:   3: [B1.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B6.2].~A() (Implicit destructor)
-// CHECK-NEXT:   5: [B7.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B1.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B6.2].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B6.2] (Lifetime ends)
+// CHECK-NEXT:   7: [B7.2].~A() (Implicit destructor)
+// CHECK-NEXT:   8: [B7.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (2): B2 B3
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -459,11 +490,14 @@ void test_return() {
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B2.2], A)
 // CHECK-NEXT:   2: A b;
 // CHECK-NEXT:   3: [B2.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B6.4].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B2.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B6.4].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B6.4] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B3]
 // CHECK-NEXT:   1: [B6.4].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B6.4] (Lifetime ends)
 // CHECK-NEXT:   T: goto l1;
 // CHECK:        Preds (1): B4
 // CHECK-NEXT:   Succs (1): B1
@@ -497,7 +531,9 @@ void test_return() {
 // CHECK-NEXT:   Succs (1): B6
 // CHECK:      [B8]
 // CHECK-NEXT:   1: [B6.4].~A() (Implicit destructor)
-// CHECK-NEXT:   2: [B6.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B6.4] (Lifetime ends)
+// CHECK-NEXT:   3: [B6.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B6.2] (Lifetime ends)
 // CHECK-NEXT:   T: goto l0;
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B6
@@ -520,7 +556,9 @@ void test_goto() {
 // CHECK-NEXT:   Succs (1): B4
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B4.6].~A() (Implicit destructor)
-// CHECK-NEXT:   2: [B4.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B4.6] (Lifetime ends)
+// CHECK-NEXT:   3: [B4.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B4.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (2): B2 B3
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -528,21 +566,23 @@ void test_goto() {
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B2.2], A)
 // CHECK-NEXT:   2: A c;
 // CHECK-NEXT:   3: [B2.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B2.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B3]
 // WARNINGS-NEXT:   1:  (CXXConstructExpr, A)
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B3.2], A)
 // CHECK-NEXT:   2: A c;
-// CHECK-NEXT:   3: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT:   3: [B3.2].~A() (Implicit destruct
+// CHECK-NEXT:   4: [B3.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B4]
 // WARNINGS-NEXT:   1:  (CXXConstructExpr, A)
-// ANALYZER-NEXT:   1:  (CXXConstructExpr, [B4.2], A)
+// ANALYZER-NEXT:   1:  (CXXConstructExpr, [B4.2],
 // CHECK-NEXT:   2: A a;
 // CHECK-NEXT:   3: a
-// CHECK-NEXT:   4: [B4.3] (ImplicitCastExpr, NoOp, const A)
+// CHECK-NEXT:   4: [B4.3] (ImplicitCastExpr, NoOp
 // WARNINGS-NEXT:   5: [B4.4] (CXXConstructExpr, A)
 // ANALYZER-NEXT:   5: [B4.4] (CXXConstructExpr, [B4.6], A)
 // CHECK-NEXT:   6: A b = a;
@@ -568,11 +608,14 @@ void test_if_implicit_scope() {
 // CHECK-NEXT:   Succs (1): B8
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B8.6].~A() (Implicit destructor)
-// WARNINGS-NEXT:   2:  (CXXConstructExpr, A)
-// ANALYZER-NEXT:   2:  (CXXConstructExpr, [B1.3], A)
-// CHECK-NEXT:   3: A e;
-// CHECK-NEXT:   4: [B1.3].~A() (Implicit destructor)
-// CHECK-NEXT:   5: [B8.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B8.6] (Lifetime ends)
+// WARNINGS-NEXT:   3:  (CXXConstructExpr, A)
+// ANALYZER-NEXT:   3:  (CXXConstructExpr, [B1.4], A)
+// CHECK-NEXT:   4: A e;
+// CHECK-NEXT:   5: [B1.4].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B1.4] (Lifetime ends)
+// CHECK-NEXT:   7: [B8.2].~A() (Implicit destructor)
+// CHECK-NEXT:   8: [B8.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (2): B2 B5
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -580,14 +623,19 @@ void test_if_implicit_scope() {
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B2.2], A)
 // CHECK-NEXT:   2: A d;
 // CHECK-NEXT:   3: [B2.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B4.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B2.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B4.2].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B4.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B3]
 // CHECK-NEXT:   1: return;
 // CHECK-NEXT:   2: [B4.2].~A() (Implicit destructor)
-// CHECK-NEXT:   3: [B8.6].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B8.2].~A() (Implicit destructor)
+// CHECK-NEXT:   3: [B4.2] (Lifetime ends)
+// CHECK-NEXT:   4: [B8.6].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B8.6] (Lifetime ends)
+// CHECK-NEXT:   6: [B8.2].~A() (Implicit destructor)
+// CHECK-NEXT:   7: [B8.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B4]
@@ -604,14 +652,19 @@ void test_if_implicit_scope() {
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B5.2], A)
 // CHECK-NEXT:   2: A d;
 // CHECK-NEXT:   3: [B5.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B7.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B5.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B7.2].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B7.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B7
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B6]
 // CHECK-NEXT:   1: return;
 // CHECK-NEXT:   2: [B7.2].~A() (Implicit destructor)
-// CHECK-NEXT:   3: [B8.6].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B8.2].~A() (Implicit destructor)
+// CHECK-NEXT:   3: [B7.2] (Lifetime ends)
+// CHECK-NEXT:   4: [B8.6].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B8.6] (Lifetime ends)
+// CHECK-NEXT:   6: [B8.2].~A() (Implicit destructor)
+// CHECK-NEXT:   7: [B8.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B7
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B7]
@@ -661,7 +714,9 @@ void test_if_jumps() {
 // CHECK-NEXT:   Succs (1): B5
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B4.4].~A() (Implicit destructor)
-// CHECK-NEXT:   2: [B5.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B4.4] (Lifetime ends)
+// CHECK-NEXT:   3: [B5.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B5.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -672,12 +727,14 @@ void test_if_jumps() {
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B3.2], A)
 // CHECK-NEXT:   2: A c;
 // CHECK-NEXT:   3: [B3.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B4.4].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B3.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B4.4].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B4.4] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B4]
 // CHECK-NEXT:   1: a
-// CHECK-NEXT:   2: [B4.1] (ImplicitCastExpr, NoOp, const A)
+// CHECK-NEXT:   2: [B4.1] (ImplicitCastExpr, NoOp
 // WARNINGS-NEXT:   3: [B4.2] (CXXConstructExpr, A)
 // ANALYZER-NEXT:   3: [B4.2] (CXXConstructExpr, [B4.4], A)
 // CHECK-NEXT:   4: A b = a;
@@ -708,11 +765,14 @@ void test_while_implicit_scope() {
 // CHECK-NEXT:   Succs (1): B11
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B10.4].~A() (Implicit destructor)
-// WARNINGS-NEXT:   2:  (CXXConstructExpr, A)
-// ANALYZER-NEXT:   2:  (CXXConstructExpr, [B1.3], A)
-// CHECK-NEXT:   3: A e;
-// CHECK-NEXT:   4: [B1.3].~A() (Implicit destructor)
-// CHECK-NEXT:   5: [B11.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B10.4] (Lifetime ends)
+// WARNINGS-NEXT:   3:  (CXXConstructExpr, A)
+// ANALYZER-NEXT:   3:  (CXXConstructExpr, [B1.4], A)
+// CHECK-NEXT:   4: A e;
+// CHECK-NEXT:   5: [B1.4].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B1.4] (Lifetime ends)
+// CHECK-NEXT:   7: [B11.2].~A() (Implicit destructor)
+// CHECK-NEXT:   8: [B11.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (2): B8 B10
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -723,15 +783,21 @@ void test_while_implicit_scope() {
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B3.2], A)
 // CHECK-NEXT:   2: A d;
 // CHECK-NEXT:   3: [B3.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B9.2].~A() (Implicit destructor)
-// CHECK-NEXT:   5: [B10.4].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B3.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B9.2].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B9.2] (Lifetime ends)
+// CHECK-NEXT:   7: [B10.4].~A() (Implicit destructor)
+// CHECK-NEXT:   8: [B10.4] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B4]
 // CHECK-NEXT:   1: return;
 // CHECK-NEXT:   2: [B9.2].~A() (Implicit destructor)
-// CHECK-NEXT:   3: [B10.4].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B11.2].~A() (Implicit destructor)
+// CHECK-NEXT:   3: [B9.2] (Lifetime ends)
+// CHECK-NEXT:   4: [B10.4].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B10.4] (Lifetime ends)
+// CHECK-NEXT:   6: [B11.2].~A() (Implicit destructor)
+// CHECK-NEXT:   7: [B11.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B5]
@@ -742,7 +808,9 @@ void test_while_implicit_scope() {
 // CHECK-NEXT:   Succs (2): B4 B3
 // CHECK:      [B6]
 // CHECK-NEXT:   1: [B9.2].~A() (Implicit destructor)
-// CHECK-NEXT:   2: [B10.4].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B9.2] (Lifetime ends)
+// CHECK-NEXT:   3: [B10.4].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B10.4] (Lifetime ends)
 // CHECK-NEXT:   T: continue;
 // CHECK:        Preds (1): B7
 // CHECK-NEXT:   Succs (1): B2
@@ -754,6 +822,7 @@ void test_while_implicit_scope() {
 // CHECK-NEXT:   Succs (2): B6 B5
 // CHECK:      [B8]
 // CHECK-NEXT:   1: [B9.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B9.2] (Lifetime ends)
 // CHECK-NEXT:   T: break;
 // CHECK:        Preds (1): B9
 // CHECK-NEXT:   Succs (1): B1
@@ -814,6 +883,7 @@ void test_while_jumps() {
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B2.2], A)
 // CHECK-NEXT:   2: A a;
 // CHECK-NEXT:   3: [B2.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B2.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (2): B3 B4
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B3]
@@ -833,7 +903,9 @@ void test_do_implicit_scope() {
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B1.2], A)
 // CHECK-NEXT:   2: A d;
 // CHECK-NEXT:   3: [B1.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B11.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B1.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B11.2].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B11.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (2): B8 B2
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -847,13 +919,17 @@ void test_do_implicit_scope() {
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B3.2], A)
 // CHECK-NEXT:   2: A c;
 // CHECK-NEXT:   3: [B3.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B9.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B3.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B9.2].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B9.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B4]
 // CHECK-NEXT:   1: return;
 // CHECK-NEXT:   2: [B9.2].~A() (Implicit destructor)
-// CHECK-NEXT:   3: [B11.2].~A() (Implicit destructor)
+// CHECK-NEXT:   3: [B9.2] (Lifetime ends)
+// CHECK-NEXT:   4: [B11.2].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B11.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B5]
@@ -864,6 +940,7 @@ void test_do_implicit_scope() {
 // CHECK-NEXT:   Succs (2): B4 B3
 // CHECK:      [B6]
 // CHECK-NEXT:   1: [B9.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B9.2] (Lifetime ends)
 // CHECK-NEXT:   T: continue;
 // CHECK:        Preds (1): B7
 // CHECK-NEXT:   Succs (1): B2
@@ -875,6 +952,7 @@ void test_do_implicit_scope() {
 // CHECK-NEXT:   Succs (2): B6 B5
 // CHECK:      [B8]
 // CHECK-NEXT:   1: [B9.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B9.2] (Lifetime ends)
 // CHECK-NEXT:   T: break;
 // CHECK:        Preds (1): B9
 // CHECK-NEXT:   Succs (1): B1
@@ -914,7 +992,9 @@ void test_do_jumps() {
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B2.6].~A() (Implicit destructor)
-// CHECK-NEXT:   2: [B2.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B2.6] (Lifetime ends)
+// CHECK-NEXT:   3: [B2.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B2.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (2): B3 B2
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -938,6 +1018,7 @@ void test_do_jumps() {
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B3.2], A)
 // CHECK-NEXT:   2: A c;
 // CHECK-NEXT:   3: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B3.2] (Lifetime ends)
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B0 (EXIT)]
 // CHECK-NEXT:   Preds (1): B1
@@ -951,11 +1032,14 @@ void test_switch_implicit_scope() {
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B2.6].~A() (Implicit destructor)
-// WARNINGS-NEXT:   2:  (CXXConstructExpr, A)
-// ANALYZER-NEXT:   2:  (CXXConstructExpr, [B1.3], A)
-// CHECK-NEXT:   3: A g;
-// CHECK-NEXT:   4: [B1.3].~A() (Implicit destructor)
-// CHECK-NEXT:   5: [B2.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B2.6] (Lifetime ends)
+// WARNINGS-NEXT:   3:  (CXXConstructExpr, A)
+// ANALYZER-NEXT:   3:  (CXXConstructExpr, [B1.4], A)
+// CHECK-NEXT:   4: A g;
+// CHECK-NEXT:   5: [B1.4].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B1.4] (Lifetime ends)
+// CHECK-NEXT:   7: [B2.2].~A() (Implicit destructor)
+// CHECK-NEXT:   8: [B2.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (3): B3 B7 B2
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -981,17 +1065,22 @@ void test_switch_implicit_scope() {
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B4]
 // WARNINGS-NEXT:   1:  (CXXConstructExpr, A)
-// ANALYZER-NEXT:   1:  (CXXConstructExpr, [B4.2], A)
+// ANALYZER-NEXT:   1:  (CXXConstructExpr, [B4.2],
 // CHECK-NEXT:   2: A f;
 // CHECK-NEXT:   3: [B4.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B8.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B4.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B8.2].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B8.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B6
 // CHECK-NEXT:   Succs (1): B3
 // CHECK:      [B5]
 // CHECK-NEXT:   1: return;
 // CHECK-NEXT:   2: [B8.2].~A() (Implicit destructor)
-// CHECK-NEXT:   3: [B2.6].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B2.2].~A() (Implicit destructor)
+// CHECK-NEXT:   3: [B8.2] (Lifetime ends)
+// CHECK-NEXT:   4: [B2.6].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B2.6] (Lifetime ends)
+// CHECK-NEXT:   6: [B2.2].~A() (Implicit destructor)
+// CHECK-NEXT:   7: [B2.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B6
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B6]
@@ -1002,6 +1091,7 @@ void test_switch_implicit_scope() {
 // CHECK-NEXT:   Succs (2): B5 B4
 // CHECK:      [B7]
 // CHECK-NEXT:   1: [B8.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B8.2] (Lifetime ends)
 // CHECK-NEXT:   T: break;
 // CHECK:        Preds (1): B8
 // CHECK-NEXT:   Succs (1): B1
@@ -1036,7 +1126,9 @@ void test_switch_jumps() {
 // CHECK-NEXT:   Succs (1): B5
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B4.4].~A() (Implicit destructor)
-// CHECK-NEXT:   2: [B5.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B4.4] (Lifetime ends)
+// CHECK-NEXT:   3: [B5.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B5.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -1044,13 +1136,15 @@ void test_switch_jumps() {
 // CHECK-NEXT:   2: [B2.1].x
 // CHECK-NEXT:   3: ++[B2.2]
 // CHECK-NEXT:   4: [B4.4].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B4.4] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B3
 // CHECK-NEXT:   Succs (1): B4
 // CHECK:      [B3]
 // WARNINGS-NEXT:   1:  (CXXConstructExpr, A)
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B3.2], A)
 // CHECK-NEXT:   2: A c;
-// CHECK-NEXT:   3: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT:   3: [B3.2].~A() (Implicit destruct
+// CHECK-NEXT:   4: [B3.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B4]
@@ -1060,10 +1154,10 @@ void test_switch_jumps() {
 // ANALYZER-NEXT:   3: [B4.2] (CXXConstructExpr, [B4.4], A)
 // CHECK-NEXT:   4: A b = a;
 // CHECK-NEXT:   5: b
-// CHECK-NEXT:   6: [B4.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   6: [B4.5] (ImplicitCastExpr, NoOp
 // CHECK-NEXT:   7: [B4.6].operator int
 // CHECK-NEXT:   8: [B4.6]
-// CHECK-NEXT:   9: [B4.8] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT:   9: [B4.8] (ImplicitCastExpr, User
 // CHECK:       10: [B4.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
 // CHECK-NEXT:   T: for (...; [B4.10]; ...)
 // CHECK-NEXT:   Preds (2): B2 B5
@@ -1082,49 +1176,58 @@ void test_for_implicit_scope() {
 }
 
 // CHECK-LABEL: void test_for_range_implicit_scope()
-// CHECK:      [B5 (ENTRY)]
-// CHECK-NEXT:   Succs (1): B4
+// CHECK:      [B6 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B5
 // CHECK:      [B1]
-// CHECK-NEXT:   1: __begin1
-// CHECK-NEXT:   2: [B1.1] (ImplicitCastExpr, LValueToRValue, int *)
-// CHECK-NEXT:   3: __end1
-// CHECK-NEXT:   4: [B1.3] (ImplicitCastExpr, LValueToRValue, int *)
-// CHECK-NEXT:   5: [B1.2] != [B1.4]
-// CHECK-NEXT:   T: for (int n : [B4.2])
-// CHECK-NEXT:[B3.7]
-// CHECK-NEXT:   Preds (2): B2 B4
-// CHECK-NEXT:   Succs (2): B3 B0
+// CHECK-NEXT:   1: [B5.8] (Lifetime ends)
+// CHECK-NEXT:   2: [B5.11] (Lifetime ends)
+// CHECK-NEXT:   3: [B5.3] (Lifetime ends)
+// CHECK-NEXT:   4: [B5.1] (Lifetime ends)
+// CHECK-NEXT:   Preds (1): B2
+// CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
 // CHECK-NEXT:   1: __begin1
-// CHECK-NEXT:   2: ++[B2.1]
-// CHECK-NEXT:   Preds (1): B3
-// CHECK-NEXT:   Succs (1): B1
+// CHECK-NEXT:   2: [B2.1] (ImplicitCastExpr, LValueToRValue, int *)
+// CHECK-NEXT:   3: __end1
+// CHECK-NEXT:   4: [B2.3] (ImplicitCastExpr, LValueToRValue, int *)
+// CHECK-NEXT:   5: [B2.2] != [B2.4]
+// CHECK-NEXT:   T: for (int n : [B5.2])
+// CHECK-NEXT:[B4.7]
+// CHECK-NEXT:   Preds (2): B3 B5
+// CHECK-NEXT:   Succs (2): B4 B1
 // CHECK:      [B3]
 // CHECK-NEXT:   1: __begin1
-// CHECK-NEXT:   2: [B3.1] (ImplicitCastExpr, LValueToRValue, int *)
-// CHECK-NEXT:   3: *[B3.2]
-// CHECK-NEXT:   4: [B3.3] (ImplicitCastExpr, LValueToRValue, int)
-// CHECK-NEXT:   5: int n
-// WARNINGS-NEXT:   6:  (CXXConstructExpr, A)
-// ANALYZER-NEXT:   6:  (CXXConstructExpr, [B3.7], A)
-// CHECK-NEXT:   7: A c;
-// CHECK-NEXT:   8: [B3.7].~A() (Implicit destructor)
-// CHECK-NEXT:   Preds (1): B1
+// CHECK-NEXT:   2: ++[B3.1]
+// CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B4]
+// CHECK-NEXT:   1: __begin1
+// CHECK-NEXT:   2: [B4.1] (ImplicitCastExpr, LValueToRValue, int *)
+// CHECK-NEXT:   3: *[B4.2]
+// CHECK-NEXT:   4: [B4.3] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT:   5: int n;
+// WARNINGS-NEXT:   6:  (CXXConstructExpr, A)
+// ANALYZER-NEXT:   6:  (CXXConstructExpr, [B4.7], A)
+// CHECK-NEXT:   7: A c;
+// CHECK-NEXT:   8: [B4.7].~A() (Implicit destructor)
+// CHECK-NEXT:   9: [B4.7] (Lifetime ends)
+// CHECK-NEXT:  10: [B4.5] (Lifetime ends)
+// CHECK-NEXT:   Preds (1): B2
+// CHECK-NEXT:   Succs (1): B3
+// CHECK:      [B5]
 // CHECK-NEXT:   1: int nums[4];
 // CHECK-NEXT:   2: nums
 // CHECK-NEXT:   3: auto &&__range1 = nums;
 // CHECK-NEXT:   4: __range1
-// CHECK-NEXT:   5: [B4.4] (ImplicitCastExpr, ArrayToPointerDecay, int *)
+// CHECK-NEXT:   5: [B5.4] (ImplicitCastExpr, ArrayToPointerDecay, int *)
 // CHECK-NEXT:   6: 4{{L*}}
-// CHECK-NEXT:   7: [B4.5] + [B4.6]
+// CHECK-NEXT:   7: [B5.5] + [B5.6]
 // CHECK-NEXT:   8: auto __end1 = __range1 + 4{{L*}};
 // CHECK-NEXT:   9: __range1
-// CHECK-NEXT:  10: [B4.9] (ImplicitCastExpr, ArrayToPointerDecay, int *)
+// CHECK-NEXT:  10: [B5.9] (ImplicitCastExpr, ArrayToPointerDecay, int *)
 // CHECK-NEXT:  11: auto __begin1 = __range1;
-// CHECK-NEXT:   Preds (1): B5
-// CHECK-NEXT:   Succs (1): B1
+// CHECK-NEXT:   Preds (1): B6
+// CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B0 (EXIT)]
 // CHECK-NEXT:   Preds (1): B1
 void test_for_range_implicit_scope() {
@@ -1138,16 +1241,21 @@ void test_for_range_implicit_scope() {
 // CHECK-NEXT:   Succs (1): B11
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B10.4].~A() (Implicit destructor)
-// CHECK-NEXT:   2: [B11.4].~A() (Implicit destructor)
-// WARNINGS-NEXT:   3:  (CXXConstructExpr, A)
-// ANALYZER-NEXT:   3:  (CXXConstructExpr, [B1.4], A)
-// CHECK-NEXT:   4: A f;
-// CHECK-NEXT:   5: [B1.4].~A() (Implicit destructor)
-// CHECK-NEXT:   6: [B11.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B10.4] (Lifetime ends)
+// CHECK-NEXT:   3: [B11.4].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B11.4] (Lifetime ends)
+// WARNINGS-NEXT:   5:  (CXXConstructExpr, A)
+// ANALYZER-NEXT:   5:  (CXXConstructExpr, [B1.6], A)
+// CHECK-NEXT:   6: A f;
+// CHECK-NEXT:   7: [B1.6].~A() (Implicit destructor)
+// CHECK-NEXT:   8: [B1.6] (Lifetime ends)
+// CHECK-NEXT:   9: [B11.2].~A() (Implicit destructor)
+// CHECK-NEXT:  10: [B11.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (2): B8 B10
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
 // CHECK-NEXT:   1: [B10.4].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B10.4] (Lifetime ends)
 // CHECK-NEXT:   Preds (2): B3 B6
 // CHECK-NEXT:   Succs (1): B10
 // CHECK:      [B3]
@@ -1155,15 +1263,21 @@ void test_for_range_implicit_scope() {
 // ANALYZER-NEXT:   1:  (CXXConstructExpr, [B3.2], A)
 // CHECK-NEXT:   2: A e;
 // CHECK-NEXT:   3: [B3.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B9.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B3.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B9.2].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B9.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B4]
 // CHECK-NEXT:   1: return;
 // CHECK-NEXT:   2: [B9.2].~A() (Implicit destructor)
-// CHECK-NEXT:   3: [B10.4].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B11.4].~A() (Implicit destructor)
-// CHECK-NEXT:   5: [B11.2].~A() (Implicit destructor)
+// CHECK-NEXT:   3: [B9.2] (Lifetime ends)
+// CHECK-NEXT:   4: [B10.4].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B10.4] (Lifetime ends)
+// CHECK-NEXT:   6: [B11.4].~A() (Implicit destructor)
+// CHECK-NEXT:   7: [B11.4] (Lifetime ends)
+// CHECK-NEXT:   8: [B11.2].~A() (Implicit destructor)
+// CHECK-NEXT:   9: [B11.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B5]
@@ -1174,6 +1288,7 @@ void test_for_range_implicit_scope() {
 // CHECK-NEXT:   Succs (2): B4 B3
 // CHECK:      [B6]
 // CHECK-NEXT:   1: [B9.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B9.2] (Lifetime ends)
 // CHECK-NEXT:   T: continue;
 // CHECK:        Preds (1): B7
 // CHECK-NEXT:   Succs (1): B2
@@ -1185,6 +1300,7 @@ void test_for_range_implicit_scope() {
 // CHECK-NEXT:   Succs (2): B6 B5
 // CHECK:      [B8]
 // CHECK-NEXT:   1: [B9.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B9.2] (Lifetime ends)
 // CHECK-NEXT:   T: break;
 // CHECK:        Preds (1): B9
 // CHECK-NEXT:   Succs (1): B1
@@ -1239,12 +1355,15 @@ void test_for_jumps() {
 // CHECK-NEXT:     Succs (1): B8
 // CHECK:        [B1]
 // CHECK-NEXT:     1: [B7.4].~A() (Implicit destructor)
-// CHECK-NEXT:     2: [B8.2].~A() (Implicit destructor)
+// CHECK-NEXT:     2: [B7.4] (Lifetime ends)
+// CHECK-NEXT:     3: [B8.2].~A() (Implicit destructor)
+// CHECK-NEXT:     4: [B8.2] (Lifetime ends)
 // CHECK-NEXT:     Preds (1): B7
 // CHECK-NEXT:     Succs (1): B0
 // CHECK:        [B2]
 // CHECK-NEXT:     1: [B5.4] ? [B3.3] : [B4.1]
 // CHECK-NEXT:     2: [B7.4].~A() (Implicit destructor)
+// CHECK-NEXT:     3: [B7.4] (Lifetime ends)
 // CHECK-NEXT:     Preds (2): B3 B4
 // CHECK-NEXT:     Succs (1): B7
 // CHECK:        [B3]
@@ -1260,14 +1379,14 @@ void test_for_jumps() {
 // CHECK:        [B5]
 // CHECK-NEXT:     1: b
 // CHECK-NEXT:     2: [B5.1].x
-// CHECK-NEXT:     3: [B5.2] (ImplicitCastExpr, LValueToRValue, int)
-// CHECK-NEXT:     4: [B5.3] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT:     3: [B5.2] (ImplicitCastExpr, LV
+// CHECK-NEXT:     4: [B5.3] (ImplicitCastExpr, In
 // CHECK-NEXT:     T: [B5.4] ? ... : ...
 // CHECK-NEXT:     Preds (1): B6
 // CHECK-NEXT:     Succs (2): B3 B4
 // CHECK:        [B6]
 // CHECK-NEXT:     1: 0
-// CHECK-NEXT:     2: (void)[B6.1] (CStyleCastExpr, ToVoid, void)
+// CHECK-NEXT:     2: (void)[B6.1] (CStyleCastExpr
 // CHECK-NEXT:     Preds (1): B7
 // CHECK-NEXT:     Succs (1): B5
 // CHECK:        [B7]
@@ -1305,6 +1424,7 @@ void test_for_inc_conditional() {
 // CHECK-NEXT:  catch (const A &e):
 // CHECK-NEXT:   1: catch (const A &e) {
 // CHECK-NEXT:  }
+// CHECK-NEXT:   2: [B2.1] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B1
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B0 (EXIT)]
@@ -1325,6 +1445,7 @@ void test_catch_const_ref() {
 // CHECK-NEXT:   1: catch (A e) {
 // CHECK-NEXT:  }
 // CHECK-NEXT:   2: [B2.1].~A() (Implicit destructor)
+// CHECK-NEXT:   3: [B2.1] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B1
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B0 (EXIT)]
diff --git a/clang/test/Analysis/blocks.mm b/clang/test/Analysis/blocks.mm
index 3ac11aa5a620ed..ed5afebd211a94 100644
--- a/clang/test/Analysis/blocks.mm
+++ b/clang/test/Analysis/blocks.mm
@@ -81,6 +81,7 @@ void testBlockWithCaptureByReference() {
 // CHECK-NEXT:   3: __attribute__((blocks("byref"))) StructWithCopyConstructor s(5);
 // CHECK-NEXT:   4: ^{ }
 // CHECK-NEXT:   5: (void)([B1.4]) (CStyleCastExpr, ToVoid, void)
+// CHECK-NEXT:   6: [B1.3] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B2
 // CHECK-NEXT:   Succs (1): B0
 
diff --git a/clang/test/Analysis/cfg-openmp.cpp b/clang/test/Analysis/cfg-openmp.cpp
index f23c7d454533c9..0c839cd4e927fe 100644
--- a/clang/test/Analysis/cfg-openmp.cpp
+++ b/clang/test/Analysis/cfg-openmp.cpp
@@ -288,7 +288,14 @@ void xxx(int argc) {
 #pragma omp target
 #pragma omp teams firstprivate(fp) reduction(+:rd)
   argc = x;
-// CHECK-NEXT:  [B1.[[#TEAMS+6]]]   Preds
+// CHECK-NEXT:  [B1.[[#TEAMS+6]]] [[#TEAMS+12]]: [B1.7] (Lifetime ends)
+// CHECK-NEXT:  [[#TEAMS+13]]: [B1.6] (Lifetime ends)
+// CHECK-NEXT:  [[#TEAMS+14]]: [B1.5] (Lifetime ends)
+// CHECK-NEXT:  [[#TEAMS+15]]: [B1.4] (Lifetime ends)
+// CHECK-NEXT:  [[#TEAMS+16]]: [B1.3] (Lifetime ends)
+// CHECK-NEXT:  [[#TEAMS+17]]: [B1.2] (Lifetime ends)
+// CHECK-NEXT:  [[#TEAMS+18]]: [B1.1] (Lifetime ends)
+// CHECK-NEXT:   Preds
 }
 
 // CHECK-LABEL:  void dpf(int argc)
diff --git a/clang/test/Analysis/cfg-rich-constructors.cpp b/clang/test/Analysis/cfg-rich-constructors.cpp
index aea983f1f74da0..9e7600853a896c 100644
--- a/clang/test/Analysis/cfg-rich-constructors.cpp
+++ b/clang/test/Analysis/cfg-rich-constructors.cpp
@@ -253,20 +253,22 @@ class D: public C {
 // CHECK-NEXT:     4: [B1.3]
 // CHECK-NEXT:     5: [B1.4] (CXXConstructExpr, C([B1.4]) (Base initializer), C)
 // CHECK-NEXT:     6: C([B1.5]) (Base initializer)
-// CHECK-NEXT:     7: CFGNewAllocator(C *)
-// CHECK-NEXT:     8: C::get
-// CHECK-NEXT:     9: [B1.8] (ImplicitCastExpr, FunctionToPointerDecay, C (*)(void))
-// CXX11-ELIDE-NEXT:    10: [B1.9]() (CXXRecordTypedCall, [B1.11], [B1.12])
-// CXX11-NOELIDE-NEXT:    10: [B1.9]() (CXXRecordTypedCall, [B1.11])
-// CXX11-NEXT:    11: [B1.10]
-// CXX11-NEXT:    12: [B1.11] (CXXConstructExpr, [B1.13], C)
-// CXX11-NEXT:    13: new C([B1.12])
-// CXX11-NEXT:    14: [B1.13] (CXXConstructExpr, c1([B1.13]) (Member initializer), C)
-// CXX11-NEXT:    15: c1([B1.14]) (Member initializer)
-// CXX17-NEXT:    10: [B1.9]()
-// CXX17-NEXT:    11: new C([B1.10])
-// CXX17-NEXT:    12: [B1.11] (CXXConstructExpr, c1([B1.11]) (Member initializer), C)
-// CXX17-NEXT:    13: c1([B1.12]) (Member initializer)
+// CHECK-NEXT:     7: (FullExprCleanup collected 1 MTE: [B1.3])
+// CHECK-NEXT:     8: CFGNewAllocator(C *)
+// CHECK-NEXT:     9: C::get
+// CHECK-NEXT:    10: [B1.9] (ImplicitCastExpr, FunctionToPointerDecay, C (*)(void))
+// CXX11-ELIDE-NEXT:    11: [B1.10]() (CXXRecordTypedCall, [B1.12], [B1.13])
+// CXX11-NOELIDE-NEXT:    11: [B1.10]() (CXXRecordTypedCall, [B1.12])
+// CXX11-NEXT:    12: [B1.11]
+// CXX11-NEXT:    13: [B1.12] (CXXConstructExpr, [B1.14], C)
+// CXX11-NEXT:    14: new C([B1.13])
+// CXX11-NEXT:    15: [B1.14] (CXXConstructExpr, c1([B1.14]) (Member initializer), C)
+// CXX11-NEXT:    16: c1([B1.15]) (Member initializer)
+// CXX11-NEXT:    17: (FullExprCleanup collected 1 MTE: [B1.11])
+// CXX17-NEXT:    11: [B1.10]()
+// CXX17-NEXT:    12: new C([B1.11])
+// CXX17-NEXT:    13: [B1.12] (CXXConstructExpr, c1([B1.12]) (Member initializer), C)
+// CXX17-NEXT:    14: c1([B1.13]) (Member initializer)
   D(double): C(C::get()), c1(new C(C::get())) {}
 };
 
@@ -292,7 +294,8 @@ class F {
 // CXX11-NEXT:     6: [B1.5]
 // CXX11-NEXT:     7: [B1.6] (CXXConstructExpr, e([B1.6]) (Member initializer), E)
 // CXX11-NEXT:     8: e([B1.7]) (Member initializer)
-// CXX11-NEXT:     9: ~E() (Temporary object destructor)
+// CXX11-NEXT:     9: (FullExprCleanup collected 1 MTE: [B1.5])
+// CXX11-NEXT:    10: ~E() (Temporary object destructor)
 // CXX17-NEXT:     3: [B1.2]() (CXXRecordTypedCall, e([B1.4]) (Member initializer), [B1.4])
 // CXX17-NEXT:     4: [B1.3] (BindTemporary)
 // CXX17-NEXT:     5: e([B1.4]) (Member initializer)
@@ -345,8 +348,9 @@ C returnBracesWithMultipleItems() {
 // CXX11-ELIDE:    1: C() (CXXConstructExpr, [B1.2], [B1.3], C)
 // CXX11-NOELIDE:  1: C() (CXXConstructExpr, [B1.2], C)
 // CXX11-NEXT:     2: [B1.1]
-// CXX11-NEXT:     3: [B1.2] (CXXConstructExpr, [B1.4], C)
-// CXX11-NEXT:     4: return [B1.3];
+// CXX11-NEXT:     3: [B1.2] (CXXConstructExpr, [B1.5], C)
+// CXX11-NEXT:     4: (FullExprCleanup collected 1 MTE: [B1.1])
+// CXX11-NEXT:     5: return [B1.3];
 // CXX17:          1: C() (CXXConstructExpr, [B1.2], C)
 // CXX17-NEXT:     2: return [B1.1];
 C returnTemporary() {
@@ -361,8 +365,9 @@ C returnTemporary() {
 // CXX17-NEXT:     3: [B1.2] (CXXConstructExpr, [B1.5], C)
 // CHECK-NEXT:     4: C([B1.3]) (CXXFunctionalCastExpr, ConstructorConversion, C)
 // CXX11-NEXT:     5: [B1.4]
-// CXX11-NEXT:     6: [B1.5] (CXXConstructExpr, [B1.7], C)
-// CXX11-NEXT:     7: return [B1.6];
+// CXX11-NEXT:     6: [B1.5] (CXXConstructExpr, [B1.8], C)
+// CXX11-NEXT:     7: (FullExprCleanup collected 1 MTE: [B1.4])
+// CXX11-NEXT:     8: return [B1.6];
 // CXX17-NEXT:     5: return [B1.4];
 
 C returnTemporaryWithArgument() {
@@ -375,8 +380,9 @@ C returnTemporaryWithArgument() {
 // CXX11-ELIDE-NEXT:     3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.5])
 // CXX11-NOELIDE-NEXT:     3: [B1.2]() (CXXRecordTypedCall, [B1.4])
 // CXX11-NEXT:     4: [B1.3]
-// CXX11-NEXT:     5: [B1.4] (CXXConstructExpr, [B1.6], C)
-// CXX11-NEXT:     6: return [B1.5];
+// CXX11-NEXT:     5: [B1.4] (CXXConstructExpr, [B1.7], C)
+// CXX11-NEXT:     6: (FullExprCleanup collected 1 MTE: [B1.3])
+// CXX11-NEXT:     7: return [B1.5];
 // CXX17-NEXT:     3: [B1.2]() (CXXRecordTypedCall, [B1.4])
 // CXX17-NEXT:     4: return [B1.3];
 C returnTemporaryConstructedByFunction() {
@@ -393,8 +399,9 @@ C returnTemporaryConstructedByFunction() {
 // CXX11-NOELIDE-NEXT:     5: [B1.4] (CXXConstructExpr, [B1.7], C)
 // CXX11-NEXT:     6: C([B1.5]) (CXXFunctionalCastExpr, ConstructorConversion, C)
 // CXX11-NEXT:     7: [B1.6]
-// CXX11-NEXT:     8: [B1.7] (CXXConstructExpr, [B1.9], C)
-// CXX11-NEXT:     9: return [B1.8];
+// CXX11-NEXT:     8: [B1.7] (CXXConstructExpr, [B1.10], C)
+// CXX11-NEXT:     9: (FullExprCleanup collected 2 MTEs: [B1.6], [B1.3])
+// CXX11-NEXT:    10: return [B1.8];
 // CXX17-NEXT:     3: [B1.2]() (CXXRecordTypedCall, [B1.5])
 // CXX17-NEXT:     4: C([B1.3]) (CXXFunctionalCastExpr, NoOp, C)
 // CXX17-NEXT:     5: return [B1.4];
@@ -418,9 +425,10 @@ class D {
 // CXX11-NEXT:     2: [B1.1] (BindTemporary)
 // CXX11-NEXT:     3: [B1.2] (ImplicitCastExpr, NoOp, const D)
 // CXX11-NEXT:     4: [B1.3]
-// CXX11-NEXT:     5: [B1.4] (CXXConstructExpr, [B1.7], D)
-// CXX11-NEXT:     6: ~D() (Temporary object destructor)
-// CXX11-NEXT:     7: return [B1.5];
+// CXX11-NEXT:     5: [B1.4] (CXXConstructExpr, [B1.8], D)
+// CXX11-NEXT:     6: (FullExprCleanup collected 1 MTE: [B1.3])
+// CXX11-NEXT:     7: ~D() (Temporary object destructor)
+// CXX11-NEXT:     8: return [B1.5];
 // CXX17:          1: D() (CXXConstructExpr, [B1.3], [B1.2], D)
 // CXX17-NEXT:     2: [B1.1] (BindTemporary)
 // CXX17-NEXT:     3: return [B1.2];
@@ -438,11 +446,15 @@ D returnTemporary() {
 // CXX11-NEXT:     6: [B1.5]
 // CXX11-NEXT:     7: [B1.6] (CXXConstructExpr, [B1.8], D)
 // CXX11-NEXT:     8: D d = returnTemporary();
-// CXX11-NEXT:     9: ~D() (Temporary object destructor)
-// CXX11-NEXT:    10: [B1.8].~D() (Implicit destructor)
+// CXX11-NEXT:     9: (FullExprCleanup collected 1 MTE: [B1.5])
+// CXX11-NEXT:    10: ~D() (Temporary object destructor)
+// CXX11-NEXT:    11: [B1.8].~D() (Implicit destructor)
+// CXX11-NEXT:    12: [B1.8] (Lifetime ends)
 // CXX17-NEXT:     3: [B1.2]() (CXXRecordTypedCall, [B1.5], [B1.4])
 // CXX17-NEXT:     4: [B1.3] (BindTemporary)
 // CXX17-NEXT:     5: D d = returnTemporary();
+// CXX17-NEXT:     6: [B1.5].~D() (Implicit destructor)
+// CXX17-NEXT:     7: [B1.5] (Lifetime ends)
 void returnByValueIntoVariable() {
   D d = returnTemporary();
 }
@@ -466,90 +478,148 @@ void simpleTemporary() {
 // CHECK-NEXT:     4: [B2.3].operator bool
 // CHECK-NEXT:     5: [B2.3]
 // CHECK-NEXT:     6: [B2.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK-NEXT:     7: (FullExprCleanup collected 1 MTE: [B2.1])
 // CHECK-NEXT:     T: if [B2.6]
 void temporaryInCondition() {
   if (C());
 }
 
 // CHECK: void temporaryInConditionVariable()
-// CXX11-ELIDE:    1: C() (CXXConstructExpr, [B2.2], [B2.3], C)
-// CXX11-NOELIDE:  1: C() (CXXConstructExpr, [B2.2], C)
-// CXX11-NEXT:     2: [B2.1]
-// CXX11-NEXT:     3: [B2.2] (CXXConstructExpr, [B2.4], C)
+// CHECK:      [B4 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B3
+// CHECK:      [B1]
+// CXX11-NEXT:     1: [B3.4] (Lifetime ends)
+// CXX17-NEXT:     1: [B3.2] (Lifetime ends)
+// CHECK-NEXT:   Preds (2): B2 B3
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B2]
+// CHECK-NEXT:   Preds (1): B3
+// CHECK-NEXT:   Succs (1): B1
+// CHECK:      [B3]
+// CXX11-ELIDE-NEXT:    1: C() (CXXConstructExpr, [B3.2], [B3.3], C)
+// CXX11-NOELIDE-NEXT:  1: C() (CXXConstructExpr, [B3.2], C)
+// CXX11-NEXT:     2: [B3.1]
+// CXX11-NEXT:     3: [B3.2] (CXXConstructExpr, [B3.4], C)
 // CXX11-NEXT:     4: C c = C();
-// CXX11-NEXT:     5: c
-// CXX11-NEXT:     6: [B2.5] (ImplicitCastExpr, NoOp, const class C)
-// CXX11-NEXT:     7: [B2.6].operator bool
-// CXX11-NEXT:     8: [B2.6]
-// CXX11-NEXT:     9: [B2.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CXX11-NEXT:     T: if [B2.9]
-// CXX17:          1: C() (CXXConstructExpr, [B2.2], C)
+// CXX11-NEXT:     5: (FullExprCleanup collected 1 MTE: [B3.1])
+// CXX11-NEXT:     6: c
+// CXX11-NEXT:     7: [B3.6] (ImplicitCastExpr, NoOp, const class C)
+// CXX11-NEXT:     8: [B3.7].operator bool
+// CXX11-NEXT:     9: [B3.7]
+// CXX11-NEXT:    10: [B3.9] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX11-NEXT:     T: if [B3.10]
+// CXX17:          1: C() (CXXConstructExpr, [B3.2], C)
 // CXX17-NEXT:     2: C c = C();
 // CXX17-NEXT:     3: c
-// CXX17-NEXT:     4: [B2.3] (ImplicitCastExpr, NoOp, const class C)
-// CXX17-NEXT:     5: [B2.4].operator bool
-// CXX17-NEXT:     6: [B2.4]
-// CXX17-NEXT:     7: [B2.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CXX17-NEXT:     T: if [B2.7]
+// CXX17-NEXT:     4: [B3.3] (ImplicitCastExpr, NoOp, const class C)
+// CXX17-NEXT:     5: [B3.4].operator bool
+// CXX17-NEXT:     6: [B3.4]
+// CXX17-NEXT:     7: [B3.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX17-NEXT:     T: if [B3.7]
+// CHECK-NEXT:   Preds (1): B4
+// CHECK-NEXT:   Succs (2): B2 B1
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (1): B1
 void temporaryInConditionVariable() {
   if (C c = C());
 }
 
 
 // CHECK: void temporaryInForLoopConditionVariable()
-// CHECK:        [B2]
-// CXX11-ELIDE-NEXT:     1: C() (CXXConstructExpr, [B2.2], [B2.3], C)
-// CXX11-NOELIDE-NEXT:     1: C() (CXXConstructExpr, [B2.2], C)
-// CXX11-NEXT:     2: [B2.1]
-// CXX11-NEXT:     3: [B2.2] (CXXConstructExpr, [B2.4], C)
-// CXX11-NEXT:     4: C c2 = C();
-// CXX11-NEXT:     5: c2
-// CXX11-NEXT:     6: [B2.5] (ImplicitCastExpr, NoOp, const class C)
-// CXX11-NEXT:     7: [B2.6].operator bool
-// CXX11-NEXT:     8: [B2.6]
-// CXX11-NEXT:     9: [B2.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CXX11-NEXT:     T: for (...; [B2.9]; )
-// CXX17-NEXT:     1: C() (CXXConstructExpr, [B2.2], C)
-// CXX17-NEXT:     2: C c2 = C();
-// CXX17-NEXT:     3: c2
-// CXX17-NEXT:     4: [B2.3] (ImplicitCastExpr, NoOp, const class C)
-// CXX17-NEXT:     5: [B2.4].operator bool
-// CXX17-NEXT:     6: [B2.4]
-// CXX17-NEXT:     7: [B2.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CXX17-NEXT:     T: for (...; [B2.7]; )
-// CHECK:        [B3]
+// CHECK:      [B5 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B4
+// CHECK:      [B1]
+// CXX11-NEXT:     1: [B3.5] (Lifetime ends)
+// CXX17-NEXT:     1: [B3.2] (Lifetime ends)
+// CXX11-NEXT:     2: [B4.4] (Lifetime ends)
+// CXX17-NEXT:     2: [B4.2] (Lifetime ends)
+// CHECK-NEXT:   Preds (1): B3
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B2]
+// CXX11-NEXT:     1: [B3.5] (Lifetime ends)
+// CXX17-NEXT:     1: [B3.2] (Lifetime ends)
+// CHECK-NEXT:   Preds (1): B3
+// CHECK-NEXT:   Succs (1): B3
+// CHECK:      [B3]
 // CXX11-ELIDE-NEXT:     1: C() (CXXConstructExpr, [B3.2], [B3.3], C)
 // CXX11-NOELIDE-NEXT:     1: C() (CXXConstructExpr, [B3.2], C)
 // CXX11-NEXT:     2: [B3.1]
-// CXX11-NEXT:     3: [B3.2] (CXXConstructExpr, [B3.4], C)
-// CXX11-NEXT:     4: C c1 = C();
+// CXX11-NEXT:     3: [B3.2] (CXXConstructExpr, [B3.5], C)
+// CXX11-NEXT:     4: (FullExprCleanup collected 1 MTE: [B3.1])
+// CXX11-NEXT:     5: C c2 = C();
+// CXX11-NEXT:     6: c2
+// CXX11-NEXT:     7: [B3.6] (ImplicitCastExpr, NoOp, const class C)
+// CXX11-NEXT:     8: [B3.7].operator bool
+// CXX11-NEXT:     9: [B3.7]
+// CXX11-NEXT:    10: [B3.9] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX11-NEXT:     T: for (...; [B3.10]; )
 // CXX17-NEXT:     1: C() (CXXConstructExpr, [B3.2], C)
+// CXX17-NEXT:     2: C c2 = C();
+// CXX17-NEXT:     3: c2
+// CXX17-NEXT:     4: [B3.3] (ImplicitCastExpr, NoOp, const class C)
+// CXX17-NEXT:     5: [B3.4].operator bool
+// CXX17-NEXT:     6: [B3.4]
+// CXX17-NEXT:     7: [B3.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX17-NEXT:     T: for (...; [B3.7]; )
+// CHECK-NEXT:   Preds (2): B2 B4
+// CHECK-NEXT:   Succs (2): B2 B1
+// CHECK:      [B4]
+// CXX11-ELIDE-NEXT:     1: C() (CXXConstructExpr, [B4.2], [B4.3], C)
+// CXX11-NOELIDE-NEXT:     1: C() (CXXConstructExpr, [B4.2], C)
+// CXX11-NEXT:     2: [B4.1]
+// CXX11-NEXT:     3: [B4.2] (CXXConstructExpr, [B4.4], C)
+// CXX11-NEXT:     4: C c1 = C();
+// CXX11-NEXT:     5: (FullExprCleanup collected 1 MTE: [B4.1])
+// CXX17-NEXT:     1: C() (CXXConstructExpr, [B4.2], C)
 // CXX17-NEXT:     2: C c1 = C();
+// CHECK-NEXT:   Preds (1): B5
+// CHECK-NEXT:   Succs (1): B3
+// CHECK:      [B0 (EXIT)]
 void temporaryInForLoopConditionVariable() {
   for (C c1 = C(); C c2 = C(); );
 }
 
 
 // CHECK: void temporaryInWhileLoopConditionVariable()
-// CXX11-ELIDE:          1: C() (CXXConstructExpr, [B2.2], [B2.3], C)
-// CXX11-NOELIDE:          1: C() (CXXConstructExpr, [B2.2], C)
-// CXX11-NEXT:     2: [B2.1]
-// CXX11-NEXT:     3: [B2.2] (CXXConstructExpr, [B2.4], C)
-// CXX11-NEXT:     4: C c = C();
-// CXX11-NEXT:     5: c
-// CXX11-NEXT:     6: [B2.5] (ImplicitCastExpr, NoOp, const class C)
-// CXX11-NEXT:     7: [B2.6].operator bool
-// CXX11-NEXT:     8: [B2.6]
-// CXX11-NEXT:     9: [B2.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CXX11-NEXT:     T: while [B2.9]
-// CXX17:          1: C() (CXXConstructExpr, [B2.2], C)
+// CHECK:      [B5 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B4
+// CHECK:      [B1]
+// CXX11-NEXT:     1: [B4.5] (Lifetime ends)
+// CXX17-NEXT:     1: [B4.2] (Lifetime ends)
+// CHECK-NEXT:   Preds (1): B4
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B2]
+// CHECK-NEXT:   Preds (1): B3
+// CHECK-NEXT:   Succs (1): B4
+// CHECK:      [B3]
+// CXX11-NEXT:     1: [B4.5] (Lifetime ends)
+// CXX17-NEXT:     1: [B4.2] (Lifetime ends)
+// CHECK-NEXT:   Preds (1): B4
+// CHECK-NEXT:   Succs (1): B2
+// CHECK:      [B4]
+// CXX11-ELIDE:          1: C() (CXXConstructExpr, [B4.2], [B4.3], C)
+// CXX11-NOELIDE:          1: C() (CXXConstructExpr, [B4.2], C)
+// CXX11-NEXT:     2: [B4.1]
+// CXX11-NEXT:     3: [B4.2] (CXXConstructExpr, [B4.5], C)
+// CXX11-NEXT:     4: (FullExprCleanup collected 1 MTE: [B4.1])
+// CXX11-NEXT:     5: C c = C();
+// CXX11-NEXT:     6: c
+// CXX11-NEXT:     7: [B4.6] (ImplicitCastExpr, NoOp, const class C)
+// CXX11-NEXT:     8: [B4.7].operator bool
+// CXX11-NEXT:     9: [B4.7]
+// CXX11-NEXT:    10: [B4.9] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX11-NEXT:     T: while [B4.10]
+// CXX17:          1: C() (CXXConstructExpr, [B4.2], C)
 // CXX17-NEXT:     2: C c = C();
 // CXX17-NEXT:     3: c
-// CXX17-NEXT:     4: [B2.3] (ImplicitCastExpr, NoOp, const class C)
-// CXX17-NEXT:     5: [B2.4].operator bool
-// CXX17-NEXT:     6: [B2.4]
-// CXX17-NEXT:     7: [B2.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CXX17-NEXT:     T: while [B2.7]
+// CXX17-NEXT:     4: [B4.3] (ImplicitCastExpr, NoOp, const class C)
+// CXX17-NEXT:     5: [B4.4].operator bool
+// CXX17-NEXT:     6: [B4.4]
+// CXX17-NEXT:     7: [B4.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX17-NEXT:     T: while [B4.7]
+// CHECK-NEXT:   Preds (2): B2 B5
+// CHECK-NEXT:   Succs (2): B3 B1
+// CHECK:      [B0 (EXIT)]
 void temporaryInWhileLoopConditionVariable() {
   while (C c = C());
 }
@@ -578,15 +648,26 @@ void simpleTemporary() {
 }
 
 // CHECK:  void temporaryInCondition()
-// CHECK:          1: D() (CXXConstructExpr, [B2.2], [B2.3], D)
+// CHECK:      [B3 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B2
+// CHECK:      [B1]
+// CHECK-NEXT:   Preds (1): B2
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B2]
+// CHECK-NEXT:     1: D() (CXXConstructExpr, [B2.2], [B2.3], D)
 // CHECK-NEXT:     2: [B2.1] (BindTemporary)
 // CHECK-NEXT:     3: [B2.2]
 // CHECK-NEXT:     4: [B2.3] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
 // CHECK-NEXT:     5: [B2.4].operator bool
 // CHECK-NEXT:     6: [B2.4]
 // CHECK-NEXT:     7: [B2.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK-NEXT:     8: ~D() (Temporary object destructor)
+// CHECK-NEXT:     8: (FullExprCleanup collected 1 MTE: [B2.2])
+// CHECK-NEXT:     9: ~D() (Temporary object destructor)
 // CHECK-NEXT:     T: if [B2.7]
+// CHECK-NEXT:   Preds (1): B3
+// CHECK-NEXT:   Succs (2): B1 B0
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (2): B1 B2
 void temporaryInCondition() {
   if (D());
 }
@@ -614,8 +695,11 @@ void referenceVariableWithInitializer() {
 }
 
 // CHECK: void referenceVariableWithTernaryOperator(bool coin)
+// CXX11:      [B8 (ENTRY)]
+// CXX11-NEXT:   Succs (1): B7
 // CXX11:        [B1]
 // CXX11-NEXT:     1: [B4.4].~D() (Implicit destructor)
+// CXX11-NEXT:     2: [B4.4] (Lifetime ends)
 // CXX11:        [B2]
 // CXX11-NEXT:     1: ~D() (Temporary object destructor)
 // CXX11:        [B3]
@@ -625,6 +709,7 @@ void referenceVariableWithInitializer() {
 // CXX11-NEXT:     2: [B4.1] (ImplicitCastExpr, NoOp, const D)
 // CXX11-NEXT:     3: [B4.2]
 // CXX11-NEXT:     4: const D &d = coin ? D::get() : D(0);
+// CXX11-NEXT:     5: (FullExprCleanup collected 2 MTEs: [B5.5], [B6.5])
 // CXX11-NEXT:     T: (Temp Dtor) [B6.3]
 // CXX11:        [B5]
 // CXX11-NEXT:     1: D::get
@@ -650,12 +735,15 @@ void referenceVariableWithInitializer() {
 // CXX11-NEXT:     1: coin
 // CXX11-NEXT:     2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
 // CXX11-NEXT:     T: [B7.2] ? ... : ...
+// CXX17:      [B5 (ENTRY)]
+// CXX17-NEXT:   Succs (1): B4
 // CXX17:        [B1]
 // CXX17-NEXT:     1: [B4.2] ? [B2.4] : [B3.4]
 // CXX17-NEXT:     2: [B1.1] (ImplicitCastExpr, NoOp, const D)
 // CXX17-NEXT:     3: [B1.2]
 // CXX17-NEXT:     4: const D &d = coin ? D::get() : D(0);
 // CXX17-NEXT:     5: [B1.4].~D() (Implicit destructor)
+// CXX17-NEXT:     6: [B1.4] (Lifetime ends)
 // CXX17:        [B2]
 // CXX17-NEXT:     1: D::get
 // CXX17-NEXT:     2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, D (*)(void))
@@ -737,14 +825,18 @@ class B {
 // CXX11-NEXT:     8: [B1.7]
 // CXX11-NEXT:     9: [B1.8] (CXXConstructExpr, [B1.10], B)
 // CXX11-NEXT:    10: B b = A();
-// CXX11-NEXT:    11: ~B() (Temporary object destructor)
-// CXX11-NEXT:    12: [B1.10].~B() (Implicit destructor)
+// CXX11-NEXT:    11: (FullExprCleanup collected 2 MTEs: [B1.7], [B1.2])
+// CXX11-NEXT:    12: ~B() (Temporary object destructor)
+// CXX11-NEXT:    13: [B1.10].~B() (Implicit destructor)
+// CXX11-NEXT:    14: [B1.10] (Lifetime ends)
 // CXX17-NEXT:     2: [B1.1] (ImplicitCastExpr, NoOp, const A)
 // CXX17-NEXT:     3: [B1.2]
 // CXX17-NEXT:     4: [B1.3] (CXXConstructExpr, [B1.6], B)
 // CXX17-NEXT:     5: [B1.4] (ImplicitCastExpr, ConstructorConversion, B)
 // CXX17-NEXT:     6: B b = A();
-// CXX17-NEXT:     7: [B1.6].~B() (Implicit destructor)
+// CXX17-NEXT:     7: (FullExprCleanup collected 1 MTE: [B1.2])
+// CXX17-NEXT:     8: [B1.6].~B() (Implicit destructor)
+// CXX17-NEXT:     9: [B1.6] (Lifetime ends)
 void implicitConstructionConversionFromTemporary() {
   B b = A();
 }
@@ -763,12 +855,16 @@ void implicitConstructionConversionFromTemporary() {
 // CXX11-NEXT:    10: [B1.9]
 // CXX11-NEXT:    11: [B1.10] (CXXConstructExpr, [B1.12], B)
 // CXX11-NEXT:    12: B b = get();
-// CXX11-NEXT:    13: ~B() (Temporary object destructor)
-// CXX11-NEXT:    14: [B1.12].~B() (Implicit destructor)
+// CXX11-NEXT:    13: (FullExprCleanup collected 2 MTEs: [B1.9], [B1.4])
+// CXX11-NEXT:    14: ~B() (Temporary object destructor)
+// CXX11-NEXT:    15: [B1.12].~B() (Implicit destructor)
+// CXX11-NEXT:    16: [B1.12] (Lifetime ends)
 // CXX17-NEXT:     6: [B1.5] (CXXConstructExpr, [B1.8], B)
 // CXX17-NEXT:     7: [B1.6] (ImplicitCastExpr, ConstructorConversion, B)
 // CXX17-NEXT:     8: B b = get();
-// CXX17-NEXT:     9: [B1.8].~B() (Implicit destructor)
+// CXX17-NEXT:     9: (FullExprCleanup collected 1 MTE: [B1.4])
+// CXX17-NEXT:    10: [B1.8].~B() (Implicit destru
+// CXX17-NEXT:    11: [B1.8] (Lifetime ends)
 void implicitConstructionConversionFromFunctionValue() {
   B b = get();
 }
@@ -782,7 +878,9 @@ void implicitConstructionConversionFromFunctionValue() {
 // CHECK-NEXT:     6: [B1.5] (ImplicitCastExpr, NoOp, const B)
 // CHECK-NEXT:     7: [B1.6]
 // CHECK-NEXT:     8: const B &b = A();
-// CHECK-NEXT:     9: [B1.8].~B() (Implicit destructor)
+// CHECK-NEXT:     9: (FullExprCleanup collected 1 MTE: [B1.2])
+// CHECK-NEXT:    10: [B1.8].~B() (Implicit destructor)
+// CHECK-NEXT:    11: [B1.8] (Lifetime ends)
 void implicitConstructionConversionFromTemporaryWithLifetimeExtension() {
   const B &b = A();
 }
@@ -798,7 +896,9 @@ void implicitConstructionConversionFromTemporaryWithLifetimeExtension() {
 // CHECK-NEXT:     8: [B1.7] (ImplicitCastExpr, NoOp, const B)
 // CHECK-NEXT:     9: [B1.8]
 // CHECK-NEXT:    10: const B &b = get();
-// CHECK-NEXT:    11: [B1.10].~B() (Implicit destructor)
+// CHECK-NEXT:    11: (FullExprCleanup collected 1 MTE: [B1.4])
+// CHECK-NEXT:    12: [B1.10].~B() (Implicit destructor)
+// CHECK-NEXT:    13: [B1.10] (Lifetime ends)
 void implicitConstructionConversionFromFunctionValueWithLifetimeExtension() {
   const B &b = get(); // no-crash
 }
@@ -854,8 +954,9 @@ void passArgument() {
 // CXX11-NEXT:    10: [B1.9] (CXXConstructExpr, [B1.11], [B1.12]+1, D)
 // CXX11-NEXT:    11: [B1.10] (BindTemporary)
 // CXX11-NEXT:    12: [B1.2]([B1.5], [B1.11])
-// CXX11-NEXT:    13: ~D() (Temporary object destructor)
+// CXX11-NEXT:    13: (FullExprCleanup collected 2 MTEs: [B1.3], [B1.8])
 // CXX11-NEXT:    14: ~D() (Temporary object destructor)
+// CXX11-NEXT:    15: ~D() (Temporary object destructor)
 // CXX17-NEXT:     3: C() (CXXConstructExpr, [B1.6]+0, C)
 // CXX17-NEXT:     4: D() (CXXConstructExpr, [B1.5], [B1.6]+1, D)
 // CXX17-NEXT:     5: [B1.4] (BindTemporary)
@@ -887,8 +988,9 @@ void passArgumentByReference() {
 // CXX11-NEXT:     7: [B1.6] (CXXConstructExpr, [B1.8], [B1.9]+0, D)
 // CXX11-NEXT:     8: [B1.7] (BindTemporary)
 // CXX11-NEXT:     9: [B1.2]([B1.8])
-// CXX11-NEXT:    10: ~D() (Temporary object destructor)
+// CXX11-NEXT:    10: (FullExprCleanup collected 1 MTE: [B1.5])
 // CXX11-NEXT:    11: ~D() (Temporary object destructor)
+// CXX11-NEXT:    12: ~D() (Temporary object destructor)
 // CXX17-NEXT:     3: D() (CXXConstructExpr, [B1.4], [B1.5]+0, D)
 // CXX17-NEXT:     4: [B1.3] (BindTemporary)
 // CXX17-NEXT:     5: [B1.2]([B1.4])
@@ -905,7 +1007,8 @@ void passArgumentWithDestructor() {
 // CHECK-NEXT:     5: [B1.4] (ImplicitCastExpr, NoOp, const D)
 // CHECK-NEXT:     6: [B1.5]
 // CHECK-NEXT:     7: [B1.2]([B1.6])
-// CHECK-NEXT:     8: ~D() (Temporary object destructor)
+// CHECK-NEXT:     8: (FullExprCleanup collected 1 MTE: [B1.5])
+// CHECK-NEXT:     9: ~D() (Temporary object destructor)
 void passArgumentWithDestructorByReference() {
   useDByReference(D());
 }
@@ -924,14 +1027,17 @@ void passArgumentWithDestructorByReference() {
 // CXX11-NEXT:     9: [B1.8]
 // CXX11-NEXT:    10: [B1.9] (CXXConstructExpr, [B1.11], E)
 // CXX11-NEXT:    11: E e = E(D());
-// CXX11-NEXT:    12: ~D() (Temporary object destructor)
+// CXX11-NEXT:    12: (FullExprCleanup collected 2 MTEs: [B1.8], [B1.3])
 // CXX11-NEXT:    13: ~D() (Temporary object destructor)
+// CXX11-NEXT:    14: ~D() (Temporary object destructor)
+// CXX11-NEXT:    15: [B1.11] (Lifetime ends)
 // CXX17:          1: D() (CXXConstructExpr, [B1.2], [B1.3]+0, D)
 // CXX17-NEXT:     2: [B1.1] (BindTemporary)
 // CXX17-NEXT:     3: [B1.2] (CXXConstructExpr, [B1.5], E)
 // CXX17-NEXT:     4: E([B1.3]) (CXXFunctionalCastExpr, ConstructorConversion, E)
 // CXX17-NEXT:     5: E e = E(D());
 // CXX17-NEXT:     6: ~D() (Temporary object destructor)
+// CXX17-NEXT:     7: [B1.5] (Lifetime ends)
 void passArgumentIntoAnotherConstructor() {
   E e = E(D());
 }
@@ -953,17 +1059,11 @@ void passArgumentIntoAnotherConstructor() {
 // CXX11-NEXT:    11: [B1.10] (CXXConstructExpr, [B1.12], [B1.13]+1, D)
 // CXX11-NEXT:    12: [B1.11] (BindTemporary)
 // CXX11-NEXT:    13: E([B1.6], [B1.12]) (CXXConstructExpr, E)
-// CXX11-NEXT:    14: ~D() (Temporary object destructor)
+// CXX11-NEXT:    14: (FullExprCleanup collected 2 MTEs: [B1.3], [B1.9])
 // CXX11-NEXT:    15: ~D() (Temporary object destructor)
 // CXX11-NEXT:    16: ~D() (Temporary object destructor)
 // CXX11-NEXT:    17: ~D() (Temporary object destructor)
-// CXX17:          1: D() (CXXConstructExpr, [B1.2], [B1.5]+0, D)
-// CXX17-NEXT:     2: [B1.1] (BindTemporary)
-// CXX17-NEXT:     3: D() (CXXConstructExpr, [B1.4], [B1.5]+1, D)
-// CXX17-NEXT:     4: [B1.3] (BindTemporary)
-// CXX17-NEXT:     5: E([B1.2], [B1.4]) (CXXConstructExpr, E)
-// CXX17-NEXT:     6: ~D() (Temporary object destructor)
-// CXX17-NEXT:     7: ~D() (Temporary object destructor)
+// CXX11-NEXT:    18: ~D() (Temporary object destructor)
 void passTwoArgumentsIntoAnotherConstructor() {
   E(D(), D());
 }
diff --git a/clang/test/Analysis/cfg-rich-constructors.mm b/clang/test/Analysis/cfg-rich-constructors.mm
index f048f061e9fba1..155ae9ceef3b33 100644
--- a/clang/test/Analysis/cfg-rich-constructors.mm
+++ b/clang/test/Analysis/cfg-rich-constructors.mm
@@ -30,8 +30,9 @@ -(D) bar;
 // CXX11-NEXT:     8: [B1.7] (BindTemporary)
 // Double brackets trigger FileCheck variables, escape.
 // CXX11-NEXT:     9: {{\[}}[B1.2] foo:[B1.8]]
-// CXX11-NEXT:    10: ~D() (Temporary object destructor)
+// CXX11-NEXT:    10: (FullExprCleanup collected 1 MTE: [B1.5])
 // CXX11-NEXT:    11: ~D() (Temporary object destructor)
+// CXX11-NEXT:    12: ~D() (Temporary object destructor)
 // CXX17-NEXT:     3: D() (CXXConstructExpr, [B1.4], [B1.5]+0, D)
 // CXX17-NEXT:     4: [B1.3] (BindTemporary)
 // Double brackets trigger FileCheck variables, escape.
@@ -53,8 +54,10 @@ void passArgumentIntoMessage(E *e) {
 // CXX11-NEXT:     6: [B1.5]
 // CXX11-NEXT:     7: [B1.6] (CXXConstructExpr, [B1.8], D)
 // CXX11-NEXT:     8: D d = [e bar];
-// CXX11-NEXT:     9: ~D() (Temporary object destructor)
-// CXX11-NEXT:    10: [B1.8].~D() (Implicit destructor)
+// CXX11-NEXT:     9: (FullExprCleanup collected 1 MTE: [B1.5])
+// CXX11-NEXT:    10: ~D() (Temporary object destructor)
+// CXX11-NEXT:    11: [B1.8].~D() (Implicit destructor)
+// CXX11-NEXT:    12: [B1.8] (Lifetime ends)
 // Double brackets trigger FileCheck variables, escape.
 // CXX17-NEXT:     3: {{\[}}[B1.2] bar] (CXXRecordTypedCall, [B1.5], [B1.4])
 // CXX17-NEXT:     4: [B1.3] (BindTemporary)
diff --git a/clang/test/Analysis/cfg.cpp b/clang/test/Analysis/cfg.cpp
index 478e457d5dcd40..c90206860390b7 100644
--- a/clang/test/Analysis/cfg.cpp
+++ b/clang/test/Analysis/cfg.cpp
@@ -32,6 +32,14 @@
 // WARNINGS-NEXT: (CXXConstructExpr, struct named)
 // ANALYZER-NEXT: (CXXConstructExpr, [B1.13], struct named)
 // CHECK-NEXT:  13: struct named myNamed;
+// CHECK-NEXT:  14: [B1.13] (Lifetime ends)
+// CHECK-NEXT:  15: [B1.11] (Lifetime ends)
+// CHECK-NEXT:  16: [B1.9] (Lifetime ends)
+// CHECK-NEXT:  17: [B1.7] (Lifetime ends)
+// CHECK-NEXT:  18: [B1.5] (Lifetime ends)
+// CHECK-NEXT:  19: [B1.4] (Lifetime ends)
+// CHECK-NEXT:  20: [B1.2] (Lifetime ends)
+// CHECK-NEXT:  21: [B1.1] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B2
 // CHECK-NEXT:   Succs (1): B0
 void checkDeclStmts() {
@@ -101,6 +109,7 @@ class A {
 // CHECK-NEXT:   6: [B1.5] (ImplicitCastExpr, LValueToRValue, A *)
 // CHECK-NEXT:   7: [B1.6]->~A() (Implicit destructor)
 // CHECK-NEXT:   8: delete [B1.6]
+// CHECK-NEXT:   9: [B1.4] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B2
 // CHECK-NEXT:   Succs (1): B0
 // CHECK: [B0 (EXIT)]
@@ -124,6 +133,7 @@ void test_deletedtor() {
 // CHECK-NEXT:   7: [B1.6] (ImplicitCastExpr, LValueToRValue, A *)
 // CHECK-NEXT:   8: [B1.7]->~A() (Implicit destructor)
 // CHECK-NEXT:   9: delete [] [B1.7]
+// CHECK-NEXT:  10: [B1.5] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B2
 // CHECK-NEXT:   Succs (1): B0
 // CHECK: [B0 (EXIT)]
@@ -149,6 +159,7 @@ namespace NoReturnSingleSuccessor {
 // CHECK: 1: 1
 // CHECK-NEXT: 2: return
 // CHECK-NEXT: ~B() (Implicit destructor)
+// CHECK-NEXT: [B4.2] (Lifetime ends)
 // CHECK-NEXT: Preds (1)
 // CHECK-NEXT: Succs (1): B0
   int test1(int *x) {
@@ -161,6 +172,7 @@ namespace NoReturnSingleSuccessor {
 // CHECK: 1: 1
 // CHECK-NEXT: 2: return
 // CHECK-NEXT: destructor
+// CHECK-NEXT: [B4.6] (Lifetime ends)
 // CHECK-NEXT: Preds (1)
 // CHECK-NEXT: Succs (1): B0
   int test2(int *x) {
@@ -178,6 +190,7 @@ namespace NoReturnSingleSuccessor {
 // CHECK-NEXT:    1: x
 // CHECK-NEXT:    2: [B1.1] (ImplicitCastExpr, LValueToRValue, int)
 // CHECK-NEXT:    3: return [B1.2];
+// CHECK-NEXT:    4: [B2.2] (Lifetime ends)
 // CHECK-NEXT:    Preds (5): B3 B4 B5 B6 B2(Unreachable)
 // CHECK-NEXT:    Succs (1): B0
 // CHECK:  [B2]
@@ -244,6 +257,7 @@ int test_enum_with_extension(enum MyEnum value) {
 // CHECK-NEXT:    1: x
 // CHECK-NEXT:    2: [B1.1] (ImplicitCastExpr, LValueToRValue, int)
 // CHECK-NEXT:    3: return [B1.2];
+// CHECK-NEXT:    4: [B2.2] (Lifetime ends)
 // CHECK-NEXT:    Preds (4): B3 B4 B5 B6
 // CHECK-NEXT:    Succs (1): B0
 // CHECK:  [B2]
@@ -313,6 +327,8 @@ int test_enum_with_extension_default(enum MyEnum value) {
 // ANALYZER-NEXT:  6:  (CXXConstructExpr, [B1.7], MyClass)
 // CHECK-NEXT:  7: new ([B1.4]) MyClass([B1.6])
 // CHECK-NEXT:  8: MyClass *obj = new (buffer) MyClass();
+// CHECK-NEXT:  9: [B1.8] (Lifetime ends)
+// CHECK-NEXT: 10: [B1.1] (Lifetime ends)
 // CHECK-NEXT:  Preds (1): B2
 // CHECK-NEXT:  Succs (1): B0
 // CHECK: [B0 (EXIT)]
@@ -346,6 +362,8 @@ void test_placement_new() {
 // ANALYZER-NEXT:  7:  (CXXConstructExpr, [B1.8], MyClass[5])
 // CHECK-NEXT:  8: new ([B1.4]) MyClass {{\[\[}}B1.5]]
 // CHECK-NEXT:  9: MyClass *obj = new (buffer) MyClass [5];
+// CHECK-NEXT: 10: [B1.9] (Lifetime ends)
+// CHECK-NEXT: 11: [B1.1] (Lifetime ends)
 // CHECK-NEXT:  Preds (1): B2
 // CHECK-NEXT:  Succs (1): B0
 // CHECK: [B0 (EXIT)]
@@ -390,6 +408,7 @@ void test_lifetime_extended_temporaries() {
     3;
   }
   // CHECK: LifetimeExtend(4)
+  // CHECK-NEXT: (FullExprCleanup collected 2 MTEs: [B1.38], [B1.45])
   // CHECK-NEXT: ~LifetimeExtend()
   // CHECK-NEXT: ~LifetimeExtend()
   // CHECK-NEXT: : 4
@@ -422,6 +441,7 @@ void test_lifetime_extended_temporaries() {
 // ANALYZER-NEXT:    1:  (CXXConstructExpr, [B1.2], A)
 // CHECK-NEXT:    2: A a;
 // CHECK-NEXT:    3: [B1.2].~A() (Implicit destructor)
+// CHECK-NEXT:    4: [B1.2] (Lifetime ends)
 // CHECK-NEXT:    Preds (1): B2
 // CHECK-NEXT:    Succs (1): B0
 // CHECK:  [B0 (EXIT)]
diff --git a/clang/test/Analysis/cxx20-range-for-cfg.cpp b/clang/test/Analysis/cxx20-range-for-cfg.cpp
index 990c1aa75c1b74..a1e70757fff6cf 100644
--- a/clang/test/Analysis/cxx20-range-for-cfg.cpp
+++ b/clang/test/Analysis/cxx20-range-for-cfg.cpp
@@ -11,7 +11,11 @@ void range_for_init() {
 // CHECK-NEXT:    Succs (1): B5
 
 // CHECK:       [B1]
-// CHECK-NEXT:    1: [B5.2].~A() (Implicit destructor)
+// CHECK-NEXT:    1: [B5.14] (Lifetime ends)
+// CHECK-NEXT:    2: [B5.17] (Lifetime ends)
+// CHECK-NEXT:    3: [B5.9] (Lifetime ends)
+// CHECK-NEXT:    4: [B5.2].~A() (Implicit destructor)
+// CHECK-NEXT:    5: [B5.2] (Lifetime ends)
 // CHECK-NEXT:    Preds (1): B2
 // CHECK-NEXT:    Succs (1): B0
 
diff --git a/clang/test/Analysis/diagnostics/track_subexpressions.cpp b/clang/test/Analysis/diagnostics/track_subexpressions.cpp
index c61738ce7b136d..6ffa411c4101e8 100644
--- a/clang/test/Analysis/diagnostics/track_subexpressions.cpp
+++ b/clang/test/Analysis/diagnostics/track_subexpressions.cpp
@@ -38,7 +38,7 @@ void testArrayIndexTracking() {
 
   for (int i = 0; i < 3; ++i)
     // expected-note at -1 3{{Loop condition is true.  Entering loop body}}
-    // expected-note at -2 {{Loop condition is false. Execution continues on line 43}}
+    // expected-note at -2 {{Loop condition is false. Execution continues on line 39}}
     arr[i] = 0;
   int x = getInt();
   int n = getIndex(x); // expected-note {{Calling 'getIndex'}}
@@ -70,7 +70,7 @@ void testArrayIndexTracking() {
 
   for (int i = 0; i < 3; ++i)
     // expected-note at -1 3{{Loop condition is true.  Entering loop body}}
-    // expected-note at -2 {{Loop condition is false. Execution continues on line 75}}
+    // expected-note at -2 {{Loop condition is false. Execution continues on line 71}}
     arr[1][i] = 0;
   int x = getInt();
   int n = getIndex(x); // expected-note {{Calling 'getIndex'}}
diff --git a/clang/test/Analysis/domtest.cpp b/clang/test/Analysis/domtest.cpp
index 2a2caed130d79f..a347a7fdf98599 100644
--- a/clang/test/Analysis/domtest.cpp
+++ b/clang/test/Analysis/domtest.cpp
@@ -45,27 +45,29 @@ void funcWithBranch() {
 }
 
 //                  1st if  2nd if
-//  [B5 (ENTRY)]  -> [B4] -> [B3] -> [B2] -> [B1] -> [B0 (EXIT)]
-//                    \        \              /         /
-//                     \        ------------->         /
-//                      ------------------------------>
+//  [B6 (ENTRY)]  -> [B5] -> [B4] -> [B3] -> [B2] -> [B1] -> [B0 (EXIT)]
+//                    \        \              /                 /
+//                     \        ------------->                 /
+//                      -------------------------------------->
 
 // CHECK:      Control dependencies (Node#,Dependency#):
-// CHECK-NEXT: (1,4)
-// CHECK-NEXT: (2,3)
-// CHECK-NEXT: (2,4)
+// CHECK-NEXT: (2,5)
 // CHECK-NEXT: (3,4)
+// CHECK-NEXT: (3,5)
+// CHECK-NEXT: (4,5)
 // CHECK-NEXT: Immediate dominance tree (Node#,IDom#):
-// CHECK-NEXT: (0,4)
-// CHECK-NEXT: (1,3)
-// CHECK-NEXT: (2,3)
+// CHECK-NEXT: (0,1)
+// CHECK-NEXT: (1,5)
+// CHECK-NEXT: (2,4)
 // CHECK-NEXT: (3,4)
 // CHECK-NEXT: (4,5)
-// CHECK-NEXT: (5,5)
+// CHECK-NEXT: (5,6)
+// CHECK-NEXT: (6,6)
 // CHECK-NEXT: Immediate post dominance tree (Node#,IDom#):
 // CHECK-NEXT: (0,0)
 // CHECK-NEXT: (1,0)
 // CHECK-NEXT: (2,1)
-// CHECK-NEXT: (3,1)
-// CHECK-NEXT: (4,0)
-// CHECK-NEXT: (5,4)
+// CHECK-NEXT: (3,2)
+// CHECK-NEXT: (4,2)
+// CHECK-NEXT: (5,1)
+// CHECK-NEXT: (6,5)
diff --git a/clang/test/Analysis/end-function-return-stmt.cpp b/clang/test/Analysis/end-function-return-stmt.cpp
index 036ccba3aa9329..433f7bde417f45 100644
--- a/clang/test/Analysis/end-function-return-stmt.cpp
+++ b/clang/test/Analysis/end-function-return-stmt.cpp
@@ -27,7 +27,7 @@ S endsWithReturnStmt() {
 // dtorAfterReturnStmt()
 // CHECK:      EndFunction
 // CHECK-NEXT: ReturnStmt: yes
-// CHECK-NEXT: CFGElement: CFGAutomaticObjDtor
+// CHECK-NEXT: CFGElement: CFGLifetimeEnds
 
 // noReturnStmt()
 // CHECK:      EndFunction
diff --git a/clang/test/Analysis/initializers-cfg-output.cpp b/clang/test/Analysis/initializers-cfg-output.cpp
index 808bc8d51712e8..6ac1352b01a5db 100644
--- a/clang/test/Analysis/initializers-cfg-output.cpp
+++ b/clang/test/Analysis/initializers-cfg-output.cpp
@@ -133,6 +133,7 @@ class TestOrder : public C, public B, public A {
 // WARNINGS-NEXT:    11:  (CXXConstructExpr, A)
 // ANALYZER-NEXT:    11:  (CXXConstructExpr, [B1.12], A)
 // CHECK-NEXT:    12: A a;
+// CHECK-NEXT:    13: [B1.12] (Lifetime ends)
 // CHECK-NEXT:     Preds (2): B2 B3
 // CHECK-NEXT:     Succs (1): B0
 // CHECK:        [B2]
@@ -169,6 +170,7 @@ class TestControlFlow {
 // CHECK-NEXT:     5: [B1.4] (ImplicitCastExpr, LValueToRValue, int)
 // CHECK-NEXT:     6: z([B1.5]) (Member initializer)
 // CHECK-NEXT:     7: int v;
+// CHECK-NEXT:     8: [B1.7] (Lifetime ends)
 // CHECK-NEXT:     Preds (2): B2 B3
 // CHECK-NEXT:     Succs (1): B0
 // CHECK:        [B2]
diff --git a/clang/test/Analysis/loop-widening-notes.cpp b/clang/test/Analysis/loop-widening-notes.cpp
index a3f030dfe98826..9a98b40c11da0d 100644
--- a/clang/test/Analysis/loop-widening-notes.cpp
+++ b/clang/test/Analysis/loop-widening-notes.cpp
@@ -8,7 +8,7 @@ int test_for_bug_25609() {
                 // expected-note at -1 {{Taking true branch}}
     bar();
   for (int i = 0;  // expected-note {{Loop condition is true.  Entering loop body}}                    
-                   // expected-note at -1 {{Loop condition is false. Execution continues on line 16}}
+                   // expected-note at -1 {{Loop condition is false. Execution continues on line 10}}
        ++i,        // expected-note {{Value assigned to 'p_a'}} 
        i < flag_a;
        ++i) {}
@@ -58,7 +58,7 @@ int flag_d;
 int test_for_loop() {
   int num = 10;
   for (int i = 0;    // expected-note {{Loop condition is true.  Entering loop body}} 
-                     // expected-note at -1 {{Loop condition is false. Execution continues on line 67}}
+                     // expected-note at -1 {{Loop condition is false. Execution continues on line 60}}
        new int(10),  // expected-note {{Value assigned to 'num'}}
        i < flag_d;
        ++i) {         
diff --git a/clang/test/Analysis/loopexit-cfg-output.cpp b/clang/test/Analysis/loopexit-cfg-output.cpp
index 81ed2533da6c24..e52d4e30fbbed3 100644
--- a/clang/test/Analysis/loopexit-cfg-output.cpp
+++ b/clang/test/Analysis/loopexit-cfg-output.cpp
@@ -6,7 +6,8 @@
 
 // CHECK:       [B1]
 // CHECK-NEXT:   1: ForStmt (LoopExit)
-// CHECK-NEXT:   2: return;
+// CHECK-NEXT:   2: [B5.2] (Lifetime ends)
+// CHECK-NEXT:   3: return;
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B0
 
@@ -82,6 +83,7 @@ void check_forloop2() {
 
 // CHECK:       [B3]
 // CHECK-NEXT:   1: int i;
+// CHECK-NEXT:   2: [B3.1] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B2
 
@@ -107,6 +109,8 @@ void check_while1() {
 // CHECK-NEXT:   2: 2
 // CHECK-NEXT:   3: int k = 2;
 // CHECK-NEXT:   4: return;
+// CHECK-NEXT:   5: [B1.3] (Lifetime ends)
+// CHECK-NEXT:   6: [B4.1] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B3
 // CHECK-NEXT:   Succs (1): B0
 
@@ -195,6 +199,7 @@ void check_dowhile1() {
 // CHECK-NEXT:   2: j
 // CHECK-NEXT:   3: [B1.2]--
 // CHECK-NEXT:   4: return;
+// CHECK-NEXT:   5: [B5.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B2
 // CHECK-NEXT:   Succs (1): B0
 
@@ -240,6 +245,7 @@ void check_dowhile2() {
 
 // CHECK:       [B1]
 // CHECK-NEXT:   1: WhileStmt (LoopExit)
+// CHECK-NEXT:   2: [B9.3] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B8
 // CHECK-NEXT:   Succs (1): B0
 
@@ -249,6 +255,7 @@ void check_dowhile2() {
 
 // CHECK:       [B3]
 // CHECK-NEXT:   1: ForStmt (LoopExit)
+// CHECK-NEXT:   2: [B7.2] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B6
 // CHECK-NEXT:   Succs (1): B2
 
@@ -310,6 +317,8 @@ void nested_loops1() {
 
 // CHECK:       [B1]
 // CHECK-NEXT:   1: ForStmt (LoopExit)
+// CHECK-NEXT:   2: [B8.5] (Lifetime ends)
+// CHECK-NEXT:   3: [B8.3] (Lifetime ends)
 // CHECK-NEXT:   Preds (1): B7
 // CHECK-NEXT:   Succs (1): B0
 
@@ -381,6 +390,7 @@ void nested_loops2() {
 // CHECK:       [B1]
 // CHECK-NEXT:   1: WhileStmt (LoopExit)
 // CHECK-NEXT:   2: return;
+// CHECK-NEXT:   3: [B6.4] (Lifetime ends)
 // CHECK-NEXT:   Preds (2): B3 B5
 // CHECK-NEXT:   Succs (1): B0
 
@@ -416,8 +426,9 @@ void nested_loops2() {
 
 // CHECK:       [B6]
 // CHECK-NEXT:   1: ForStmt (LoopExit)
-// CHECK-NEXT:   2: 1
-// CHECK-NEXT:   3: int i = 1;
+// CHECK-NEXT:   2: [B11.2] (Lifetime ends)
+// CHECK-NEXT:   3: 1
+// CHECK-NEXT:   4: int i = 1;
 // CHECK-NEXT:   Preds (2): B8 B10
 // CHECK-NEXT:   Succs (1): B5
 
diff --git a/clang/test/Analysis/missing-bind-temporary.cpp b/clang/test/Analysis/missing-bind-temporary.cpp
index 2ce733b0986b0d..b70e22a3f8b8e2 100644
--- a/clang/test/Analysis/missing-bind-temporary.cpp
+++ b/clang/test/Analysis/missing-bind-temporary.cpp
@@ -28,8 +28,10 @@ class B {
 // CHECK-NEXT:    7: [B1.6]
 // CHECK-NEXT:    8: i
 // CHECK-NEXT:    9: [B1.8] = [B1.7] (OperatorCall)
-// CHECK-NEXT:   10: ~B() (Temporary object destructor)
-// CHECK-NEXT:   11: [B1.2].~B() (Implicit destructor)
+// CHECK-NEXT:    10: (FullExprCleanup collected 1 MTE: [B1.6])
+// CHECK-NEXT:   11: ~B() (Temporary object destructor)
+// CHECK-NEXT:   12: [B1.2].~B() (Implicit destructor)
+// CHECK-NEXT:   13: [B1.2] (Lifetime ends)
 void foo(int) {
   B i;
   i = {};
@@ -65,8 +67,10 @@ class B {
 // CHECK-NEXT:    7: [B1.6]
 // CHECK-NEXT:    8: i
 // CHECK-NEXT:    9: [B1.8] = [B1.7] (OperatorCall)
-// CHECK-NEXT:   10: ~B() (Temporary object destructor)
-// CHECK-NEXT:   11: [B1.2].~B() (Implicit destructor)
+// CHECK-NEXT:   10: (FullExprCleanup collected 1 MTE: [B1.6])
+// CHECK-NEXT:   11: ~B() (Temporary object destructor)
+// CHECK-NEXT:   12: [B1.2].~B() (Implicit destructor)
+// CHECK-NEXT:   13: [B1.2] (Lifetime ends)
 template <typename T> void foo(T) {
   B i;
   i = {};
@@ -107,8 +111,10 @@ class B {
 // CHECK-NEXT:    8: [B1.7]
 // CHECK-NEXT:    9: i
 // CHECK-NEXT:   10: [B1.9] = [B1.8] (OperatorCall)
-// CHECK-NEXT:   11: ~B() (Temporary object destructor)
-// CHECK-NEXT:   12: [B1.2].~B() (Implicit destructor)
+// CHECK-NEXT:   11: (FullExprCleanup collected 1 MTE: [B1.7])
+// CHECK-NEXT:   12: ~B() (Temporary object destructor)
+// CHECK-NEXT:   13: [B1.2].~B() (Implicit destructor)
+// CHECK-NEXT:   14: [B1.2] (Lifetime ends)
 template <typename T> void foo(T) {
   B i;
   i = {};
diff --git a/clang/test/Analysis/scopes-cfg-output.cpp b/clang/test/Analysis/scopes-cfg-output.cpp
index ac8ff1179a9945..b94e9ebf58b94a 100644
--- a/clang/test/Analysis/scopes-cfg-output.cpp
+++ b/clang/test/Analysis/scopes-cfg-output.cpp
@@ -40,7 +40,9 @@ extern const bool UV;
 // CHECK-NEXT:   4:  (CXXConstructExpr, [B1.5], A[0])
 // CHECK-NEXT:   5: A b[0];
 // CHECK-NEXT:   6: [B1.3].~A[2]() (Implicit destructor)
-// CHECK-NEXT:   7: CFGScopeEnd(a)
+// CHECK-NEXT:   7: [B1.3] (Lifetime ends)
+// CHECK-NEXT:   8: [B1.5] (Lifetime ends)
+// CHECK-NEXT:   9: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (1): B2
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B0 (EXIT)]
@@ -62,17 +64,19 @@ void test_array() {
 // CHECK-NEXT:   7:  (CXXConstructExpr, [B1.8], A)
 // CHECK-NEXT:   8: A d;
 // CHECK-NEXT:   9: [B1.8].~A() (Implicit destructor)
-// CHECK-NEXT:  10: [B1.6].~A() (Implicit destructor)
-// CHECK-NEXT:  11: CFGScopeEnd(c)
-// CHECK-NEXT:  12:  (CXXConstructExpr, [B1.13], A)
-// CHECK-NEXT:  13: A b;
-// CHECK-NEXT:  14: [B1.13].~A() (Implicit destructor)
-// CHECK-NEXT:  15: [B1.3].~A() (Implicit destructor)
-// CHECK-NEXT:  16: CFGScopeEnd(a)
+// CHECK-NEXT:  10: [B1.8] (Lifetime ends)
+// CHECK-NEXT:  11: [B1.6].~A() (Implicit destructor)
+// CHECK-NEXT:  12: [B1.6] (Lifetime ends)
+// CHECK-NEXT:  13: CFGScopeEnd(c)
+// CHECK-NEXT:  14:  (CXXConstructExpr, [B1.15], A)
+// CHECK-NEXT:  15: A b;
+// CHECK-NEXT:  16: [B1.15].~A() (Implicit destructor)
+// CHECK-NEXT:  17: [B1.15] (Lifetime ends)
+// CHECK-NEXT:  18: [B1.3].~A() (Implicit destructor)
+// CHECK-NEXT:  19: [B1.3] (Lifetime ends)
+// CHECK-NEXT:  20: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (1): B2
 // CHECK-NEXT:   Succs (1): B0
-// CHECK:      [B0 (EXIT)]
-// CHECK-NEXT:   Preds (1): B1
 void test_scope() {
   A a;
   { A c;
@@ -87,16 +91,21 @@ void test_scope() {
 // CHECK-NEXT:   1:  (CXXConstructExpr, [B1.2], A)
 // CHECK-NEXT:   2: A c;
 // CHECK-NEXT:   3: [B1.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B3.5].~A() (Implicit destructor)
-// CHECK-NEXT:   5: [B3.3].~A() (Implicit destructor)
-// CHECK-NEXT:   6: CFGScopeEnd(a)
+// CHECK-NEXT:   4: [B1.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B3.5].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B3.5] (Lifetime ends)
+// CHECK-NEXT:   7: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT:   8: [B3.3] (Lifetime ends)
+// CHECK-NEXT:   9: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (1): B3
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
 // CHECK-NEXT:   1: return;
 // CHECK-NEXT:   2: [B3.5].~A() (Implicit destructor)
-// CHECK-NEXT:   3: [B3.3].~A() (Implicit destructor)
-// CHECK-NEXT:   4: CFGScopeEnd(a)
+// CHECK-NEXT:   3: [B3.5] (Lifetime ends)
+// CHECK-NEXT:   4: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B3.3] (Lifetime ends)
+// CHECK-NEXT:   6: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (1): B3
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B3]
@@ -123,9 +132,11 @@ void test_return() {
 // CHECK-NEXT:   Succs (1): B4
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B4.8].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(b)
-// CHECK-NEXT:   3: [B4.3].~A() (Implicit destructor)
-// CHECK-NEXT:   4: CFGScopeEnd(a)
+// CHECK-NEXT:   2: [B4.8] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(b)
+// CHECK-NEXT:   4: [B4.3].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B4.3] (Lifetime ends)
+// CHECK-NEXT:   6: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (2): B2 B3
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -133,7 +144,8 @@ void test_return() {
 // CHECK-NEXT:   2:  (CXXConstructExpr, [B2.3], A)
 // CHECK-NEXT:   3: A c;
 // CHECK-NEXT:   4: [B2.3].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(c)
+// CHECK-NEXT:   5: [B2.3] (Lifetime ends)
+// CHECK-NEXT:   6: CFGScopeEnd(c)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B3]
@@ -141,7 +153,8 @@ void test_return() {
 // CHECK-NEXT:   2:  (CXXConstructExpr, [B3.3], A)
 // CHECK-NEXT:   3: A c;
 // CHECK-NEXT:   4: [B3.3].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(c)
+// CHECK-NEXT:   5: [B3.3] (Lifetime ends)
+// CHECK-NEXT:   6: CFGScopeEnd(c)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B4]
@@ -175,30 +188,38 @@ void test_if_implicit_scope() {
 // CHECK-NEXT:   Succs (1): B8
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B8.8].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(b)
-// CHECK-NEXT:   3:  (CXXConstructExpr, [B1.4], A)
-// CHECK-NEXT:   4: A e;
-// CHECK-NEXT:   5: [B1.4].~A() (Implicit destructor)
-// CHECK-NEXT:   6: [B8.3].~A() (Implicit destructor)
-// CHECK-NEXT:   7: CFGScopeEnd(a)
+// CHECK-NEXT:   2: [B8.8] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(b)
+// CHECK-NEXT:   4:  (CXXConstructExpr, [B1.5], A)
+// CHECK-NEXT:   5: A e;
+// CHECK-NEXT:   6: [B1.5].~A() (Implicit destructor)
+// CHECK-NEXT:   7: [B1.5] (Lifetime ends)
+// CHECK-NEXT:   8: [B8.3].~A() (Implicit destructor)
+// CHECK-NEXT:   9: [B8.3] (Lifetime ends)
+// CHECK-NEXT:  10: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (2): B2 B5
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
 // CHECK-NEXT:   1:  (CXXConstructExpr, [B2.2], A)
 // CHECK-NEXT:   2: A d;
 // CHECK-NEXT:   3: [B2.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B4.3].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(c)
+// CHECK-NEXT:   4: [B2.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B4.3].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B4.3] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(c)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B3]
 // CHECK-NEXT:   1: return;
 // CHECK-NEXT:   2: [B4.3].~A() (Implicit destructor)
-// CHECK-NEXT:   3: CFGScopeEnd(c)
-// CHECK-NEXT:   4: [B8.8].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(b)
-// CHECK-NEXT:   6: [B8.3].~A() (Implicit destructor)
-// CHECK-NEXT:   7: CFGScopeEnd(a)
+// CHECK-NEXT:   3: [B4.3] (Lifetime ends)
+// CHECK-NEXT:   4: CFGScopeEnd(c)
+// CHECK-NEXT:   5: [B8.8].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B8.8] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(b)
+// CHECK-NEXT:   8: [B8.3].~A() (Implicit destructor)
+// CHECK-NEXT:   9: [B8.3] (Lifetime ends)
+// CHECK-NEXT:  10: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B4]
@@ -214,18 +235,23 @@ void test_if_implicit_scope() {
 // CHECK-NEXT:   1:  (CXXConstructExpr, [B5.2], A)
 // CHECK-NEXT:   2: A d;
 // CHECK-NEXT:   3: [B5.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B7.3].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(c)
+// CHECK-NEXT:   4: [B5.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B7.3].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B7.3] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(c)
 // CHECK-NEXT:   Preds (1): B7
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B6]
 // CHECK-NEXT:   1: return;
 // CHECK-NEXT:   2: [B7.3].~A() (Implicit destructor)
-// CHECK-NEXT:   3: CFGScopeEnd(c)
-// CHECK-NEXT:   4: [B8.8].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(b)
-// CHECK-NEXT:   6: [B8.3].~A() (Implicit destructor)
-// CHECK-NEXT:   7: CFGScopeEnd(a)
+// CHECK-NEXT:   3: [B7.3] (Lifetime ends)
+// CHECK-NEXT:   4: CFGScopeEnd(c)
+// CHECK-NEXT:   5: [B8.8].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B8.8] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(b)
+// CHECK-NEXT:   8: [B8.3].~A() (Implicit destructor)
+// CHECK-NEXT:   9: [B8.3] (Lifetime ends)
+// CHECK-NEXT:  10: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (1): B7
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B7]
@@ -275,9 +301,11 @@ void test_if_jumps() {
 // CHECK-NEXT:   Succs (1): B5
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B4.5].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(b)
-// CHECK-NEXT:   3: [B5.3].~A() (Implicit destructor)
-// CHECK-NEXT:   4: CFGScopeEnd(a)
+// CHECK-NEXT:   2: [B4.5] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(b)
+// CHECK-NEXT:   4: [B5.3].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B5.3] (Lifetime ends)
+// CHECK-NEXT:   6: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -288,9 +316,11 @@ void test_if_jumps() {
 // CHECK-NEXT:   2:  (CXXConstructExpr, [B3.3], A)
 // CHECK-NEXT:   3: A c;
 // CHECK-NEXT:   4: [B3.3].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(c)
-// CHECK-NEXT:   6: [B4.5].~A() (Implicit destructor)
-// CHECK-NEXT:   7: CFGScopeEnd(b)
+// CHECK-NEXT:   5: [B3.3] (Lifetime ends)
+// CHECK-NEXT:   6: CFGScopeEnd(c)
+// CHECK-NEXT:   7: [B4.5].~A() (Implicit destructor)
+// CHECK-NEXT:   8: [B4.5] (Lifetime ends)
+// CHECK-NEXT:   9: CFGScopeEnd(b)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B4]
@@ -326,12 +356,15 @@ void test_while_implicit_scope() {
 // CHECK-NEXT:   Succs (1): B11
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B10.5].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(b)
-// CHECK-NEXT:   3:  (CXXConstructExpr, [B1.4], A)
-// CHECK-NEXT:   4: A e;
-// CHECK-NEXT:   5: [B1.4].~A() (Implicit destructor)
-// CHECK-NEXT:   6: [B11.3].~A() (Implicit destructor)
-// CHECK-NEXT:   7: CFGScopeEnd(a)
+// CHECK-NEXT:   2: [B10.5] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(b)
+// CHECK-NEXT:   4:  (CXXConstructExpr, [B1.5], A)
+// CHECK-NEXT:   5: A e;
+// CHECK-NEXT:   6: [B1.5].~A() (Implicit destructor)
+// CHECK-NEXT:   7: [B1.5] (Lifetime ends)
+// CHECK-NEXT:   8: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT:   9: [B11.3] (Lifetime ends)
+// CHECK-NEXT:  10: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (2): B8 B10
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -341,20 +374,26 @@ void test_while_implicit_scope() {
 // CHECK-NEXT:   1:  (CXXConstructExpr, [B3.2], A)
 // CHECK-NEXT:   2: A d;
 // CHECK-NEXT:   3: [B3.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B9.3].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(c)
-// CHECK-NEXT:   6: [B10.5].~A() (Implicit destructor)
-// CHECK-NEXT:   7: CFGScopeEnd(b)
+// CHECK-NEXT:   4: [B3.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B9.3] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(c)
+// CHECK-NEXT:   8: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT:   9: [B10.5] (Lifetime ends)
+// CHECK-NEXT:  10: CFGScopeEnd(b)
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B4]
 // CHECK-NEXT:   1: return;
 // CHECK-NEXT:   2: [B9.3].~A() (Implicit destructor)
-// CHECK-NEXT:   3: CFGScopeEnd(c)
-// CHECK-NEXT:   4: [B10.5].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(b)
-// CHECK-NEXT:   6: [B11.3].~A() (Implicit destructor)
-// CHECK-NEXT:   7: CFGScopeEnd(a)
+// CHECK-NEXT:   3: [B9.3] (Lifetime ends)
+// CHECK-NEXT:   4: CFGScopeEnd(c)
+// CHECK-NEXT:   5: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B10.5] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(b)
+// CHECK-NEXT:   8: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT:   9: [B11.3] (Lifetime ends)
+// CHECK-NEXT:  10: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B5]
@@ -365,9 +404,11 @@ void test_while_implicit_scope() {
 // CHECK-NEXT:   Succs (2): B4 B3
 // CHECK:      [B6]
 // CHECK-NEXT:   1: [B9.3].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(c)
-// CHECK-NEXT:   3: [B10.5].~A() (Implicit destructor)
-// CHECK-NEXT:   4: CFGScopeEnd(b)
+// CHECK-NEXT:   2: [B9.3] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(c)
+// CHECK-NEXT:   4: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B10.5] (Lifetime ends)
+// CHECK-NEXT:   6: CFGScopeEnd(b)
 // CHECK-NEXT:   T: continue;
 // CHECK-NEXT:   Preds (1): B7
 // CHECK-NEXT:   Succs (1): B2
@@ -379,7 +420,8 @@ void test_while_implicit_scope() {
 // CHECK-NEXT:   Succs (2): B6 B5
 // CHECK:      [B8]
 // CHECK-NEXT:   1: [B9.3].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(c)
+// CHECK-NEXT:   2: [B9.3] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(c)
 // CHECK-NEXT:   T: break;
 // CHECK-NEXT:   Preds (1): B9
 // CHECK-NEXT:   Succs (1): B1
@@ -433,8 +475,10 @@ void test_while_jumps() {
 // CHECK-NEXT:   1:  (CXXConstructExpr, [B1.2], A)
 // CHECK-NEXT:   2: A d;
 // CHECK-NEXT:   3: [B1.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B11.3].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(a)
+// CHECK-NEXT:   4: [B1.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B11.3] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (2): B8 B2
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -447,16 +491,20 @@ void test_while_jumps() {
 // CHECK-NEXT:   1:  (CXXConstructExpr, [B3.2], A)
 // CHECK-NEXT:   2: A c;
 // CHECK-NEXT:   3: [B3.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B9.3].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(b)
+// CHECK-NEXT:   4: [B3.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B9.3] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(b)
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B4]
 // CHECK-NEXT:   1: return;
 // CHECK-NEXT:   2: [B9.3].~A() (Implicit destructor)
-// CHECK-NEXT:   3: CFGScopeEnd(b)
-// CHECK-NEXT:   4: [B11.3].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(a)
+// CHECK-NEXT:   3: [B9.3] (Lifetime ends)
+// CHECK-NEXT:   4: CFGScopeEnd(b)
+// CHECK-NEXT:   5: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B11.3] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B5]
@@ -467,7 +515,8 @@ void test_while_jumps() {
 // CHECK-NEXT:   Succs (2): B4 B3
 // CHECK:      [B6]
 // CHECK-NEXT:   1: [B9.3].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(b)
+// CHECK-NEXT:   2: [B9.3] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(b)
 // CHECK-NEXT:   T: continue;
 // CHECK-NEXT:   Preds (1): B7
 // CHECK-NEXT:   Succs (1): B2
@@ -479,7 +528,8 @@ void test_while_jumps() {
 // CHECK-NEXT:   Succs (2): B6 B5
 // CHECK:      [B8]
 // CHECK-NEXT:   1: [B9.3].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(b)
+// CHECK-NEXT:   2: [B9.3] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(b)
 // CHECK-NEXT:   T: break;
 // CHECK-NEXT:   Preds (1): B9
 // CHECK-NEXT:   Succs (1): B1
@@ -519,16 +569,19 @@ void test_do_jumps() {
 // CHECK-NEXT:   Succs (1): B5
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B4.5].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(b)
-// CHECK-NEXT:   3: [B5.3].~A() (Implicit destructor)
-// CHECK-NEXT:   4: CFGScopeEnd(a)
+// CHECK-NEXT:   2: [B4.5] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(b)
+// CHECK-NEXT:   4: [B5.3].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B5.3] (Lifetime ends)
+// CHECK-NEXT:   6: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
 // CHECK-NEXT:   1: b
 // CHECK-NEXT:   2: [B2.1].p
 // CHECK-NEXT:   3: [B4.5].~A() (Implicit destructor)
-// CHECK-NEXT:   4: CFGScopeEnd(b)
+// CHECK-NEXT:   4: [B4.5] (Lifetime ends)
+// CHECK-NEXT:   5: CFGScopeEnd(b)
 // CHECK-NEXT:   Preds (1): B3
 // CHECK-NEXT:   Succs (1): B4
 // CHECK:      [B3]
@@ -536,7 +589,8 @@ void test_do_jumps() {
 // CHECK-NEXT:   2:  (CXXConstructExpr, [B3.3], A)
 // CHECK-NEXT:   3: A c;
 // CHECK-NEXT:   4: [B3.3].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(c)
+// CHECK-NEXT:   5: [B3.3] (Lifetime ends)
+// CHECK-NEXT:   6: CFGScopeEnd(c)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B4]
@@ -571,39 +625,50 @@ void test_for_implicit_scope() {
 // CHECK-NEXT:   Succs (1): B11
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B10.5].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(c)
-// CHECK-NEXT:   3: [B11.6].~A() (Implicit destructor)
-// CHECK-NEXT:   4: CFGScopeEnd(b)
-// CHECK-NEXT:   5:  (CXXConstructExpr, [B1.6], A)
-// CHECK-NEXT:   6: A f;
-// CHECK-NEXT:   7: [B1.6].~A() (Implicit destructor)
-// CHECK-NEXT:   8: [B11.3].~A() (Implicit destructor)
-// CHECK-NEXT:   9: CFGScopeEnd(a)
+// CHECK-NEXT:   2: [B10.5] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(c)
+// CHECK-NEXT:   4: [B11.6].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B11.6] (Lifetime ends)
+// CHECK-NEXT:   6: CFGScopeEnd(b)
+// CHECK-NEXT:   7:  (CXXConstructExpr, [B1.8], A)
+// CHECK-NEXT:   8: A f;
+// CHECK-NEXT:   9: [B1.8].~A() (Implicit destructor)
+// CHECK-NEXT:  10: [B1.8] (Lifetime ends)
+// CHECK-NEXT:  11: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT:  12: [B11.3] (Lifetime ends)
+// CHECK-NEXT:  13: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (2): B8 B10
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
 // CHECK-NEXT:   1: [B10.5].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(c)
+// CHECK-NEXT:   2: [B10.5] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(c)
 // CHECK-NEXT:   Preds (2): B3 B6
 // CHECK-NEXT:   Succs (1): B10
 // CHECK:      [B3]
 // CHECK-NEXT:   1:  (CXXConstructExpr, [B3.2], A)
 // CHECK-NEXT:   2: A e;
 // CHECK-NEXT:   3: [B3.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B9.3].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(d)
+// CHECK-NEXT:   4: [B3.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B9.3] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(d)
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B4]
 // CHECK-NEXT:   1: return;
 // CHECK-NEXT:   2: [B9.3].~A() (Implicit destructor)
-// CHECK-NEXT:   3: CFGScopeEnd(d)
-// CHECK-NEXT:   4: [B10.5].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(c)
-// CHECK-NEXT:   6: [B11.6].~A() (Implicit destructor)
-// CHECK-NEXT:   7: CFGScopeEnd(b)
-// CHECK-NEXT:   8: [B11.3].~A() (Implicit destructor)
-// CHECK-NEXT:   9: CFGScopeEnd(a)
+// CHECK-NEXT:   3: [B9.3] (Lifetime ends)
+// CHECK-NEXT:   4: CFGScopeEnd(d)
+// CHECK-NEXT:   5: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B10.5] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(c)
+// CHECK-NEXT:   8: [B11.6].~A() (Implicit destructor)
+// CHECK-NEXT:   9: [B11.6] (Lifetime ends)
+// CHECK-NEXT:  10: CFGScopeEnd(b)
+// CHECK-NEXT:  11: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT:  12: [B11.3] (Lifetime ends)
+// CHECK-NEXT:  13: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B5]
@@ -614,7 +679,8 @@ void test_for_implicit_scope() {
 // CHECK-NEXT:   Succs (2): B4 B3
 // CHECK:      [B6]
 // CHECK-NEXT:   1: [B9.3].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(d)
+// CHECK-NEXT:   2: [B9.3] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(d)
 // CHECK-NEXT:   T: continue;
 // CHECK-NEXT:   Preds (1): B7
 // CHECK-NEXT:   Succs (1): B2
@@ -626,7 +692,8 @@ void test_for_implicit_scope() {
 // CHECK-NEXT:   Succs (2): B6 B5
 // CHECK:      [B8]
 // CHECK-NEXT:   1: [B9.3].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(d)
+// CHECK-NEXT:   2: [B9.3] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(d)
 // CHECK-NEXT:   T: break;
 // CHECK-NEXT:   Preds (1): B9
 // CHECK-NEXT:   Succs (1): B1
@@ -664,7 +731,7 @@ void test_for_implicit_scope() {
 // CHECK-NEXT:   Preds (1): B12
 // CHECK-NEXT:   Succs (1): B10
 // CHECK:      [B0 (EXIT)]
-// CHECK-NEXT:   Preds (2): B1 B4
+// CHECK-NEXT:   Preds (2): B1 B4      
 void test_for_jumps() {
   A a;
   for (A b; A c = b; ) {
@@ -681,15 +748,18 @@ void test_for_jumps() {
 // CHECK-NEXT:   Succs (1): B8
 // CHECK:      [B1]
 // CHECK-NEXT:   1: [B7.5].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(b)
-// CHECK-NEXT:   3: [B8.3].~A() (Implicit destructor)
-// CHECK-NEXT:   4: CFGScopeEnd(a)
+// CHECK-NEXT:   2: [B7.5] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(b)
+// CHECK-NEXT:   4: [B8.3].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B8.3] (Lifetime ends)
+// CHECK-NEXT:   6: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (1): B7
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
 // CHECK-NEXT:   1: [B5.4] ? [B3.3] : [B4.2]
 // CHECK-NEXT:   2: [B7.5].~A() (Implicit destructor)
-// CHECK-NEXT:   3: CFGScopeEnd(b)
+// CHECK-NEXT:   3: [B7.5] (Lifetime ends)
+// CHECK-NEXT:   4: CFGScopeEnd(b)
 // CHECK-NEXT:   Preds (2): B3 B4
 // CHECK-NEXT:   Succs (1): B7
 // CHECK:      [B3]
@@ -749,23 +819,30 @@ void test_for_inc_conditional() {
 // CHECK-NEXT:   1:  (CXXConstructExpr, [B1.2], A)
 // CHECK-NEXT:   2: A c;
 // CHECK-NEXT:   3: [B1.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B6.4].~A() (Implicit destructor)
-// CHECK-NEXT:   5: [B6.2].~A() (Implicit destructor)
-// CHECK-NEXT:   6: [B7.3].~A() (Implicit destructor)
-// CHECK-NEXT:   7: CFGScopeEnd(a)
+// CHECK-NEXT:   4: [B1.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B6.4].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B6.4] (Lifetime ends)
+// CHECK-NEXT:   7: [B6.2].~A() (Implicit destructor)
+// CHECK-NEXT:   8: [B6.2] (Lifetime ends)
+// CHECK-NEXT:   9: [B7.3].~A() (Implicit destructor)
+// CHECK-NEXT:  10: [B7.3] (Lifetime ends)
+// CHECK-NEXT:  11: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (2): B2 B3
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
 // CHECK-NEXT:   1:  (CXXConstructExpr, [B2.2], A)
 // CHECK-NEXT:   2: A nb;
 // CHECK-NEXT:   3: [B2.2].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B6.7].~A() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(na)
+// CHECK-NEXT:   4: [B2.2] (Lifetime ends)
+// CHECK-NEXT:   5: [B6.7].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B6.7] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(na)
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B3]
 // CHECK-NEXT:   1: [B6.7].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(na)
+// CHECK-NEXT:   2: [B6.7] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(na)
 // CHECK-NEXT:   T: goto l1;
 // CHECK-NEXT:   Preds (1): B4
 // CHECK-NEXT:   Succs (1): B1
@@ -800,9 +877,12 @@ void test_for_inc_conditional() {
 // CHECK-NEXT:   Succs (1): B6
 // CHECK:      [B8]
 // CHECK-NEXT:   1: [B6.7].~A() (Implicit destructor)
-// CHECK-NEXT:   2: CFGScopeEnd(na)
-// CHECK-NEXT:   3: [B6.4].~A() (Implicit destructor)
-// CHECK-NEXT:   4: [B6.2].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B6.7] (Lifetime ends)
+// CHECK-NEXT:   3: CFGScopeEnd(na)
+// CHECK-NEXT:   4: [B6.4].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B6.4] (Lifetime ends)
+// CHECK-NEXT:   6: [B6.2].~A() (Implicit destructor)
+// CHECK-NEXT:   7: [B6.2] (Lifetime ends)
 // CHECK-NEXT:   T: goto l0;
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B6
@@ -825,10 +905,12 @@ void test_goto() {
 // CHECK:      [B7 (ENTRY)]
 // CHECK-NEXT:   Succs (1): B6
 // CHECK:      [B1]
-// CHECK-NEXT:   1: CFGScopeEnd(i)
-// CHECK-NEXT:   2: CFGScopeBegin(unused2)
-// CHECK-NEXT:   3: int unused2;
-// CHECK-NEXT:   4: CFGScopeEnd(unused2)
+// CHECK-NEXT:   1: [B6.3] (Lifetime ends)
+// CHECK-NEXT:   2: CFGScopeEnd(i)
+// CHECK-NEXT:   3: CFGScopeBegin(unused2)
+// CHECK-NEXT:   4: int unused2;
+// CHECK-NEXT:   5: [B1.4] (Lifetime ends)
+// CHECK-NEXT:   6: CFGScopeEnd(unused2)
 // CHECK-NEXT:   Preds (2): B4 B5
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -837,12 +919,14 @@ void test_goto() {
 // CHECK-NEXT:   Preds (1): B3
 // CHECK-NEXT:   Succs (1): B5
 // CHECK:      [B3]
-// CHECK-NEXT:   1: CFGScopeEnd(unused1)
+// CHECK-NEXT:   1: [B4.2] (Lifetime ends)
+// CHECK-NEXT:   2: CFGScopeEnd(unused1)
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B4]
 // CHECK-NEXT:   1: CFGScopeBegin(unused1)
 // CHECK-NEXT:   2: int unused1;
-// CHECK-NEXT:   3: CFGScopeEnd(unused1)
+// CHECK-NEXT:   3: [B4.2] (Lifetime ends)
+// CHECK-NEXT:   4: CFGScopeEnd(unused1)
 // CHECK-NEXT:   T: break;
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B1
@@ -877,11 +961,15 @@ void test_for_compound_and_break() {
 // CHECK:      [B6 (ENTRY)]
 // CHECK-NEXT:   Succs (1): B5
 // CHECK:      [B1]
-// CHECK-NEXT:   1: CFGScopeEnd(__end1)
-// CHECK-NEXT:   2: CFGScopeEnd(__begin1)
-// CHECK-NEXT:   3: CFGScopeEnd(__range1)
-// CHECK-NEXT:   4: [B5.3].~A[10]() (Implicit destructor)
-// CHECK-NEXT:   5: CFGScopeEnd(a)
+// CHECK-NEXT:   1: [B5.11] (Lifetime ends)
+// CHECK-NEXT:   2: CFGScopeEnd(__end1)
+// CHECK-NEXT:   3: [B5.14] (Lifetime ends)
+// CHECK-NEXT:   4: CFGScopeEnd(__begin1)
+// CHECK-NEXT:   5: [B5.5] (Lifetime ends)
+// CHECK-NEXT:   6: CFGScopeEnd(__range1)
+// CHECK-NEXT:   7: [B5.3].~A[10]() (Implicit destructor)
+// CHECK-NEXT:   8: [B5.3] (Lifetime ends)
+// CHECK-NEXT:   9: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (1): B2
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -911,7 +999,8 @@ void test_for_compound_and_break() {
 // CHECK-NEXT:   9: [B4.8] (ImplicitCastExpr, NoOp, const A)
 // CHECK-NEXT:  10: i
 // CHECK-NEXT:  11: [B4.10] = [B4.9] (OperatorCall)
-// CHECK-NEXT:  12: CFGScopeEnd(i)
+// CHECK-NEXT:  12: [B4.5] (Lifetime ends)
+// CHECK-NEXT:  13: CFGScopeEnd(i)
 // CHECK-NEXT:   Preds (1): B2
 // CHECK-NEXT:   Succs (1): B3
 // CHECK:      [B5]
@@ -942,10 +1031,13 @@ void test_range_for(A &b) {
 // CHECK:      [B8 (ENTRY)]
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B1]
-// CHECK-NEXT:   1: CFGScopeEnd(i)
-// CHECK-NEXT:   2: 1
-// CHECK-NEXT:   3: int k = 1;
-// CHECK-NEXT:   4: CFGScopeEnd(c)
+// CHECK-NEXT:   1: [B2.8] (Lifetime ends)
+// CHECK-NEXT:   2: CFGScopeEnd(i)
+// CHECK-NEXT:   3: 1
+// CHECK-NEXT:   4: int k = 1;
+// CHECK-NEXT:   5: [B1.4] (Lifetime ends)
+// CHECK-NEXT:   6: [B2.3] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(c)
 // CHECK-NEXT:   Preds (3): B3 B5 B6
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -969,7 +1061,8 @@ void test_range_for(A &b) {
 // CHECK-NEXT:   3: int a = 0;
 // CHECK-NEXT:   4: i
 // CHECK-NEXT:   5: ++[B3.4]
-// CHECK-NEXT:   6: CFGScopeEnd(a)
+// CHECK-NEXT:   6: [B3.3] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (2): B4 B2
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B4]
@@ -1029,10 +1122,13 @@ void test_switch_with_compound_with_default() {
 // CHECK:      [B6 (ENTRY)]
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B1]
-// CHECK-NEXT:   1: CFGScopeEnd(i)
-// CHECK-NEXT:   2: 3
-// CHECK-NEXT:   3: int k = 3;
-// CHECK-NEXT:   4: CFGScopeEnd(c)
+// CHECK-NEXT:   1: [B2.8] (Lifetime ends)
+// CHECK-NEXT:   2: CFGScopeEnd(i)
+// CHECK-NEXT:   3: 3
+// CHECK-NEXT:   4: int k = 3;
+// CHECK-NEXT:   5: [B1.4] (Lifetime ends)
+// CHECK-NEXT:   6: [B2.3] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(c)
 // CHECK-NEXT:   Preds (3): B3 B4 B2
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -1092,10 +1188,13 @@ void test_switch_with_compound_without_default() {
 // CHECK:      [B5 (ENTRY)]
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B1]
-// CHECK-NEXT:   1: CFGScopeEnd(i)
-// CHECK-NEXT:   2: 1
-// CHECK-NEXT:   3: int k = 1;
-// CHECK-NEXT:   4: CFGScopeEnd(s)
+// CHECK-NEXT:   1: [B2.8] (Lifetime ends)
+// CHECK-NEXT:   2: CFGScopeEnd(i)
+// CHECK-NEXT:   3: 1
+// CHECK-NEXT:   4: int k = 1;
+// CHECK-NEXT:   5: [B1.4] (Lifetime ends)
+// CHECK-NEXT:   6: [B2.3] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(s)
 // CHECK-NEXT:   Preds (1): B3
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -1119,7 +1218,8 @@ void test_switch_with_compound_without_default() {
 // CHECK-NEXT:   3: int a = 0;
 // CHECK-NEXT:   4: i
 // CHECK-NEXT:   5: ++[B3.4]
-// CHECK-NEXT:   6: CFGScopeEnd(a)
+// CHECK-NEXT:   6: [B3.3] (Lifetime ends)
+// CHECK-NEXT:   7: CFGScopeEnd(a)
 // CHECK-NEXT:   Preds (2): B4 B2
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B4]
@@ -1142,7 +1242,10 @@ void test_without_compound() {
 // CHECK:      [B12 (ENTRY)]
 // CHECK-NEXT:   Succs (1): B11
 // CHECK:      [B1]
-// CHECK-NEXT:   1: CFGScopeEnd(i)
+// CHECK-NEXT:   1: [B11.4] (Lifetime ends)
+// CHECK-NEXT:   2: [B11.3] (Lifetime ends)
+// CHECK-NEXT:   3: [B11.2] (Lifetime ends)
+// CHECK-NEXT:   4: CFGScopeEnd(i)
 // CHECK-NEXT:   Preds (2): B4 B10
 // CHECK-NEXT:   Succs (1): B0
 // CHECK:      [B2]
@@ -1151,13 +1254,15 @@ void test_without_compound() {
 // CHECK-NEXT:   Preds (2): B3 B7
 // CHECK-NEXT:   Succs (1): B10
 // CHECK:      [B3]
-// CHECK-NEXT:   1: CFGScopeEnd(z)
+// CHECK-NEXT:   1: [B4.3] (Lifetime ends)
+// CHECK-NEXT:   2: CFGScopeEnd(z)
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B4]
 // CHECK-NEXT:   1: CFGScopeBegin(z)
 // CHECK-NEXT:   2: 5
 // CHECK-NEXT:   3: int z = 5;
-// CHECK-NEXT:   4: CFGScopeEnd(z)
+// CHECK-NEXT:   4: [B4.3] (Lifetime ends)
+// CHECK-NEXT:   5: CFGScopeEnd(z)
 // CHECK-NEXT:   T: break;
 // CHECK-NEXT:   Preds (2): B6 B8
 // CHECK-NEXT:   Succs (1): B1
@@ -1243,21 +1348,26 @@ void test_for_switch_in_for() {
 // CHECK-NEXT:    Succs (1): B3
 // CHECK:       [B1]
 // CHECK-NEXT:   label:
-// CHECK-NEXT:    1: CFGScopeEnd(n2t)
-// CHECK-NEXT:    2: CFGScopeEnd(n1t)
-// CHECK-NEXT:    3: [B3.3].~A() (Implicit destructor)
-// CHECK-NEXT:    4: CFGScopeEnd(a)
+// CHECK-NEXT:    1: [B2.10] (Lifetime ends)
+// CHECK-NEXT:    2: CFGScopeEnd(n2t)
+// CHECK-NEXT:    3: [B2.8] (Lifetime ends)
+// CHECK-NEXT:    4: CFGScopeEnd(n1t)
+// CHECK-NEXT:    5: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT:    6: [B3.3] (Lifetime ends)
+// CHECK-NEXT:    7: CFGScopeEnd(a)
 // CHECK-NEXT:    Preds (2): B2 B3
 // CHECK-NEXT:    Succs (1): B0
 // CHECK:       [B2]
 // CHECK-NEXT:    1: [B3.9].~A() (Implicit destructor)
-// CHECK-NEXT:    2: CFGScopeEnd(n2s)
-// CHECK-NEXT:    3: [B3.6].~A() (Implicit destructor)
-// CHECK-NEXT:    4: CFGScopeEnd(n1s)
-// CHECK-NEXT:    5: CFGScopeBegin(n1t)
-// CHECK-NEXT:    6: int n1t;
-// CHECK-NEXT:    7: CFGScopeBegin(n2t)
-// CHECK-NEXT:    8: int n2t;
+// CHECK-NEXT:    2: [B3.9] (Lifetime ends)
+// CHECK-NEXT:    3: CFGScopeEnd(n2s)
+// CHECK-NEXT:    4: [B3.6].~A() (Implicit destructor)
+// CHECK-NEXT:    5: [B3.6] (Lifetime ends)
+// CHECK-NEXT:    6: CFGScopeEnd(n1s)
+// CHECK-NEXT:    7: CFGScopeBegin(n1t)
+// CHECK-NEXT:    8: int n1t;
+// CHECK-NEXT:    9: CFGScopeBegin(n2t)
+// CHECK-NEXT:   10: int n2t;
 // CHECK-NEXT:    Succs (1): B1
 // CHECK:       [B3]
 // CHECK-NEXT:    1: CFGScopeBegin(a)
@@ -1270,11 +1380,13 @@ void test_for_switch_in_for() {
 // CHECK-NEXT:    8:  (CXXConstructExpr, [B3.9], A)
 // CHECK-NEXT:    9: A n2s;
 // CHECK-NEXT:   10: [B3.9].~A() (Implicit destructor)
-// CHECK-NEXT:   11: CFGScopeEnd(n2s)
-// CHECK-NEXT:   12: [B3.6].~A() (Implicit destructor)
-// CHECK-NEXT:   13: CFGScopeEnd(n1s)
-// CHECK-NEXT:   14: CFGScopeBegin(n1t)
-// CHECK-NEXT:   15: CFGScopeBegin(n2t)
+// CHECK-NEXT:   11: [B3.9] (Lifetime ends)
+// CHECK-NEXT:   12: CFGScopeEnd(n2s)
+// CHECK-NEXT:   13: [B3.6].~A() (Implicit destructor)
+// CHECK-NEXT:   14: [B3.6] (Lifetime ends)
+// CHECK-NEXT:   15: CFGScopeEnd(n1s)
+// CHECK-NEXT:   16: CFGScopeBegin(n1t)
+// CHECK-NEXT:   17: CFGScopeBegin(n2t)
 // CHECK-NEXT:    T: goto label;
 // CHECK-NEXT:    Preds (1): B4
 // CHECK-NEXT:    Succs (1): B1
@@ -1301,23 +1413,28 @@ void test_goto_multiple_scopes() {
 // CHECK:       [B5 (ENTRY)]
 // CHECK-NEXT:    Succs (1): B3
 // CHECK:       [B1]
-// CHECK-NEXT:    1: [B2.8].~A() (Implicit destructor)
-// CHECK-NEXT:    2: CFGScopeEnd(n2s)
-// CHECK-NEXT:    3: [B2.5].~A() (Implicit destructor)
-// CHECK-NEXT:    4: CFGScopeEnd(n1s)
-// CHECK-NEXT:    5: [B3.3].~A() (Implicit destructor)
-// CHECK-NEXT:    6: CFGScopeEnd(a)
+// CHECK-NEXT:    1: [B2.10].~A() (Implicit destructor)
+// CHECK-NEXT:    2: [B2.10] (Lifetime ends)
+// CHECK-NEXT:    3: CFGScopeEnd(n2s)
+// CHECK-NEXT:    4: [B2.7].~A() (Implicit destructor)
+// CHECK-NEXT:    5: [B2.7] (Lifetime ends)
+// CHECK-NEXT:    6: CFGScopeEnd(n1s)
+// CHECK-NEXT:    7: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT:    8: [B3.3] (Lifetime ends)
+// CHECK-NEXT:    9: CFGScopeEnd(a)
 // CHECK-NEXT:    Succs (1): B0
 // CHECK:       [B2]
 // CHECK-NEXT:   label:
-// CHECK-NEXT:    1: CFGScopeEnd(n2t)
-// CHECK-NEXT:    2: CFGScopeEnd(n1t)
-// CHECK-NEXT:    3: CFGScopeBegin(n1s)
-// CHECK-NEXT:    4:  (CXXConstructExpr, [B2.5], A)
-// CHECK-NEXT:    5: A n1s;
-// CHECK-NEXT:    6: CFGScopeBegin(n2s)
-// CHECK-NEXT:    7:  (CXXConstructExpr, [B2.8], A)
-// CHECK-NEXT:    8: A n2s;
+// CHECK-NEXT:    1: [B3.7] (Lifetime ends)
+// CHECK-NEXT:    2: CFGScopeEnd(n2t)
+// CHECK-NEXT:    3: [B3.5] (Lifetime ends)
+// CHECK-NEXT:    4: CFGScopeEnd(n1t)
+// CHECK-NEXT:    5: CFGScopeBegin(n1s)
+// CHECK-NEXT:    6:  (CXXConstructExpr, [B2.7], A)
+// CHECK-NEXT:    7: A n1s;
+// CHECK-NEXT:    8: CFGScopeBegin(n2s)
+// CHECK-NEXT:    9:  (CXXConstructExpr, [B2.10], A)
+// CHECK-NEXT:   10: A n2s;
 // CHECK-NEXT:    Preds (2): B3 B4
 // CHECK-NEXT:    Succs (1): B4
 // CHECK:       [B3]
@@ -1331,12 +1448,14 @@ void test_goto_multiple_scopes() {
 // CHECK-NEXT:    Preds (1): B5
 // CHECK-NEXT:    Succs (1): B2
 // CHECK:       [B4]
-// CHECK-NEXT:    1: [B2.8].~A() (Implicit destructor)
-// CHECK-NEXT:    2: CFGScopeEnd(n2s)
-// CHECK-NEXT:    3: [B2.5].~A() (Implicit destructor)
-// CHECK-NEXT:    4: CFGScopeEnd(n1s)
-// CHECK-NEXT:    5: CFGScopeBegin(n1t)
-// CHECK-NEXT:    6: CFGScopeBegin(n2t)
+// CHECK-NEXT:    1: [B2.10].~A() (Implicit destructor)
+// CHECK-NEXT:    2: [B2.10] (Lifetime ends)
+// CHECK-NEXT:    3: CFGScopeEnd(n2s)
+// CHECK-NEXT:    4: [B2.7].~A() (Implicit destructor)
+// CHECK-NEXT:    5: [B2.7] (Lifetime ends)
+// CHECK-NEXT:    6: CFGScopeEnd(n1s)
+// CHECK-NEXT:    7: CFGScopeBegin(n1t)
+// CHECK-NEXT:    8: CFGScopeBegin(n2t)
 // CHECK-NEXT:    T: goto label;
 // CHECK-NEXT:    Preds (1): B2
 // CHECK-NEXT:    Succs (1): B2
@@ -1364,8 +1483,10 @@ void test_backpatched_goto_multiple_scopes() {
 // CHECK-NEXT:    Succs (1): B7
 // CHECK:       [B1]
 // CHECK-NEXT:   label:
-// CHECK-NEXT:    1: CFGScopeEnd(n2t)
-// CHECK-NEXT:    2: CFGScopeEnd(n1t)
+// CHECK-NEXT:    1: [B3.2] (Lifetime ends)
+// CHECK-NEXT:    2: CFGScopeEnd(n2t)
+// CHECK-NEXT:    3: [B5.2] (Lifetime ends)
+// CHECK-NEXT:    4: CFGScopeEnd(n1t)
 // CHECK-NEXT:    Preds (4): B2 B3 B4 B6
 // CHECK-NEXT:    Succs (1): B0
 // CHECK:       [B2]
@@ -1424,7 +1545,8 @@ void test_multiple_goto_entering_scopes() {
 // CHECK-NEXT:   1: CFGScopeBegin(i)
 // CHECK-NEXT:   2: int i __attribute__((cleanup(cleanup_int)));
 // CHECK-NEXT:   3: CleanupFunction (cleanup_int)
-// CHECK-NEXT:   4: CFGScopeEnd(i)
+// CHECK-NEXT:   4: [B1.2] (Lifetime ends)
+// CHECK-NEXT:   5: CFGScopeEnd(i)
 void cleanup_int(int *i);
 void test_cleanup_functions() {
   int i __attribute__((cleanup(cleanup_int)));
@@ -1436,13 +1558,15 @@ void test_cleanup_functions() {
 // CHECK-NEXT:    3: [B1.2] = [B1.1]
 // CHECK-NEXT:    4: return;
 // CHECK-NEXT:    5: CleanupFunction (cleanup_int)
-// CHECK-NEXT:    6: CFGScopeEnd(i)
+// CHECK-NEXT:    6: [B3.2] (Lifetime ends)
+// CHECK-NEXT:    7: CFGScopeEnd(i)
 // CHECK-NEXT:    Preds (1): B3
 // CHECK-NEXT:    Succs (1): B0
 // CHECK:      [B2]
 // CHECK-NEXT:    1: return;
 // CHECK-NEXT:    2: CleanupFunction (cleanup_int)
-// CHECK-NEXT:    3: CFGScopeEnd(i)
+// CHECK-NEXT:    3: [B3.2] (Lifetime ends)
+// CHECK-NEXT:    4: CFGScopeEnd(i)
 // CHECK-NEXT:    Preds (1): B3
 // CHECK-NEXT:    Succs (1): B0
 // CHECK:      [B3]
@@ -1472,7 +1596,8 @@ void test_cleanup_functions2(int m) {
 // CHECK-NEXT:    3: F f __attribute__((cleanup(cleanup_F)));
 // CHECK-NEXT:    4: CleanupFunction (cleanup_F)
 // CHECK-NEXT:    5: [B1.3].~F() (Implicit destructor)
-// CHECK-NEXT:    6: CFGScopeEnd(f)
+// CHECK-NEXT:    6: [B1.3] (Lifetime ends)
+// CHECK-NEXT:    7: CFGScopeEnd(f)
 // CHECK-NEXT:    Preds (1): B2
 // CHECK-NEXT:    Succs (1): B0
 class F {
diff --git a/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp b/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp
index b496d261e92f4a..e63f643c8e7fdc 100644
--- a/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp
+++ b/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp
@@ -240,9 +240,10 @@ const C &bar3(bool coin) {
 // CHECK:     3: [B1.2] (ImplicitCastExpr, NoOp, const A)
 // CHECK:     4: [B1.3]
 // WARNINGS:     5: [B1.4] (CXXConstructExpr, A)
-// ANALYZER:     5: [B1.4] (CXXConstructExpr, [B1.7], A)
-// CHECK:     6: ~A() (Temporary object destructor)
-// CHECK:     7: return [B1.5];
+// ANALYZER:     5: [B1.4] (CXXConstructExpr, [B1.8], A)
+// CHECK:     6: (FullExprCleanup collected 1 MTE: [B1.3])
+// CHECK:     7: ~A() (Temporary object destructor)
+// CHECK:     8: return [B1.5];
 // CHECK:     Preds (1): B2
 // CHECK:     Succs (1): B0
 // CHECK:   [B0 (EXIT)]
@@ -300,9 +301,10 @@ const C &bar3(bool coin) {
 // CHECK:     3: [B1.2] (ImplicitCastExpr, NoOp, const A)
 // CHECK:     4: [B1.3]
 // WARNINGS:     5: [B1.4] (CXXConstructExpr, A)
-// ANALYZER:     5: [B1.4] (CXXConstructExpr, [B1.7], A)
-// CHECK:     6: ~A() (Temporary object destructor)
-// CHECK:     7: return [B1.5];
+// ANALYZER:     5: [B1.4] (CXXConstructExpr, [B1.8], A)
+// CHECK:     6: (FullExprCleanup collected 1 MTE: [B1.3])
+// CHECK:     7: ~A() (Temporary object destructor)
+// CHECK:     8: return [B1.5];
 // CHECK:     Preds (1): B2
 // CHECK:     Succs (1): B0
 // CHECK:   [B0 (EXIT)]
@@ -328,31 +330,35 @@ const C &bar3(bool coin) {
 // CHECK:    14: int([B1.13]) (CXXFunctionalCastExpr, NoOp, int)
 // CHECK:    15: [B1.7] + [B1.14]
 // CHECK:    16: int a = int(A()) + int(B());
-// CHECK:    17: ~B() (Temporary object destructor)
-// CHECK:    18: ~A() (Temporary object destructor)
-// CHECK:    19: foo
-// CHECK:    20: [B1.19] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int))
-// WARNINGS:    21: A() (CXXConstructExpr, A)
-// ANALYZER:    21: A() (CXXConstructExpr, [B1.22], [B1.23], A)
-// CHECK:    22: [B1.21] (BindTemporary)
-// CHECK:    23: [B1.22]
-// CHECK:    24: [B1.23].operator int
-// CHECK:    25: [B1.23]
-// CHECK:    26: [B1.25] (ImplicitCastExpr, UserDefinedConversion, int)
-// CHECK:    27: int([B1.26]) (CXXFunctionalCastExpr, NoOp, int)
-// WARNINGS:    28: B() (CXXConstructExpr, B)
-// ANALYZER:    28: B() (CXXConstructExpr, [B1.29], [B1.30], B)
-// CHECK:    29: [B1.28] (BindTemporary)
-// CHECK:    30: [B1.29]
-// CHECK:    31: [B1.30].operator int
-// CHECK:    32: [B1.30]
-// CHECK:    33: [B1.32] (ImplicitCastExpr, UserDefinedConversion, int)
-// CHECK:    34: int([B1.33]) (CXXFunctionalCastExpr, NoOp, int)
-// CHECK:    35: [B1.27] + [B1.34]
-// CHECK:    36: [B1.20]([B1.35])
-// CHECK:    37: ~B() (Temporary object destructor)
-// CHECK:    38: ~A() (Temporary object destructor)
-// CHECK:    39: int b;
+// CHECK:    17: (FullExprCleanup collected 2 MTEs: [B1.2], [B1.9])
+// CHECK:    18: ~B() (Temporary object destructor)
+// CHECK:    19: ~A() (Temporary object destructor)
+// CHECK:    20: foo
+// CHECK:    21: [B1.20] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int))
+// WARNINGS:    22: A() (CXXConstructExpr, A)
+// ANALYZER:    22: A() (CXXConstructExpr, [B1.23], [B1.24], A)
+// CHECK:    23: [B1.22] (BindTemporary)
+// CHECK:    24: [B1.23]
+// CHECK:    25: [B1.24].operator int
+// CHECK:    26: [B1.24]
+// CHECK:    27: [B1.26] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK:    28: int([B1.27]) (CXXFunctionalCastExpr, NoOp, int)
+// WARNINGS:    29: B() (CXXConstructExpr, B)
+// ANALYZER:    29: B() (CXXConstructExpr, [B1.30], [B1.31], B)
+// CHECK:    30: [B1.29] (BindTemporary)
+// CHECK:    31: [B1.30]
+// CHECK:    32: [B1.31].operator int
+// CHECK:    33: [B1.31]
+// CHECK:    34: [B1.33] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK:    35: int([B1.34]) (CXXFunctionalCastExpr, NoOp, int)
+// CHECK:    36: [B1.28] + [B1.35]
+// CHECK:    37: [B1.21]([B1.36])
+// CHECK:    38: (FullExprCleanup collected 2 MTEs: [B1.23], [B1.30])
+// CHECK:    39: ~B() (Temporary object destructor)
+// CHECK:    40: ~A() (Temporary object destructor)
+// CHECK:    41: int b;
+// CHECK:    42: [B1.41] (Lifetime ends)
+// CHECK:    43: [B1.16] (Lifetime ends)
 // CHECK:     Preds (1): B2
 // CHECK:     Succs (1): B0
 // CHECK:   [B0 (EXIT)]
@@ -362,6 +368,8 @@ const C &bar3(bool coin) {
 // CHECK:   [B1]
 // CHECK:     1: ~A() (Temporary object destructor)
 // CHECK:     2: int b;
+// CHECK:     3: [B1.2] (Lifetime ends)
+// CHECK:     4: [B7.2] (Lifetime ends)
 // CHECK:     Preds (2): B2 B3
 // CHECK:     Succs (1): B0
 // CHECK:   [B2]
@@ -371,6 +379,7 @@ const C &bar3(bool coin) {
 // CHECK:   [B3]
 // CHECK:     1: [B5.9] && [B4.6]
 // CHECK:     2: [B5.3]([B3.1])
+// CHECK:     3: (FullExprCleanup collected 2 MTEs: [B5.5], [B4.2])
 // CHECK:     T: (Temp Dtor) [B4.2]
 // CHECK:     Preds (2): B4 B5
 // CHECK:     Succs (2): B2 B1
@@ -405,6 +414,7 @@ const C &bar3(bool coin) {
 // CHECK:   [B7]
 // CHECK:     1: [B9.6] && [B8.6]
 // CHECK:     2: bool a = A() && B();
+// CHECK:     3: (FullExprCleanup collected 2 MTEs: [B9.2], [B8.2])
 // CHECK:     T: (Temp Dtor) [B8.2]
 // CHECK:     Preds (2): B8 B9
 // CHECK:     Succs (2): B6 B5
@@ -436,6 +446,8 @@ const C &bar3(bool coin) {
 // CHECK:   [B1]
 // CHECK:     1: ~A() (Temporary object destructor)
 // CHECK:     2: int b;
+// CHECK:     3: [B1.2] (Lifetime ends)
+// CHECK:     4: [B7.2] (Lifetime ends)
 // CHECK:     Preds (2): B2 B3
 // CHECK:     Succs (1): B0
 // CHECK:   [B2]
@@ -445,6 +457,7 @@ const C &bar3(bool coin) {
 // CHECK:   [B3]
 // CHECK:     1: [B5.9] || [B4.6]
 // CHECK:     2: [B5.3]([B3.1])
+// CHECK:     3: (FullExprCleanup collected 2 MTEs: [B5.5], [B4.2])
 // CHECK:     T: (Temp Dtor) [B4.2]
 // CHECK:     Preds (2): B4 B5
 // CHECK:     Succs (2): B2 B1
@@ -479,6 +492,7 @@ const C &bar3(bool coin) {
 // CHECK:   [B7]
 // CHECK:     1: [B9.6] || [B8.6]
 // CHECK:     2: bool a = A() || B();
+// CHECK:     3: (FullExprCleanup collected 2 MTEs: [B9.2], [B8.2])
 // CHECK:     T: (Temp Dtor) [B8.2]
 // CHECK:     Preds (2): B8 B9
 // CHECK:     Succs (2): B6 B5
@@ -510,6 +524,8 @@ const C &bar3(bool coin) {
 // CHECK:   [B1]
 // CHECK:     1: int b;
 // CHECK:     2: [B7.5].~A() (Implicit destructor)
+// CHECK:     3: [B7.5] (Lifetime ends)
+// CHECK:     4: [B1.1] (Lifetime ends)
 // CHECK:     Preds (2): B2 B3
 // CHECK:     Succs (1): B0
 // CHECK:   [B2]
@@ -535,7 +551,8 @@ const C &bar3(bool coin) {
 // CHECK:     5: [B4.4].operator bool
 // CHECK:     6: [B4.4]
 // CHECK:     7: [B4.6] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK:     8: ~B() (Temporary object destructor)
+// CHECK:     8: (FullExprCleanup collected 1 MTE: [B4.3])
+// CHECK:     9: ~B() (Temporary object destructor)
 // CHECK:     T: if [B4.7]
 // CHECK:     Preds (2): B5 B6
 // CHECK:     Succs (2): B3 B2
@@ -558,6 +575,7 @@ const C &bar3(bool coin) {
 // WARNINGS:     4: [B7.3] (CXXConstructExpr, A)
 // ANALYZER:     4: [B7.3] (CXXConstructExpr, [B7.5], A)
 // CHECK:     5: A a = B() ? A() : A(B());
+// CHECK:     6: (FullExprCleanup collected 6 MTEs: [B7.2], [B10.2], [B8.3], [B9.13], [B9.8], [B9.2])
 // CHECK:     T: (Temp Dtor) [B9.2]
 // CHECK:     Preds (2): B8 B9
 // CHECK:     Succs (2): B6 B5
@@ -671,7 +689,8 @@ const C &bar3(bool coin) {
 // CHECK:     4: [B3.3].operator bool
 // CHECK:     5: [B3.3]
 // CHECK:     6: [B3.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK:     7: ~C() (Temporary object destructor)
+// CHECK:     7: (FullExprCleanup collected 1 MTE: [B3.2])
+// CHECK:     8: ~C() (Temporary object destructor)
 // CHECK:     T: if [B3.6]
 // CHECK:     Preds (1): B4
 // CHECK:     Succs (2): B2 B1
@@ -681,17 +700,20 @@ const C &bar3(bool coin) {
 // CHECK:     Succs (1): B4
 // CHECK:   [B1]
 // CHECK:     1: [B4.6].~C() (Implicit destructor)
+// CHECK:     2: [B4.6] (Lifetime ends)
 // CHECK:     Succs (1): B0
 // CHECK:   [B2]
 // CHECK:     1: 0
 // CHECK:     2: return [B2.1];
 // CHECK:     3: [B4.6].~C() (Implicit destructor)
+// CHECK:     4: [B4.6] (Lifetime ends)
 // CHECK:     Preds (1): B4
 // CHECK:     Succs (1): B0
 // CHECK:   [B3]
 // CHECK:     1: 1
 // CHECK:     2: return [B3.1];
 // CHECK:     3: [B4.6].~C() (Implicit destructor)
+// CHECK:     4: [B4.6] (Lifetime ends)
 // CHECK:     Preds (1): B4
 // CHECK:     Succs (1): B0
 // CHECK:   [B4]
@@ -703,12 +725,13 @@ const C &bar3(bool coin) {
 // WARNINGS:     5: [B4.4] (CXXConstructExpr, C)
 // ANALYZER:     5: [B4.4] (CXXConstructExpr, [B4.6], C)
 // CHECK:     6: C c = C();
-// CHECK:     7: ~C() (Temporary object destructor)
-// CHECK:     8: c
-// CHECK:     9: [B4.8].operator bool
-// CHECK:    10: [B4.8]
-// CHECK:    11: [B4.10] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK:     T: if [B4.11]
+// CHECK:     7: (FullExprCleanup collected 1 MTE: [B4.3])
+// CHECK:     8: ~C() (Temporary object destructor)
+// CHECK:     9: c
+// CHECK:    10: [B4.9].operator bool
+// CHECK:    11: [B4.9]
+// CHECK:    12: [B4.11] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK:     T: if [B4.12]
 // CHECK:     Preds (1): B5
 // CHECK:     Succs (2): B3 B2
 // CHECK:   [B0 (EXIT)]
@@ -732,51 +755,62 @@ const C &bar3(bool coin) {
 // CHECK:     3: [B3.2].operator bool
 // CHECK:     4: [B3.2]
 // CHECK:     5: [B3.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK:     6: (FullExprCleanup collected 1 MTE: [B3.1])
 // CHECK:     T: if [B3.5]
 // CHECK:     Preds (1): B4
 // CHECK:     Succs (2): B2 B1
 // CHECK:   [B0 (EXIT)]
 // CHECK:     Preds (2): B1 B2
-// CHECK:   [B4 (ENTRY)]
-// CHECK:     Succs (1): B3
+// CHECK:   [B5 (ENTRY)]
+// CHECK:     Succs (1): B4
 // CHECK:   [B1]
-// CHECK:     1: 0
-// CHECK:     2: return [B1.1];
-// CHECK:     Preds (1): B3
+// CXX98:     1: [B4.5] (Lifetime ends)
+// CXX11:     1: [B4.4] (Lifetime ends)
 // CHECK:     Succs (1): B0
 // CHECK:   [B2]
-// CHECK:     1: 1
+// CHECK:     1: 0
 // CHECK:     2: return [B2.1];
-// CHECK:     Preds (1): B3
+// CXX98:     3: [B4.5] (Lifetime ends)
+// CXX11:     3: [B4.4] (Lifetime ends)
+// CHECK:     Preds (1): B4
 // CHECK:     Succs (1): B0
 // CHECK:   [B3]
+// CHECK:     1: 1
+// CHECK:     2: return [B3.1];
+// CXX98:     3: [B4.5] (Lifetime ends)
+// CXX11:     3: [B4.4] (Lifetime ends)
+// CHECK:     Preds (1): B4
+// CHECK:     Succs (1): B0
+// CHECK:   [B4]
 // CXX98-WARNINGS:     1: D() (CXXConstructExpr, D)
-// CXX98-ANALYZER:     1: D() (CXXConstructExpr, [B3.3], [B3.4], D)
-// CXX98:     2: [B3.1] (ImplicitCastExpr, NoOp, const D)
-// CXX98:     3: [B3.2]
-// CXX98-WARNINGS:     4: [B3.3] (CXXConstructExpr, D)
-// CXX98-ANALYZER:     4: [B3.3] (CXXConstructExpr, [B3.5], D)
+// CXX98-ANALYZER:     1: D() (CXXConstructExpr, [B4.3], [B4.4], D)
+// CXX98:     2: [B4.1] (ImplicitCastExpr, NoOp, const D)
+// CXX98:     3: [B4.2]
+// CXX98-WARNINGS:     4: [B4.3] (CXXConstructExpr, D)
+// CXX98-ANALYZER:     4: [B4.3] (CXXConstructExpr, [B4.5], D)
 // CXX98:     5: D d = D();
-// CXX98:     6: d
-// CXX98:     7: [B3.6].operator bool
-// CXX98:     8: [B3.6]
-// CXX98:     9: [B3.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CXX98:     T: if [B3.9]
+// CXX98:     6: (FullExprCleanup collected 1 MTE: [B4.2])
+// CXX98:     7: d
+// CXX98:     8: [B4.7].operator bool
+// CXX98:     9: [B4.7]
+// CXX98:    10: [B4.9] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX98:     T: if [B4.10]
 // CXX11-WARNINGS:     1: D() (CXXConstructExpr, D)
-// CXX11-ANALYZER:     1: D() (CXXConstructExpr, [B3.2], [B3.3], D)
-// CXX11:     2: [B3.1]
-// CXX11-WARNINGS:     3: [B3.2] (CXXConstructExpr, D)
-// CXX11-ANALYZER:     3: [B3.2] (CXXConstructExpr, [B3.4], D)
+// CXX11-ANALYZER:     1: D() (CXXConstructExpr, [B4.2], [B4.3], D)
+// CXX11:     2: [B4.1]
+// CXX11-WARNINGS:     3: [B4.2] (CXXConstructExpr, D)
+// CXX11-ANALYZER:     3: [B4.2] (CXXConstructExpr, [B4.4], D)
 // CXX11:     4: D d = D();
-// CXX11:     5: d
-// CXX11:     6: [B3.5].operator bool
-// CXX11:     7: [B3.5]
-// CXX11:     8: [B3.7] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CXX11:     T: if [B3.8]
-// CHECK:     Preds (1): B4
-// CHECK:     Succs (2): B2 B1
+// CXX11:     5: (FullExprCleanup collected 1 MTE: [B4.1])
+// CXX11:     6: d
+// CXX11:     7: [B4.6].operator bool
+// CXX11:     8: [B4.6]
+// CXX11:     9: [B4.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CXX11:     T: if [B4.9]
+// CHECK:     Preds (1): B5
+// CHECK:     Succs (2): B3 B2
 // CHECK:   [B0 (EXIT)]
-// CHECK:     Preds (2): B1 B2
+// CHECK:     Preds (3): B1 B2 B3
 // CHECK:   [B14 (ENTRY)]
 // CHECK:     Succs (1): B13
 // CHECK:   [B1]
@@ -1103,9 +1137,12 @@ const C &bar3(bool coin) {
 // WARNINGS:     5: [B1.4] (CXXConstructExpr, A)
 // ANALYZER:     5: [B1.4] (CXXConstructExpr, [B1.6], A)
 // CHECK:     6: A a = A();
-// CHECK:     7: ~A() (Temporary object destructor)
-// CHECK:     8: int b;
-// CHECK:     9: [B1.6].~A() (Implicit destructor)
+// CHECK:     7: (FullExprCleanup collected 1 MTE: [B1.3])
+// CHECK:     8: ~A() (Temporary object destructor)
+// CHECK:     9: int b;
+// CHECK:    10: [B1.6].~A() (Implicit destructor)
+// CHECK:    11: [B1.6] (Lifetime ends)
+// CHECK:    12: [B1.9] (Lifetime ends)
 // CHECK:     Preds (1): B2
 // CHECK:     Succs (1): B0
 // CHECK:   [B0 (EXIT)]
@@ -1127,9 +1164,12 @@ const C &bar3(bool coin) {
 // CHECK:    10: [B1.9] (ImplicitCastExpr, NoOp, const A)
 // CHECK:    11: [B1.10]
 // CHECK:    12: [B1.7]([B1.11])
-// CHECK:    13: ~A() (Temporary object destructor)
-// CHECK:    14: int b;
-// CHECK:    15: [B1.5].~A() (Implicit destructor)
+// CHECK:    13: (FullExprCleanup collected 1 MTE: [B1.10])
+// CHECK:    14: ~A() (Temporary object destructor)
+// CHECK:    15: int b;
+// CHECK:    16: [B1.5].~A() (Implicit destructor)
+// CHECK:    17: [B1.5] (Lifetime ends)
+// CHECK:    18: [B1.15] (Lifetime ends)
 // CHECK:     Preds (1): B2
 // CHECK:     Succs (1): B0
 // CHECK:   [B0 (EXIT)]
@@ -1147,9 +1187,12 @@ const C &bar3(bool coin) {
 // WARNINGS:     7: [B1.6] (CXXConstructExpr, A)
 // ANALYZER:     7: [B1.6] (CXXConstructExpr, [B1.8], A)
 // CHECK:     8: A a = A::make();
-// CHECK:     9: ~A() (Temporary object destructor)
-// CHECK:    10: int b;
-// CHECK:    11: [B1.8].~A() (Implicit destructor)
+// CHECK:     9: (FullExprCleanup collected 1 MTE: [B1.5])
+// CHECK:    10: ~A() (Temporary object destructor)
+// CHECK:    11: int b;
+// CHECK:    12: [B1.8].~A() (Implicit destructor)
+// CHECK:    13: [B1.8] (Lifetime ends)
+// CHECK:    14: [B1.11] (Lifetime ends)
 // CHECK:     Preds (1): B2
 // CHECK:     Succs (1): B0
 // CHECK:   [B0 (EXIT)]
@@ -1175,9 +1218,12 @@ const C &bar3(bool coin) {
 // CHECK:    14: [B1.13] (ImplicitCastExpr, NoOp, const A)
 // CHECK:    15: [B1.14]
 // CHECK:    16: [B1.9]([B1.15])
-// CHECK:    17: ~A() (Temporary object destructor)
-// CHECK:    18: int b;
-// CHECK:    19: [B1.7].~A() (Implicit destructor)
+// CHECK:    17: (FullExprCleanup collected 1 MTE: [B1.14])
+// CHECK:    18: ~A() (Temporary object destructor)
+// CHECK:    19: int b;
+// CHECK:    20: [B1.7].~A() (Implicit destructor)
+// CHECK:    21: [B1.7] (Lifetime ends)
+// CHECK:    22: [B1.19] (Lifetime ends)
 // CHECK:     Preds (1): B2
 // CHECK:     Succs (1): B0
 // CHECK:   [B0 (EXIT)]
@@ -1195,8 +1241,11 @@ const C &bar3(bool coin) {
 // CHECK:     7: [B1.6] (ImplicitCastExpr, UserDefinedConversion, int)
 // CHECK:     8: a
 // CHECK:     9: [B1.8] = [B1.7]
-// CHECK:    10: ~A() (Temporary object destructor)
-// CHECK:    11: int b;
+// CHECK:    10: (FullExprCleanup collected 1 MTE: [B1.3])
+// CHECK:    11: ~A() (Temporary object destructor)
+// CHECK:    12: int b;
+// CHECK:    13: [B1.12] (Lifetime ends)
+// CHECK:    14: [B1.1] (Lifetime ends)
 // CHECK:     Preds (1): B2
 // CHECK:     Succs (1): B0
 // CHECK:   [B0 (EXIT)]
@@ -1222,9 +1271,10 @@ const C &bar3(bool coin) {
 // CHECK:    14: int([B1.13]) (CXXFunctionalCastExpr, NoOp, int)
 // CHECK:    15: [B1.7] + [B1.14]
 // CHECK:    16: a([B1.15]) (Member initializer)
-// CHECK:    17: ~B() (Temporary object destructor)
-// CHECK:    18: ~A() (Temporary object destructor)
-// CHECK:    19: b(/*implicit*/(int)0) (Member initializer)
+// CHECK:    17: (FullExprCleanup collected 2 MTEs: [B1.2], [B1.9])
+// CHECK:    18: ~B() (Temporary object destructor)
+// CHECK:    19: ~A() (Temporary object destructor)
+// CHECK:    20: b(/*implicit*/(int)0) (Member initializer)
 // CHECK:     Preds (1): B2
 // CHECK:     Succs (1): B0
 // CHECK:   [B0 (EXIT)]
@@ -1233,6 +1283,8 @@ const C &bar3(bool coin) {
 // CHECK:     Succs (1): B2
 // CHECK:   [B1]
 // CHECK:     1: int b;
+// CHECK:     2: [B1.1] (Lifetime ends)
+// CHECK:     3: [B2.1] (Lifetime ends)
 // CHECK:     Preds (1): B2(Unreachable)
 // CHECK:     Succs (1): B0
 // CHECK:   [B2 (NORETURN)]
@@ -1243,7 +1295,8 @@ const C &bar3(bool coin) {
 // CHECK:     3: [B2.2] (BindTemporary)
 // CHECK:     [[MEMBER:[45]]]: [B2.{{[34]}}].f
 // CHECK:     {{[56]}}: [B2.[[MEMBER]]]()
-// CHECK:     {{[67]}}: ~NoReturn() (Temporary object destructor)
+// CHECK:     {{[78]}}: (FullExprCleanup collected 1 MTE: [B2.3])
+// CHECK:     {{[89]}}: ~NoReturn() (Temporary object destructor)
 // CHECK:     Preds (1): B3
 // CHECK:     Succs (1): B0
 // CHECK:   [B0 (EXIT)]
diff --git a/clang/test/Analysis/unreachable-code-path.c b/clang/test/Analysis/unreachable-code-path.c
index cc526adece69a0..67b74cd6749cf7 100644
--- a/clang/test/Analysis/unreachable-code-path.c
+++ b/clang/test/Analysis/unreachable-code-path.c
@@ -108,7 +108,7 @@ void test9(unsigned a) {
 void test10(void) {
   goto c;
   d:
-  goto e; // expected-warning {{never executed}}
+  goto e;
   c: ;
   int i;
   return;
@@ -120,7 +120,7 @@ void test10(void) {
   i = 2;  // no-warning
   goto f;
   e:
-  goto d;
+  goto d; // expected-warning {{never executed}}
   f: ;
 }
 

>From e97ad19975ef2d4c91645d4528835807d5278bef Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Thu, 1 Oct 2026 21:57:33 +0200
Subject: [PATCH 2/3] [analyzer] Turn on CFGLifetimeEnds elements by default

---
 .../diagnostics/track_subexpressions.cpp      |  4 +-
 .../Analysis/end-function-return-stmt.cpp     |  3 +-
 clang/test/Analysis/lifetime-end-order.cpp    | 68 +++++++++++++++++++
 clang/test/Analysis/loop-widening-notes.cpp   |  4 +-
 4 files changed, 74 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/Analysis/lifetime-end-order.cpp

diff --git a/clang/test/Analysis/diagnostics/track_subexpressions.cpp b/clang/test/Analysis/diagnostics/track_subexpressions.cpp
index 6ffa411c4101e8..c61738ce7b136d 100644
--- a/clang/test/Analysis/diagnostics/track_subexpressions.cpp
+++ b/clang/test/Analysis/diagnostics/track_subexpressions.cpp
@@ -38,7 +38,7 @@ void testArrayIndexTracking() {
 
   for (int i = 0; i < 3; ++i)
     // expected-note at -1 3{{Loop condition is true.  Entering loop body}}
-    // expected-note at -2 {{Loop condition is false. Execution continues on line 39}}
+    // expected-note at -2 {{Loop condition is false. Execution continues on line 43}}
     arr[i] = 0;
   int x = getInt();
   int n = getIndex(x); // expected-note {{Calling 'getIndex'}}
@@ -70,7 +70,7 @@ void testArrayIndexTracking() {
 
   for (int i = 0; i < 3; ++i)
     // expected-note at -1 3{{Loop condition is true.  Entering loop body}}
-    // expected-note at -2 {{Loop condition is false. Execution continues on line 71}}
+    // expected-note at -2 {{Loop condition is false. Execution continues on line 75}}
     arr[1][i] = 0;
   int x = getInt();
   int n = getIndex(x); // expected-note {{Calling 'getIndex'}}
diff --git a/clang/test/Analysis/end-function-return-stmt.cpp b/clang/test/Analysis/end-function-return-stmt.cpp
index 433f7bde417f45..13afd05957a932 100644
--- a/clang/test/Analysis/end-function-return-stmt.cpp
+++ b/clang/test/Analysis/end-function-return-stmt.cpp
@@ -1,7 +1,8 @@
 //RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder -analyzer-config debug.AnalysisOrder:EndFunction=true %s 2>&1 | FileCheck %s
 
 // At the end of a function, we can only obtain a ReturnStmt if the last
-// CFGElement in the CFGBlock is either a CFGStmt or a CFGAutomaticObjDtor.
+// CFGElement in the CFGBlock is either a CFGStmt, CFGAutomaticObjDtor
+// or a scope marker like CFGLifetimeEnds.
 
 void noReturnStmt() {}
 
diff --git a/clang/test/Analysis/lifetime-end-order.cpp b/clang/test/Analysis/lifetime-end-order.cpp
new file mode 100644
index 00000000000000..2790544ce8c17e
--- /dev/null
+++ b/clang/test/Analysis/lifetime-end-order.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder %s 2>&1 \
+// RUN:   -analyzer-config debug.AnalysisOrder:LifetimeEnd=true,debug.AnalysisOrder:PreCall=true,debug.AnalysisOrder:PostCall=true,debug.AnalysisOrder:EndFunction=true \
+// RUN:   | FileCheck %s
+
+// Tests when does the check::LifetimeEnd callback fires compared to
+// other callbacks.
+
+// Local integers end their lifetime at the closing brace of the
+// inner block.
+void testLocalInts() {
+  {
+    int i = 4, y = 5;
+  }
+}
+
+// The loop variable's lifetime ends once at the point of the
+// loop's exit.
+void testLoopVar() {
+  for(int i = 0; i < 3; ++i) {}
+}
+
+struct S {
+  ~S();
+};
+
+// The lifetime of the object ends after its destructor returns.
+void testDestrAndLifetimeEnd() {
+  S s;
+}
+
+// Local integers lifetime ends at the return statement.
+int testEarlyReturn() {
+  {
+    int i = 5;
+    return i;
+  }
+}
+
+// testEarlyReturn()
+// CHECK:      LifetimeEnd
+// CHECK-NEXT: EndFunction
+// CHECK-NEXT: ReturnStmt: yes
+// CHECK-NEXT: CFGElement: CFGLifetimeEnds
+
+// testDestrAndLifetimeEnd()
+// CHECK:      PreCall (S::S) [CXXConstructorCall]
+// CHECK-NEXT: EndFunction
+// CHECK-NEXT: ReturnStmt: no
+// CHECK-NEXT: PostCall (S::S) [CXXConstructorCall]
+// CHECK-NEXT: PreCall (S::~S) [CXXDestructorCall]
+// CHECK-NEXT: PostCall (S::~S) [CXXDestructorCall]
+// CHECK-NEXT: LifetimeEnd
+// CHECK-NEXT: EndFunction
+// CHECK-NEXT: ReturnStmt: no
+
+// testLoopVar()
+// CHECK:      LifetimeEnd
+// CHECK-NEXT: EndFunction
+// CHECK-NEXT: ReturnStmt: no
+
+// testLocalInts()
+// CHECK:      LifetimeEnd
+// CHECK-NEXT: LifetimeEnd
+// CHECK-NEXT: EndFunction
+// CHECK-NEXT: ReturnStmt: no
+
+// There should not be further LifetimeEnd elementes.
+// CHECK-NOT: LifetimeEnd
diff --git a/clang/test/Analysis/loop-widening-notes.cpp b/clang/test/Analysis/loop-widening-notes.cpp
index 9a98b40c11da0d..a3f030dfe98826 100644
--- a/clang/test/Analysis/loop-widening-notes.cpp
+++ b/clang/test/Analysis/loop-widening-notes.cpp
@@ -8,7 +8,7 @@ int test_for_bug_25609() {
                 // expected-note at -1 {{Taking true branch}}
     bar();
   for (int i = 0;  // expected-note {{Loop condition is true.  Entering loop body}}                    
-                   // expected-note at -1 {{Loop condition is false. Execution continues on line 10}}
+                   // expected-note at -1 {{Loop condition is false. Execution continues on line 16}}
        ++i,        // expected-note {{Value assigned to 'p_a'}} 
        i < flag_a;
        ++i) {}
@@ -58,7 +58,7 @@ int flag_d;
 int test_for_loop() {
   int num = 10;
   for (int i = 0;    // expected-note {{Loop condition is true.  Entering loop body}} 
-                     // expected-note at -1 {{Loop condition is false. Execution continues on line 60}}
+                     // expected-note at -1 {{Loop condition is false. Execution continues on line 67}}
        new int(10),  // expected-note {{Value assigned to 'num'}}
        i < flag_d;
        ++i) {         

>From 633dd6f82e54b4963c68e4c124201ff6a69bdc6c Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Tue, 13 Oct 2026 14:54:33 +0200
Subject: [PATCH 3/3] Update the test file.

---
 clang/test/Analysis/lifetime-end-order.cpp | 72 ++++++++++++----------
 1 file changed, 39 insertions(+), 33 deletions(-)

diff --git a/clang/test/Analysis/lifetime-end-order.cpp b/clang/test/Analysis/lifetime-end-order.cpp
index 2790544ce8c17e..6b53dca1e40b6e 100644
--- a/clang/test/Analysis/lifetime-end-order.cpp
+++ b/clang/test/Analysis/lifetime-end-order.cpp
@@ -1,6 +1,15 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder %s 2>&1 \
-// RUN:   -analyzer-config debug.AnalysisOrder:LifetimeEnd=true,debug.AnalysisOrder:PreCall=true,debug.AnalysisOrder:PostCall=true,debug.AnalysisOrder:EndFunction=true \
-// RUN:   | FileCheck %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder -analyze-function="testLocalInts()"\
+// RUN:   -analyzer-config debug.AnalysisOrder:LifetimeEnd=true,debug.AnalysisOrder:PreCall=true,debug.AnalysisOrder:PostCall=true,debug.AnalysisOrder:EndFunction=true\
+// RUN:   %s 2>&1 | FileCheck %s --check-prefix=CHECK-LOCAL-INTS
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder -analyze-function="testLoopVar()"\
+// RUN:   -analyzer-config debug.AnalysisOrder:LifetimeEnd=true,debug.AnalysisOrder:PreCall=true,debug.AnalysisOrder:PostCall=true,debug.AnalysisOrder:EndFunction=true\
+// RUN:   %s 2>&1 | FileCheck %s --check-prefix=CHECK-LOOP-VAR
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder -analyze-function="testDestrAndLifetimeEnd()"\
+// RUN:   -analyzer-config debug.AnalysisOrder:LifetimeEnd=true,debug.AnalysisOrder:PreCall=true,debug.AnalysisOrder:PostCall=true,debug.AnalysisOrder:EndFunction=true\
+// RUN:   %s 2>&1 | FileCheck %s --check-prefix=CHECK-DESTR
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder -analyze-function="testEarlyReturn()"\
+// RUN:   -analyzer-config debug.AnalysisOrder:LifetimeEnd=true,debug.AnalysisOrder:PreCall=true,debug.AnalysisOrder:PostCall=true,debug.AnalysisOrder:EndFunction=true\
+// RUN:   %s 2>&1 | FileCheck %s --check-prefix=CHECK-EARLY-RETURN
 
 // Tests when does the check::LifetimeEnd callback fires compared to
 // other callbacks.
@@ -13,12 +22,23 @@ void testLocalInts() {
   }
 }
 
+// CHECK-LOCAL-INTS:      LifetimeEnd
+// CHECK-LOCAL-INTS-NEXT: LifetimeEnd
+// CHECK-LOCAL-INTS-NEXT: EndFunction
+// CHECK-LOCAL-INTS-NEXT: ReturnStmt: no
+// CHECK-LOCAL-INTS-NOT:  LifetimeEnd
+
 // The loop variable's lifetime ends once at the point of the
 // loop's exit.
 void testLoopVar() {
   for(int i = 0; i < 3; ++i) {}
 }
 
+// CHECK-LOOP-VAR:      LifetimeEnd
+// CHECK-LOOP-VAR-NEXT: EndFunction
+// CHECK-LOOP-VAR-NEXT: ReturnStmt: no
+// CHECK-LOOP-VAR-NOT:  LifetimeEnd
+
 struct S {
   ~S();
 };
@@ -28,6 +48,17 @@ void testDestrAndLifetimeEnd() {
   S s;
 }
 
+// CHECK-DESTR:      PreCall (S::S) [CXXConstructorCall]
+// CHECK-DESTR-NEXT: EndFunction
+// CHECK-DESTR-NEXT: ReturnStmt: no
+// CHECK-DESTR-NEXT: PostCall (S::S) [CXXConstructorCall]
+// CHECK-DESTR-NEXT: PreCall (S::~S) [CXXDestructorCall]
+// CHECK-DESTR-NEXT: PostCall (S::~S) [CXXDestructorCall]
+// CHECK-DESTR-NEXT: LifetimeEnd
+// CHECK-DESTR-NEXT: EndFunction
+// CHECK-DESTR-NEXT: ReturnStmt: no
+// CHECK-DESTR-NOT:  LifetimeEnd
+
 // Local integers lifetime ends at the return statement.
 int testEarlyReturn() {
   {
@@ -36,33 +67,8 @@ int testEarlyReturn() {
   }
 }
 
-// testEarlyReturn()
-// CHECK:      LifetimeEnd
-// CHECK-NEXT: EndFunction
-// CHECK-NEXT: ReturnStmt: yes
-// CHECK-NEXT: CFGElement: CFGLifetimeEnds
-
-// testDestrAndLifetimeEnd()
-// CHECK:      PreCall (S::S) [CXXConstructorCall]
-// CHECK-NEXT: EndFunction
-// CHECK-NEXT: ReturnStmt: no
-// CHECK-NEXT: PostCall (S::S) [CXXConstructorCall]
-// CHECK-NEXT: PreCall (S::~S) [CXXDestructorCall]
-// CHECK-NEXT: PostCall (S::~S) [CXXDestructorCall]
-// CHECK-NEXT: LifetimeEnd
-// CHECK-NEXT: EndFunction
-// CHECK-NEXT: ReturnStmt: no
-
-// testLoopVar()
-// CHECK:      LifetimeEnd
-// CHECK-NEXT: EndFunction
-// CHECK-NEXT: ReturnStmt: no
-
-// testLocalInts()
-// CHECK:      LifetimeEnd
-// CHECK-NEXT: LifetimeEnd
-// CHECK-NEXT: EndFunction
-// CHECK-NEXT: ReturnStmt: no
-
-// There should not be further LifetimeEnd elementes.
-// CHECK-NOT: LifetimeEnd
+// CHECK-EARLY-RETURN:      LifetimeEnd
+// CHECK-EARLY-RETURN-NEXT: EndFunction
+// CHECK-EARLY-RETURN-NEXT: ReturnStmt: yes
+// CHECK-EARLY-RETURN-NEXT: CFGElement: CFGLifetimeEnds
+// CHECK-EARLY-RETURN-NOT:  LifetimeEnd



More information about the llvm-branch-commits mailing list