blob: 118b23dc01f5aec0117fa9ecdf568a7326d631f5 [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all %s -enforce-exclusivity=unchecked -diagnose-static-exclusivity -verify | %FileCheck %s
sil_stage raw
import Builtin
import Swift
sil @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
sil @takesOneInout : $@convention(thin) (@inout Int) -> ()
sil @makesInt : $@convention(thin) () -> Int
sil @takesInoutAndNoEscapeClosure : $@convention(thin) (@inout Int, @owned @callee_owned () -> ()) -> ()
sil @takesInoutAndNoEscapeClosureTakingArgument : $@convention(thin) (@inout Int, @owned @callee_owned (Int) -> ()) -> ()
// CHECK-LABEL: sil hidden @twoLocalInoutsDisaliased
sil hidden @twoLocalInoutsDisaliased : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%5 = alloc_box ${ var Int }
%6 = project_box %5 : ${ var Int }, 0
store %0 to [trivial] %6 : $*Int
%8 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%9 = begin_access [modify] [unknown] %3 : $*Int
%10 = begin_access [modify] [unknown] %6 : $*Int // no-error
%11 = apply %8(%9, %10) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %10 : $*Int
end_access %9: $*Int
destroy_value %5 : ${ var Int }
destroy_value %2 : ${ var Int }
%14 = tuple ()
return %14 : $()
}
// CHECK-LABEL: sil hidden @twoLocalInoutsSimpleAliasing
sil hidden @twoLocalInoutsSimpleAliasing : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = begin_access [modify] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
%7 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %6 : $*Int
end_access %5: $*Int
destroy_value %2 : ${ var Int }
%8 = tuple ()
return %8 : $()
}
// CHECK-LABEL: sil hidden @conflictingPriorAccess
sil hidden @conflictingPriorAccess : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = begin_access [modify] [unknown] %5 : $*Int
%7 = begin_access [modify] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
%8 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*Int
end_access %6 : $*Int
end_access %5: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
// CHECK-LABEL: sil hidden @twoSequentialInouts
sil hidden @twoSequentialInouts : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesOneInout : $@convention(thin) (@inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*Int
%6 = apply %4(%5) : $@convention(thin) (@inout Int) -> ()
end_access %5 : $*Int
%7 = begin_access [modify] [unknown] %3 : $*Int // no-error
%8 = apply %4(%7) : $@convention(thin) (@inout Int) -> ()
end_access %7: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %8 : $()
}
// CHECK-LABEL: sil hidden @unconditionalBranch
sil hidden @unconditionalBranch : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = begin_access [modify] [unknown] %3 : $*Int
br finish
finish:
end_access %4: $*Int
destroy_value %2 : ${ var Int }
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: sil hidden @diamondMergeStacks
sil hidden @diamondMergeStacks : $@convention(thin) (Int, Builtin.Int1) -> () {
bb0(%0 : $Int, %1 : $Builtin.Int1):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = begin_access [modify] [unknown] %3 : $*Int
cond_br %1, then, else
then:
br finish
else:
br finish
finish:
end_access %4: $*Int
destroy_value %2 : ${ var Int }
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: sil hidden @loopMergeStacks
sil hidden @loopMergeStacks : $@convention(thin) (Int, Builtin.Int1) -> () {
bb0(%0 : $Int, %1 : $Builtin.Int1):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = begin_access [modify] [unknown] %3 : $*Int
br bb1
bb1:
cond_br %1, bb1, bb2
bb2:
end_access %4: $*Int
destroy_value %2 : ${ var Int }
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: sil hidden @loopWithError
sil hidden @loopWithError : $@convention(thin) (Int, Builtin.Int1) -> () {
bb0(%0 : $Int, %1 : $Builtin.Int1):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
br bb1
bb1:
// Make sure we don't diagnose twice.
%4 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%5 = begin_access [modify] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
end_access %5: $*Int
end_access %4: $*Int
cond_br %1, bb1, bb2
bb2:
destroy_value %2 : ${ var Int }
%6 = tuple ()
return %6 : $()
}
// CHECK-LABEL: sil hidden @modifySubAccessesAreAllowed
sil hidden @modifySubAccessesAreAllowed : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*Int
%6 = begin_access [modify] [unknown] %5 : $*Int // no-error
%7 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %6 : $*Int
end_access %5: $*Int
destroy_value %2 : ${ var Int }
%8 = tuple ()
return %8 : $()
}
// Multiple access kinds
// CHECK-LABEL: sil hidden @twoLocalReadsSimpleAliasing
sil hidden @twoLocalReadsSimpleAliasing : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = alloc_box ${ var Int }
%2 = project_box %1 : ${ var Int }, 0
store %0 to [trivial] %2 : $*Int
%4 = begin_access [read] [unknown] %2 : $*Int
%5 = begin_access [read] [unknown] %2 : $*Int // no-error
end_access %5 : $*Int
end_access %4: $*Int
destroy_value %1 : ${ var Int }
%6 = tuple ()
return %6 : $()
}
// CHECK-LABEL: sil hidden @localReadFollowedByModify
sil hidden @localReadFollowedByModify : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = alloc_box ${ var Int }
%2 = project_box %1 : ${ var Int }, 0
store %0 to [trivial] %2 : $*Int
%4 = begin_access [read] [unknown] %2 : $*Int // expected-note {{conflicting access is here}}
%5 = begin_access [modify] [unknown] %2 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
end_access %5 : $*Int
end_access %4: $*Int
destroy_value %1 : ${ var Int }
%6 = tuple ()
return %6 : $()
}
// CHECK-LABEL: sil hidden @localModifyFollowedByRead
sil hidden @localModifyFollowedByRead : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = alloc_box ${ var Int }
%2 = project_box %1 : ${ var Int }, 0
store %0 to [trivial] %2 : $*Int
%4 = begin_access [modify] [unknown] %2 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%5 = begin_access [read] [unknown] %2 : $*Int // expected-note {{conflicting access is here}}
end_access %5 : $*Int
end_access %4: $*Int
destroy_value %1 : ${ var Int }
%6 = tuple ()
return %6 : $()
}
class ClassWithStoredProperty {
@sil_stored var f: Int
init()
}
// CHECK-LABEL: sil hidden @classStoredProperty
sil hidden @classStoredProperty : $@convention(thin) (ClassWithStoredProperty) -> () {
bb0(%0 : $ClassWithStoredProperty):
%1 = ref_element_addr %0 : $ClassWithStoredProperty, #ClassWithStoredProperty.f
// expected-error@+1{{overlapping accesses to 'f', but modification requires exclusive access; consider copying to a local variable}}
%2 = begin_access [modify] [dynamic] %1 : $*Int
%3 = ref_element_addr %0 : $ClassWithStoredProperty, #ClassWithStoredProperty.f
// expected-note@+1{{conflicting access is here}}
%4 = begin_access [modify] [dynamic] %3 : $*Int
end_access %4 : $*Int
end_access %2 : $*Int
destroy_value %0 : $ClassWithStoredProperty
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: sil hidden @lookThroughBeginBorrow
sil hidden @lookThroughBeginBorrow : $@convention(thin) (ClassWithStoredProperty) -> () {
bb0(%0 : $ClassWithStoredProperty):
%1 = begin_borrow %0 : $ClassWithStoredProperty
%2 = begin_borrow %0 : $ClassWithStoredProperty
%3 = ref_element_addr %1 : $ClassWithStoredProperty, #ClassWithStoredProperty.f
// expected-error@+1{{overlapping accesses to 'f', but modification requires exclusive access; consider copying to a local variable}}
%4 = begin_access [modify] [dynamic] %3 : $*Int
%5 = ref_element_addr %2 : $ClassWithStoredProperty, #ClassWithStoredProperty.f
// expected-note@+1{{conflicting access is here}}
%6 = begin_access [modify] [dynamic] %5 : $*Int
end_access %6 : $*Int
end_access %4 : $*Int
end_borrow %2 from %0 : $ClassWithStoredProperty, $ClassWithStoredProperty
end_borrow %1 from %0 : $ClassWithStoredProperty, $ClassWithStoredProperty
destroy_value %0 : $ClassWithStoredProperty
%7 = tuple ()
return %7 : $()
}
// Tests for address identity
// Treat 'alloc_box' as identity for project_box
// CHECK-LABEL: sil hidden @twoAllocBoxProjections
sil hidden @twoAllocBoxProjections : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = copy_value %2 : ${ var Int }
%5 = project_box %4 : ${ var Int }, 0
%6 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%7 = begin_access [modify] [unknown] %5 : $*Int // expected-note {{conflicting access is here}}
end_access %7 : $*Int
end_access %6: $*Int
destroy_value %2 : ${ var Int }
destroy_value %4 : ${ var Int }
%8 = tuple ()
return %8 : $()
}
// CHECK-LABEL: sil hidden @lookThroughMarkUninitialized
sil hidden @lookThroughMarkUninitialized : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = alloc_box ${ var Int }
%2 = mark_uninitialized [rootself] %1 : ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = project_box %2 : ${ var Int }, 0
%5 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = begin_access [modify] [unknown] %4 : $*Int // expected-note {{conflicting access is here}}
end_access %6 : $*Int
end_access %5: $*Int
destroy_value %2 : ${ var Int }
%7 = tuple ()
return %7 : $()
}
// Treat global as identity for global_addr instruction-
sil_global hidden @global1 : $Int
sil_global hidden @global2 : $Int
// CHECK-LABEL: sil hidden @modifySameGlobal
sil hidden @modifySameGlobal : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = global_addr @global1 :$*Int
%2 = global_addr @global1 :$*Int
%3 = begin_access [modify] [unknown] %1 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%4 = begin_access [modify] [unknown] %2 : $*Int // expected-note {{conflicting access is here}}
end_access %4 : $*Int
end_access %3: $*Int
%5 = tuple ()
return %5 : $()
}
// CHECK-LABEL: sil hidden @modifyDifferentGlobal
sil hidden @modifyDifferentGlobal : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = global_addr @global1 :$*Int
%2 = global_addr @global2 :$*Int
%3 = begin_access [modify] [unknown] %1 : $*Int
%4 = begin_access [modify] [unknown] %2 : $*Int // no-error
end_access %4 : $*Int
end_access %3: $*Int
%5 = tuple ()
return %5 : $()
}
// Multiple errors accessing the same location
// If we have a sequence of begin read - begin write - begin read accesses make
// sure the second read doesn't report a confusing read-read conflict.
// CHECK-LABEL: sil hidden @readWriteReadConflictingThirdAccess
sil hidden @readWriteReadConflictingThirdAccess : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [read] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
%6 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%7 = begin_access [read] [unknown] %3 : $*Int // no-error
%8 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*Int
end_access %6 : $*Int
end_access %5: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
// If we have a sequence of begin write - begin write - begin write accesses make sure the
// third write doesn't report a conflict.
// CHECK-LABEL: sil hidden @writeWriteWriteConflictingThirdAccess
sil hidden @writeWriteWriteConflictingThirdAccess : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = begin_access [modify] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
%7 = begin_access [modify] [unknown] %3 : $*Int // no-error
%8 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*Int
end_access %6 : $*Int
end_access %5: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
// If we have a sequence of begin write - end write - begin write - begin write
// accesses make sure the it is the second begin write that gets the note
// about the conflict and not the first
// CHECK-LABEL: sil hidden @resetFirstAccessForNote
sil hidden @resetFirstAccessForNote : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*Int // no-note
end_access %5 : $*Int
%6 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%7 = begin_access [modify] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
%8 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*Int
end_access %6: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
// Check for iterator invalidation issues when the hash from
// basic blocks to analysis state is re-hashed. The number of
// blocks in this test is determined by the initial size of the
// 'BlockOutAccesses' DenseMap in the implementation.
//
// The unreachable block below must branch to bN where
// N = 3/4 * INITIAL_SIZE - 2
sil @blockMapRehash : $@convention(method) (Builtin.Int1) -> () {
bb0(%0: $Builtin.Int1):
br bb1
bb1:
br bb2
bb2:
br bb3
bb3:
br bb4
bb4:
br bb5
bb5:
br bb6
bb6:
br bb7
bb7:
br bb8
bb8:
br bb9
bb9:
br bb10
bb10:
br bb11
bb11:
br bb12
bb12:
br bb13
bb13:
br bb14
bb14:
br bb15
bb15:
br bb16
bb16:
br bb17
bb17:
br bb18
bb18:
br bb19
bb19:
br bb20
bb20:
br bb21
bb21:
br bb22
bb22:
br bb23 // no-crash
bb23:
%1 = tuple ()
return %1 : $()
bbUnreachable:
br bb22
}
// Check that a pointer_to_address access passes diagnostics.
//
// CHECK-LABEL: sil hidden @pointerToAddr
sil hidden @pointerToAddr : $@convention(thin) (Builtin.RawPointer) -> Int {
bb0(%0: $Builtin.RawPointer):
%adr = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*Int
%access = begin_access [read] [dynamic] %adr : $*Int
%val = load [trivial] %access : $*Int
end_access %access : $*Int
return %val : $Int
}
// Helper.
struct S {
var x: Int
}
// Check inlined struct element access.
// This only happens when mandatory passes are applied repeatedly.
// e.g. importing from a debug standard library.
//
// CHECK-LABEL: sil hidden @inlinedStructElement
sil hidden @inlinedStructElement : $@convention(thin) (@inout S) -> Int {
bb0(%0 : $*S):
%2 = begin_access [modify] [static] %0 : $*S
%3 = struct_element_addr %2 : $*S, #S.x
%4 = begin_access [read] [static] %3 : $*Int
%5 = load [trivial] %4 : $*Int
end_access %4 : $*Int
end_access %2 : $*S
return %5 : $Int
}
// Check inlined tuple element access.
// This only happens when mandatory passes are applied repeatedly.
//
// CHECK-LABEL: sil hidden @inlinedTupleElement
sil hidden @inlinedTupleElement : $@convention(thin) (@inout (Int, Int)) -> Int {
bb0(%0 : $*(Int, Int)):
%2 = begin_access [modify] [static] %0 : $*(Int, Int)
%3 = tuple_element_addr %2 : $*(Int, Int), 0
%4 = begin_access [read] [static] %3 : $*Int
%5 = load [trivial] %4 : $*Int
end_access %4 : $*Int
end_access %2 : $*(Int, Int)
return %5 : $Int
}
// Check inlined enum access.
// This only happens when mandatory passes are applied repeatedly.
//
// CHECK-LABEL: sil hidden @inlinedEnumValue
sil hidden @inlinedEnumValue : $@convention(thin) (Int) -> (@out Optional<Int>, Int) {
bb0(%0 : $*Optional<Int>, %1 : $Int):
%6 = unchecked_take_enum_data_addr %0 : $*Optional<Int>, #Optional.some!enumelt.1
%7 = begin_access [read] [static] %6 : $*Int
%8 = load [trivial] %7 : $*Int
end_access %7 : $*Int
return %8 : $Int
}
// Helper.
class Storage {}
// Check inlined array access.
// This only happens when mandatory passes are applied repeatedly.
//
// CHECK-LABEL: sil hidden @inlinedArrayProp
sil hidden @inlinedArrayProp : $@convention(thin) (@guaranteed Storage, Builtin.Word) -> Int {
bb0(%0 : $Storage, %1 : $Builtin.Word):
%2 = ref_tail_addr %0 : $Storage, $UInt
%3 = begin_access [read] [static] %2 : $*UInt
%4 = tail_addr %3 : $*UInt, %1 : $Builtin.Word, $Int
%5 = begin_access [read] [static] %4 : $*Int
%6 = index_addr %5 : $*Int, %1 : $Builtin.Word
%7 = begin_access [read] [static] %6 : $*Int
%8 = load [trivial] %7 : $*Int
end_access %7 : $*Int
end_access %5 : $*Int
end_access %3 : $*UInt
return %8 : $Int
}
// Conflicts involving noescape closures.
sil hidden @closureThatModifiesCapture_1: $@convention(thin) (@inout_aliasable Int) -> () {
bb0(%0 : $*Int):
%1 = begin_access [modify] [unknown] %0 : $*Int // expected-note {{conflicting access is here}}
end_access %1 : $*Int
%2 = tuple ()
return %2 : $()
}
// CHECK-LABEL: sil hidden @inProgressModifyModifyConflictWithCallToClosure
sil hidden @inProgressModifyModifyConflictWithCallToClosure : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @closureThatModifiesCapture_1: $@convention(thin) (@inout_aliasable Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%8 = apply %4(%3) : $@convention(thin) (@inout_aliasable Int) -> ()
end_access %5: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
sil hidden @closureWithArgument_1 : $@convention(thin) (Int, @inout_aliasable Int) -> () {
bb0(%0 : $Int, %1 : $*Int):
%2 = begin_access [modify] [unknown] %1 : $*Int // expected-note {{conflicting access is here}}
end_access %2 : $*Int
%3 = tuple ()
return %3 : $()
}
// CHECK-LABEL: sil hidden @inProgressConflictWithNoEscapeClosureArgument
sil hidden @inProgressConflictWithNoEscapeClosureArgument : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesInoutAndNoEscapeClosureTakingArgument : $@convention(thin) (@inout Int, @owned @callee_owned (Int) -> ()) -> ()
%5 = function_ref @closureWithArgument_1 : $@convention(thin) (Int, @inout_aliasable Int) -> ()
%6 = partial_apply %5(%3) : $@convention(thin) (Int, @inout_aliasable Int) -> ()
%7 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%8 = apply %4(%3, %6) : $@convention(thin) (@inout Int, @owned @callee_owned (Int) -> ()) -> ()
end_access %7: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
sil hidden @closureThatModifiesCapture_2 : $@convention(thin) (@inout_aliasable Int) -> () {
bb0(%0 : $*Int):
%1 = begin_access [modify] [unknown] %0 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
end_access %1 : $*Int
%2 = tuple ()
return %2 : $()
}
// CHECK-LABEL: sil hidden @inProgressReadModifyConflictWithNoEscapeClosureArgument
sil hidden @inProgressReadModifyConflictWithNoEscapeClosureArgument : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var Int }
%3 = project_box %2 : ${ var Int }, 0
store %0 to [trivial] %3 : $*Int
%4 = function_ref @takesInoutAndNoEscapeClosure : $@convention(thin) (@inout Int, @owned @callee_owned () -> ()) -> ()
%5 = function_ref @closureThatModifiesCapture_2 : $@convention(thin) (@inout_aliasable Int) -> ()
%6 = partial_apply %5(%3) : $@convention(thin) (@inout_aliasable Int) -> ()
%7 = begin_access [read] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
%8 = apply %4(%3, %6) : $@convention(thin) (@inout Int, @owned @callee_owned () -> ()) -> ()
end_access %7: $*Int
destroy_value %2 : ${ var Int }
%9 = tuple ()
return %9 : $()
}
// Stored property relaxation.
struct NestedStructWithStoredProps {
var a: Int
var b: Int
}
struct StructWithStoredProps {
var x: Int
var y: Int
var n: NestedStructWithStoredProps
}
sil @takesInoutIntAndStructWithStoredProps : $@convention(thin) (@inout Int, @inout StructWithStoredProps) -> ()
// CHECK-LABEL: sil hidden @twoSeparateStoredProperties
sil hidden @twoSeparateStoredProperties : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var StructWithStoredProps }
%3 = project_box %2 : ${ var StructWithStoredProps }, 0
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps
%6 = struct_element_addr %5 : $*StructWithStoredProps, #StructWithStoredProps.x
%7 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // no-error
%8 = struct_element_addr %7 : $*StructWithStoredProps, #StructWithStoredProps.y
%9 = apply %4(%6, %8) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*StructWithStoredProps
end_access %5: $*StructWithStoredProps
destroy_value %2 : ${ var StructWithStoredProps }
%10 = tuple ()
return %10 : $()
}
// CHECK-LABEL: sil hidden @twoSeparateNestedStoredProperties
sil hidden @twoSeparateNestedStoredProperties : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var StructWithStoredProps }
%3 = project_box %2 : ${ var StructWithStoredProps }, 0
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps
%6 = struct_element_addr %5 : $*StructWithStoredProps, #StructWithStoredProps.n
%7 = struct_element_addr %6 : $*NestedStructWithStoredProps, #NestedStructWithStoredProps.a
%8 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // no-error
%9 = struct_element_addr %8 : $*StructWithStoredProps, #StructWithStoredProps.n
%10 = struct_element_addr %9 : $*NestedStructWithStoredProps, #NestedStructWithStoredProps.b
%11 = apply %4(%7, %10) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %8 : $*StructWithStoredProps
end_access %5: $*StructWithStoredProps
destroy_value %2 : ${ var StructWithStoredProps }
%12 = tuple ()
return %12 : $()
}
// CHECK-LABEL: sil hidden @theSameStoredProperty
sil hidden @theSameStoredProperty : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var StructWithStoredProps }
%3 = project_box %2 : ${ var StructWithStoredProps }, 0
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = struct_element_addr %5 : $*StructWithStoredProps, #StructWithStoredProps.x
%7 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // expected-note {{conflicting access is here}}
%8 = struct_element_addr %7 : $*StructWithStoredProps, #StructWithStoredProps.x
%9 = apply %4(%6, %8) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*StructWithStoredProps
end_access %5: $*StructWithStoredProps
destroy_value %2 : ${ var StructWithStoredProps }
%10 = tuple ()
return %10 : $()
}
// CHECK-LABEL: sil hidden @storedPropertyAndAggregate
sil hidden @storedPropertyAndAggregate : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var StructWithStoredProps }
%3 = project_box %2 : ${ var StructWithStoredProps }, 0
%4 = function_ref @takesInoutIntAndStructWithStoredProps : $@convention(thin) (@inout Int, @inout StructWithStoredProps) -> ()
%5 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = struct_element_addr %5 : $*StructWithStoredProps, #StructWithStoredProps.x
%7 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // expected-note {{conflicting access is here}}
%8 = apply %4(%6, %7) : $@convention(thin) (@inout Int, @inout StructWithStoredProps) -> ()
end_access %7 : $*StructWithStoredProps
end_access %5: $*StructWithStoredProps
destroy_value %2 : ${ var StructWithStoredProps }
%9 = tuple ()
return %9 : $()
}
// CHECK-LABEL: sil hidden @nestedStoredPropertyAndAggregate
sil hidden @nestedStoredPropertyAndAggregate : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var StructWithStoredProps }
%3 = project_box %2 : ${ var StructWithStoredProps }, 0
%4 = function_ref @takesInoutIntAndStructWithStoredProps : $@convention(thin) (@inout Int, @inout StructWithStoredProps) -> ()
%5 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = struct_element_addr %5 : $*StructWithStoredProps, #StructWithStoredProps.n
%7 = struct_element_addr %6 : $*NestedStructWithStoredProps, #NestedStructWithStoredProps.a
%8 = begin_access [modify] [unknown] %3 : $*StructWithStoredProps // expected-note {{conflicting access is here}}
%9 = struct_element_addr %8 : $*StructWithStoredProps, #StructWithStoredProps.n
end_access %8 : $*StructWithStoredProps
end_access %5: $*StructWithStoredProps
destroy_value %2 : ${ var StructWithStoredProps }
%10 = tuple ()
return %10 : $()
}
// CHECK-LABEL: sil hidden @twoSeparateTupleElements
sil hidden @twoSeparateTupleElements : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var (Int, Int) }
%3 = project_box %2 : ${ var (Int, Int) }, 0
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*(Int, Int)
%6 = tuple_element_addr %5 : $*(Int, Int), 0
%7 = begin_access [modify] [unknown] %3 : $*(Int, Int) // no-error
%8 = tuple_element_addr %7 : $*(Int, Int), 1
%9 = apply %4(%6, %8) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*(Int, Int)
end_access %5: $*(Int, Int)
destroy_value %2 : ${ var (Int, Int) }
%10 = tuple ()
return %10 : $()
}
// CHECK-LABEL: sil hidden @sameTupleElement
sil hidden @sameTupleElement : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%2 = alloc_box ${ var (Int, Int) }
%3 = project_box %2 : ${ var (Int, Int) }, 0
%4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
%5 = begin_access [modify] [unknown] %3 : $*(Int, Int) // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
%6 = tuple_element_addr %5 : $*(Int, Int), 0
%7 = begin_access [modify] [unknown] %3 : $*(Int, Int) // expected-note {{conflicting access is here}}
%8 = tuple_element_addr %7 : $*(Int, Int), 0
%9 = apply %4(%6, %8) : $@convention(thin) (@inout Int, @inout Int) -> ()
end_access %7 : $*(Int, Int)
end_access %5: $*(Int, Int)
destroy_value %2 : ${ var (Int, Int) }
%10 = tuple ()
return %10 : $()
}