diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 9ea91953ef8..8978a6c6c4e 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -5359,6 +5359,17 @@ public: instResultType.dump();); requireSameType(functionResultType, instResultType, "return value type does not match return type of function"); + + // If the result type is an address, ensure it's base address is from a + // function argument. + if (F.getModule().getStage() >= SILStage::Canonical && + functionResultType.isAddress()) { + auto base = getAccessBase(RI->getOperand()); + require(!base->getType().isAddress() || isa(base) || + isa(base) && + cast(base)->hasAddressResult(), + "unidentified address return"); + } } void checkThrowInst(ThrowInst *TI) { diff --git a/test/SIL/borrow_accessor_verify_errors.sil b/test/SIL/borrow_accessor_verify_errors.sil new file mode 100644 index 00000000000..a9e508c1673 --- /dev/null +++ b/test/SIL/borrow_accessor_verify_errors.sil @@ -0,0 +1,32 @@ +// RUN: %target-sil-opt -dont-abort-on-memory-lifetime-errors -verify-continue-on-failure -enable-sil-verify-all=0 %s 2>&1 | %FileCheck %s + +sil_stage canonical + +public struct GenWrapper { + @_hasStorage var _prop: T { get set } + public var prop: T +} + +sil [ossa] @borrow_addressonly_prop : $@convention(method) (@in_guaranteed GenWrapper) -> @guaranteed_address T { +bb0(%0 : $*GenWrapper): + %2 = struct_element_addr %0, #GenWrapper._prop + return %2 +} + +// CHECK: Begin Error in function test_address_of_temp +// CHECK: SIL verification failed: unidentified address return: !base->getType().isAddress() || isa(base) || isa(base) && cast(base)->hasAddressResult() +// CHECK: Verifying instruction: +// CHECK: %4 = apply %3(%1) : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_address τ_0_0 +// CHECK: -> return %4 : $*T +// CHECK: End Error in function test_address_of_temp +sil [ossa] @test_address_of_temp : $@convention(thin) (@in_guaranteed GenWrapper) -> @guaranteed_address T { +bb0(%0 : $*GenWrapper): + %stk = alloc_stack $GenWrapper + copy_addr %0 to [init] %stk + %1 = function_ref @borrow_addressonly_prop : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_address τ_0_0 + %2 = apply %1(%stk) : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_address τ_0_0 + destroy_addr %stk + dealloc_stack %stk + return %2 +} + diff --git a/test/SILGen/borrow_accessor_failues.swift b/test/SILGen/borrow_accessor_failues.swift index 488665bacc6..5e1c300e876 100644 --- a/test/SILGen/borrow_accessor_failues.swift +++ b/test/SILGen/borrow_accessor_failues.swift @@ -1,4 +1,4 @@ -// RUN:%target-swift-frontend -emit-silgen %s -verify -enable-experimental-feature BorrowAndMutateAccessors +// RUN:%target-swift-frontend -emit-silgen %s -enable-experimental-feature BorrowAndMutateAccessors -sil-verify-none -verify // REQUIRES: swift_feature_BorrowAndMutateAccessors