@@ -149,7 +149,11 @@ class LocalVariableAccessInfo: CustomStringConvertible {
149149 case . load:
150150 self . _isFullyAssigned = false
151151 case . store:
152- self . _isFullyAssigned = true
152+ if let store = localAccess. instruction as? StoringInstruction {
153+ self . _isFullyAssigned = LocalVariableAccessInfo . isBase ( address: store. source)
154+ } else {
155+ self . _isFullyAssigned = true
156+ }
153157 case . apply:
154158 let apply = localAccess. instruction as! FullApplySite
155159 if let convention = apply. convention ( of: localAccess. operand!) {
@@ -191,6 +195,18 @@ class LocalVariableAccessInfo: CustomStringConvertible {
191195 return " full-assign: \( _isFullyAssigned == nil ? " unknown " : String ( describing: _isFullyAssigned!) ) "
192196 + " \( access) "
193197 }
198+
199+ // Does this address correspond to the local variable's base address? Any writes to this address will be a full
200+ // assignment. This should match any instructions that the LocalVariableAccessMap initializer below recognizes as an
201+ // allocation.
202+ static private func isBase( address: Value ) -> Bool {
203+ switch address {
204+ case is AllocBoxInst , is AllocStackInst , is BeginAccessInst :
205+ return true
206+ default :
207+ return false
208+ }
209+ }
194210}
195211
196212/// Model the formal accesses of an addressible variable introduced by an alloc_box, alloc_stack, or indirect
@@ -363,24 +379,14 @@ extension LocalVariableAccessWalker: AddressUseVisitor {
363379 return . continueWalk
364380 }
365381
366- // Handle storage type projections, like MarkUninitializedInst. Path projections should not be visited. They only
367- // occur inside the access .
382+ // Handle storage type projections, like MarkUninitializedInst. Path projections are visited for field
383+ // initialization because SILGen does not emit begin_access [init] consistently .
368384 //
369- // Exception: stack -allocated temporaries may be treated like local variables for the purpose of finding all
370- // uses. Such temporaries do not have access scopes, so we need to walk down any projection that may be used to
371- // initialize the temporary.
385+ // Stack -allocated temporaries are also treated like local variables for the purpose of finding all uses. Such
386+ // temporaries do not have access scopes, so we need to walk down any projection that may be used to initialize the
387+ // temporary.
372388 mutating func projectedAddressUse( of operand: Operand , into value: Value ) -> WalkResult {
373- // TODO: we need an abstraction for path projections. For local variables, these cannot occur outside of an access.
374- switch operand. instruction {
375- case is StructElementAddrInst , is TupleElementAddrInst , is IndexAddrInst , is TailAddrInst ,
376- is UncheckedTakeEnumDataAddrInst , is OpenExistentialAddrInst :
377- return . abortWalk
378- // Projections used to initialize a temporary
379- case is InitEnumDataAddrInst , is InitExistentialAddrInst :
380- fallthrough
381- default :
382- return walkDownAddressUses ( address: value)
383- }
389+ return walkDownAddressUses ( address: value)
384390 }
385391
386392 mutating func scopedAddressUse( of operand: Operand ) -> WalkResult {
0 commit comments