| Void tail-call inlining test cases. |
| |
| 1. a0: deeply nested bare blocks ending in return. |
| 2. a1: call in switch case, with return after the switch statement. |
| 3. a2: complex nested hierarchy (if -> switch -> block) ending at return. |
| 4. a3: multiple stacked labels before return. |
| 5. a4: call inside else-if branch with explicit return. |
| 6. a5: call inside for loop (must literalize, loop repeats). |
| 7. a6: trailing code after block (must literalize). |
| 8. a7: last statement of if at function end (implicit return). |
| 9. a8: last statement of else at function end (implicit return). |
| 10. a9: type switch case, with return after the type switch. |
| 11. a10: fallthrough after the call (must literalize). |
| 12. a11: call in select default, with return after the select. |
| 13. a12: stacked labels on the return that follows the call. |
| 14. a13: explicit bare return, func f() { defer ...; return }. |
| |
| -- go.mod -- |
| module testdata |
| go 1.20 |
| |
| -- a/pkg.go -- |
| package a |
| |
| func cleanup() { |
| defer println("done") |
| println("cleaning") |
| } |
| |
| -- a/a0.go -- |
| package a |
| |
| func _() { |
| { |
| { |
| cleanup() //@ inline(re"cleanup", nestedBlocks) |
| } |
| } |
| return |
| } |
| |
| -- nestedBlocks -- |
| package a |
| |
| func _() { |
| { |
| { |
| defer println("done") |
| println("cleaning") //@ inline(re"cleanup", nestedBlocks) |
| } |
| } |
| return |
| } |
| |
| -- a/a1.go -- |
| package a |
| |
| func _(x int) { |
| switch x { |
| case 1: |
| cleanup() //@ inline(re"cleanup", switchThenReturn) |
| default: |
| println("default") |
| } |
| return |
| } |
| |
| -- switchThenReturn -- |
| package a |
| |
| func _(x int) { |
| switch x { |
| case 1: |
| defer println("done") |
| println("cleaning") //@ inline(re"cleanup", switchThenReturn) |
| default: |
| println("default") |
| } |
| return |
| } |
| |
| -- a/a2.go -- |
| package a |
| |
| func _(x int, cond bool) { |
| if cond { |
| switch x { |
| case 1: |
| { |
| cleanup() //@ inline(re"cleanup", ifSwitchBlock) |
| } |
| } |
| } |
| return |
| } |
| |
| -- ifSwitchBlock -- |
| package a |
| |
| func _(x int, cond bool) { |
| if cond { |
| switch x { |
| case 1: |
| { |
| defer println("done") |
| println("cleaning") //@ inline(re"cleanup", ifSwitchBlock) |
| } |
| } |
| } |
| return |
| } |
| |
| -- a/a3.go -- |
| package a |
| |
| func _() { |
| label1: |
| label2: |
| cleanup() //@ inline(re"cleanup", stackedLabels) |
| return |
| } |
| |
| -- stackedLabels -- |
| package a |
| |
| func _() { |
| label1: |
| label2: |
| { |
| defer println("done") |
| println("cleaning") |
| } //@ inline(re"cleanup", stackedLabels) |
| return |
| } |
| |
| -- a/a4.go -- |
| package a |
| |
| func _(a, b int) { |
| if a > 0 { |
| println("a") |
| } else if b > 0 { |
| cleanup() //@ inline(re"cleanup", elseIfReturn) |
| return |
| } |
| println("after") |
| } |
| |
| -- elseIfReturn -- |
| package a |
| |
| func _(a, b int) { |
| if a > 0 { |
| println("a") |
| } else if b > 0 { |
| defer println("done") |
| println("cleaning") //@ inline(re"cleanup", elseIfReturn) |
| return |
| } |
| println("after") |
| } |
| |
| -- a/a5.go -- |
| package a |
| |
| func _() { |
| for i := 0; i < 2; i++ { |
| cleanup() //@ inline(re"cleanup", inLoop) |
| } |
| return |
| } |
| |
| -- inLoop -- |
| package a |
| |
| func _() { |
| for i := 0; i < 2; i++ { |
| func() { defer println("done"); println("cleaning") }() //@ inline(re"cleanup", inLoop) |
| } |
| return |
| } |
| |
| -- a/a6.go -- |
| package a |
| |
| func _() { |
| { |
| cleanup() //@ inline(re"cleanup", trailingCode) |
| } |
| println("not tail") |
| return |
| } |
| |
| -- trailingCode -- |
| package a |
| |
| func _() { |
| { |
| func() { defer println("done"); println("cleaning") }() //@ inline(re"cleanup", trailingCode) |
| } |
| println("not tail") |
| return |
| } |
| |
| -- a/a7.go -- |
| package a |
| |
| func _(cond bool) { |
| if cond { |
| cleanup() //@ inline(re"cleanup", lastInIf) |
| } else { |
| println("else") |
| } |
| } |
| |
| -- lastInIf -- |
| package a |
| |
| func _(cond bool) { |
| if cond { |
| defer println("done") |
| println("cleaning") //@ inline(re"cleanup", lastInIf) |
| } else { |
| println("else") |
| } |
| } |
| |
| -- a/a8.go -- |
| package a |
| |
| func _(cond bool) { |
| if cond { |
| println("then") |
| } else { |
| cleanup() //@ inline(re"cleanup", lastInElse) |
| } |
| } |
| |
| -- lastInElse -- |
| package a |
| |
| func _(cond bool) { |
| if cond { |
| println("then") |
| } else { |
| defer println("done") |
| println("cleaning") //@ inline(re"cleanup", lastInElse) |
| } |
| } |
| |
| -- a/a9.go -- |
| package a |
| |
| func _(x any) { |
| switch x.(type) { |
| case int: |
| cleanup() //@ inline(re"cleanup", typeSwitchThenReturn) |
| default: |
| println("default") |
| } |
| return |
| } |
| |
| -- typeSwitchThenReturn -- |
| package a |
| |
| func _(x any) { |
| switch x.(type) { |
| case int: |
| defer println("done") |
| println("cleaning") //@ inline(re"cleanup", typeSwitchThenReturn) |
| default: |
| println("default") |
| } |
| return |
| } |
| |
| -- a/a10.go -- |
| package a |
| |
| func _(x int) { |
| switch x { |
| case 1: |
| cleanup() //@ inline(re"cleanup", fallthroughAfter) |
| fallthrough |
| default: |
| println("default") |
| } |
| return |
| } |
| |
| -- fallthroughAfter -- |
| package a |
| |
| func _(x int) { |
| switch x { |
| case 1: |
| func() { defer println("done"); println("cleaning") }() //@ inline(re"cleanup", fallthroughAfter) |
| fallthrough |
| default: |
| println("default") |
| } |
| return |
| } |
| |
| -- a/a11.go -- |
| package a |
| |
| func _() { |
| select { |
| default: |
| cleanup() //@ inline(re"cleanup", selectThenReturn) |
| } |
| return |
| } |
| |
| -- selectThenReturn -- |
| package a |
| |
| func _() { |
| select { |
| default: |
| defer println("done") |
| println("cleaning") //@ inline(re"cleanup", selectThenReturn) |
| } |
| return |
| } |
| |
| -- a/a12.go -- |
| package a |
| |
| func _() { |
| cleanup() //@ inline(re"cleanup", labeledReturn) |
| done: |
| return |
| } |
| |
| -- labeledReturn -- |
| package a |
| |
| func _() { |
| { |
| defer println("done") |
| println("cleaning") |
| } //@ inline(re"cleanup", labeledReturn) |
| done: |
| return |
| } |
| |
| -- a/a13.go -- |
| package a |
| |
| func f() { |
| justDefer() //@ inline(re"justDefer", explicitBareReturn) |
| return |
| } |
| |
| func justDefer() { |
| defer println("done") |
| } |
| |
| -- explicitBareReturn -- |
| package a |
| |
| func f() { |
| defer println("done") //@ inline(re"justDefer", explicitBareReturn) |
| return |
| } |
| |
| func justDefer() { |
| defer println("done") |
| } |