[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