[DebugInfo] Avoid applying a misleading cleanup loc in case blocks
Switch cases without a trailing curly brace have ambiguous cleanup
locations. Here's what the current stepping behavior looks like:
switch x {
case ...:
if true { foo() } // Step
else { bar() } // Step
}
The second step can be misleading, because users might think that the
else branch is taken.
rdar://35628620
(cherry picked from commit b27ed065b6bb67c27a4e5f8e8863ee7c12f32065)
diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp
index 6c27178..664eb3f 100644
--- a/lib/SILGen/SILGenPattern.cpp
+++ b/lib/SILGen/SILGenPattern.cpp
@@ -2315,7 +2315,13 @@
// Implicitly break out of the pattern match statement.
if (SGF.B.hasValidInsertionPoint()) {
- SGF.emitBreakOutOf(CleanupLocation(caseBlock), PatternMatchStmt);
+ // Case blocks without trailing braces have ambiguous cleanup locations.
+ SILLocation cleanupLoc = getCompilerGeneratedLocation();
+ if (auto *braces = dyn_cast<BraceStmt>(caseBlock->getBody()))
+ if (braces->getNumElements() == 1 &&
+ dyn_cast_or_null<DoStmt>(braces->getElement(0).dyn_cast<Stmt *>()))
+ cleanupLoc = CleanupLocation(caseBlock);
+ SGF.emitBreakOutOf(cleanupLoc, PatternMatchStmt);
}
}
diff --git a/test/DebugInfo/patternmatching.swift b/test/DebugInfo/patternmatching.swift
index b98d31a..144a66f 100644
--- a/test/DebugInfo/patternmatching.swift
+++ b/test/DebugInfo/patternmatching.swift
@@ -23,7 +23,7 @@
markUsed(x)
// SIL-CHECK: dealloc_stack{{.*}}line:[[@LINE-1]]:17:cleanup
// Verify that the branch has a location >= the cleanup.
- // SIL-CHECK-NEXT: br{{.*}}line:[[@LINE-3]]:17:cleanup
+ // SIL-CHECK-NEXT: br{{.*}}no_loc
// CHECK-SCOPES: call void @llvm.dbg
// CHECK-SCOPES: call void @llvm.dbg
// CHECK-SCOPES: call void @llvm.dbg
@@ -56,5 +56,16 @@
// CHECK-SCOPES-SAME: scope: ![[SCOPE3]])
markUsed(x)
}
+
+switch p {
+ case (let x, let y) where x == 0:
+ if y == 0 { markUsed(x) }
+ else { markUsed(y) } // SIL-CHECK-NOT: br{{.*}}line:[[@LINE]]:31:cleanup
+ case (let x, let y): do {
+ if y == 0 { markUsed(x) }
+ else { markUsed(y) }
+ } // SIL-CHECK: br{{.*}}line:[[@LINE]]:5:cleanup
+}
+
// CHECK: !DILocation(line: [[@LINE+1]],
}