| // RUN: %target-sil-opt %s -yield-once-check -o /dev/null -verify |
| // |
| // SIL-level tests for yield-once diagnostics emitted for yield-once coroutines. |
| // Note that the yield-once check runs on all functions with yield_once |
| // qualifier in their type, regardless of whether or not they are |
| // accessors of a property. In fact, currently it is not possible to parse |
| // a property with _read and _modify accessors from a SIL source. |
| |
| sil_stage raw |
| |
| import Builtin |
| import Swift |
| |
| sil @testNoYield : $@yield_once @convention(thin) () -> @yields Int { |
| bb0: |
| %2 = tuple () |
| return %2 : $() // expected-error {{accessor must yield before returning}} |
| } |
| |
| struct TestYield { |
| var flag : Builtin.Int1 |
| var stored: Int64 |
| } |
| |
| sil @testMultipleYields : $@yield_once @convention(thin) (TestYield) -> @yields Int64 { |
| bb0(%0 : $TestYield): |
| %1 = struct_extract %0 : $TestYield, #TestYield.flag |
| cond_br %1, bb1, bb3 |
| |
| bb1: |
| %5 = struct_extract %0 : $TestYield, #TestYield.stored |
| yield %5 : $Int64, resume bb2, unwind bb6 // expected-note {{previous yield was here}} |
| |
| bb2: |
| br bb4 |
| |
| bb3: |
| br bb4 |
| |
| bb4: |
| %9 = struct_extract %0 : $TestYield, #TestYield.stored |
| yield %9 : $Int64, resume bb5, unwind bb7 // expected-error {{accessor must not yield more than once}} |
| |
| bb5: |
| %11 = tuple () |
| return %11 : $() |
| |
| bb6: |
| br bb8 |
| |
| bb7: |
| br bb8 |
| |
| bb8: |
| unwind |
| } |
| |
| sil @testPartialReturnWithoutYield : $@yield_once @convention(thin) (TestYield) -> @yields Int64 { |
| bb0(%0 : $TestYield): |
| %1 = struct_extract %0 : $TestYield, #TestYield.flag |
| cond_br %1, bb1, bb3 // expected-note {{missing yield when the condition is false}} |
| |
| bb1: |
| %5 = struct_extract %0 : $TestYield, #TestYield.stored |
| yield %5 : $Int64, resume bb2, unwind bb5 |
| |
| bb2: |
| br bb4 |
| |
| bb3: |
| br bb4 |
| |
| bb4: |
| %21 = tuple () |
| return %21 : $() // expected-error {{accessor must yield on all paths before returning}} |
| |
| bb5: |
| unwind |
| } |
| |
| sil @testExplicitReturns : $@yield_once @convention(thin) (TestYield) -> @yields Int64 { |
| bb0(%0 : $TestYield): |
| %2 = struct_extract %0 : $TestYield, #TestYield.stored |
| %3 = integer_literal $Builtin.Int64, 0 |
| %4 = struct_extract %2 : $Int64, #Int64._value |
| %5 = builtin "cmp_slt_Int64"(%3 : $Builtin.Int64, %4 : $Builtin.Int64) : $Builtin.Int1 |
| %6 = struct $Bool (%5 : $Builtin.Int1) |
| %7 = struct_extract %6 : $Bool, #Bool._value |
| cond_br %7, bb1, bb2 // expected-note {{missing yield when the condition is true}} |
| |
| bb1: |
| br bb4 |
| |
| bb2: |
| %10 = struct_extract %0 : $TestYield, #TestYield.stored |
| yield %10 : $Int64, resume bb3, unwind bb5 |
| |
| bb3: |
| br bb4 |
| |
| bb4: |
| %13 = tuple () |
| return %13 : $() // expected-error {{accessor must yield on all paths before returning}} |
| |
| bb5: |
| unwind |
| } |