go/pointer: fix bug in constraint generation of "for _, v := range map"
+ regression test Change-Id: I9ec28f222e14af0cb737494e3c48e5423cdcf236 Reviewed-on: https://go-review.googlesource.com/16294 Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
		
							parent
							
								
									b6b32a4fbf
								
							
						
					
					
						commit
						0f9d71c428
					
				| 
						 | 
				
			
			@ -1050,11 +1050,32 @@ func (a *analysis) genInstr(cgn *cgnode, instr ssa.Instruction) {
 | 
			
		|||
			// Assumes that Next is always directly applied to a Range result.
 | 
			
		||||
			theMap := instr.Iter.(*ssa.Range).X
 | 
			
		||||
			tMap := theMap.Type().Underlying().(*types.Map)
 | 
			
		||||
 | 
			
		||||
			ksize := a.sizeof(tMap.Key())
 | 
			
		||||
			vsize := a.sizeof(tMap.Elem())
 | 
			
		||||
 | 
			
		||||
			// The k/v components of the Next tuple may each be invalid.
 | 
			
		||||
			tTuple := instr.Type().(*types.Tuple)
 | 
			
		||||
 | 
			
		||||
			// Load from the map's (k,v) into the tuple's (ok, k, v).
 | 
			
		||||
			a.genLoad(cgn, a.valueNode(instr)+1, theMap, 0, ksize+vsize)
 | 
			
		||||
			osrc := uint32(0) // offset within map object
 | 
			
		||||
			odst := uint32(1) // offset within tuple (initially just after 'ok bool')
 | 
			
		||||
			sz := uint32(0)   // amount to copy
 | 
			
		||||
 | 
			
		||||
			// Is key valid?
 | 
			
		||||
			if tTuple.At(1).Type() != tInvalid {
 | 
			
		||||
				sz += ksize
 | 
			
		||||
			} else {
 | 
			
		||||
				odst += ksize
 | 
			
		||||
				osrc += ksize
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Is value valid?
 | 
			
		||||
			if tTuple.At(2).Type() != tInvalid {
 | 
			
		||||
				sz += vsize
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			a.genLoad(cgn, a.valueNode(instr)+nodeid(odst), theMap, osrc, sz)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case *ssa.Lookup:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,7 +45,30 @@ func maps2() {
 | 
			
		|||
	print(m2[nil]) // @pointsto main.c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var g int
 | 
			
		||||
 | 
			
		||||
func maps3() {
 | 
			
		||||
	// Regression test for a constraint generation bug for map range
 | 
			
		||||
	// loops in which the key is unused: the (ok, k, v) tuple
 | 
			
		||||
	// returned by ssa.Next may have type 'invalid' for the k and/or
 | 
			
		||||
	// v components, so copying the map key or value may cause
 | 
			
		||||
	// miswiring if the key has >1 components.  In the worst case,
 | 
			
		||||
	// this causes a crash.  The test below used to report that
 | 
			
		||||
	// pts(v) includes not just main.g but new(float64) too, which
 | 
			
		||||
	// is ill-typed.
 | 
			
		||||
 | 
			
		||||
	// sizeof(K) > 1, abstractly
 | 
			
		||||
	type K struct{ a, b *float64 }
 | 
			
		||||
	k := K{new(float64), nil}
 | 
			
		||||
	m := map[K]*int{k: &g}
 | 
			
		||||
 | 
			
		||||
	for _, v := range m {
 | 
			
		||||
		print(v) // @pointsto main.g
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	maps1()
 | 
			
		||||
	maps2()
 | 
			
		||||
	maps3()
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue