Skip to content

Commit c084403

Browse files
author
Kevin Ballard
committed
[SILGen] Handle #function in defer blocks correctly
Using `#function` in a `defer` block should return the enclosing function name rather than the string `$defer()`. Fixes SR-819.
1 parent fbd74a3 commit c084403

File tree

2 files changed

+37
-10
lines changed

2 files changed

+37
-10
lines changed

lib/SILGen/SILGenFunction.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,15 @@ DeclName SILGenModule::getMagicFunctionName(DeclContext *dc) {
6666
return getMagicFunctionName(closure->getParent());
6767
}
6868
if (auto absFunc = dyn_cast<AbstractFunctionDecl>(dc)) {
69-
// If this is an accessor, use the name of the storage.
7069
if (auto func = dyn_cast<FuncDecl>(absFunc)) {
71-
if (auto storage = func->getAccessorStorageDecl())
70+
// If this is an accessor, use the name of the storage.
71+
if (auto storage = func->getAccessorStorageDecl()) {
7272
return storage->getFullName();
73+
}
74+
// If this is a defer body, use the parent name.
75+
if (func->isDeferBody()) {
76+
return getMagicFunctionName(func->getParent());
77+
}
7378
}
7479

7580
return absFunc->getFullName();

test/Interpreter/defer.swift

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,33 @@
11
// RUN: %target-run-simple-swift | FileCheck %s
22
// REQUIRES: executable_test
33

4-
defer { print("deferred 1") }
5-
defer { print("deferred 2") }
6-
print("start!")
7-
8-
// CHECK-NOT: deferred
9-
// CHECK-LABEL: start!
10-
// CHECK-NEXT: deferred 2
11-
// CHECK-NEXT: deferred 1
4+
do {
5+
defer { print("deferred 1") }
6+
defer { print("deferred 2") }
7+
print("start!")
8+
9+
// CHECK-NOT: deferred
10+
// CHECK-LABEL: start!
11+
// CHECK-NEXT: deferred 2
12+
// CHECK-NEXT: deferred 1
13+
}
14+
15+
// ensure #function ignores defer blocks
16+
do {
17+
print("top-level #function")
18+
let name = #function
19+
defer { print(name == #function ? "good" : "bad") }
20+
21+
// CHECK-LABEL: top-level #function
22+
// CHECK-NEXT: good
23+
}
24+
25+
func foo() {
26+
print("foo()")
27+
let name = #function
28+
defer { print(name == #function ? "good" : "bad") }
29+
30+
// CHECK-LABEL: foo()
31+
// CHECK-NEXT: good
32+
}
33+
foo()

0 commit comments

Comments
 (0)