...

Source file src/golang.org/x/tools/go/ssa/interp/testdata/forvarlifetime_go122.go

Documentation: golang.org/x/tools/go/ssa/interp/testdata

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build go1.22
     6  
     7  package main
     8  
     9  import (
    10  	"reflect"
    11  )
    12  
    13  func main() {
    14  	test_init()
    15  	bound()
    16  	manyvars()
    17  	nocond()
    18  	nopost()
    19  	address_sequences()
    20  	post_escapes()
    21  
    22  	// Clones from cmd/compile/internal/loopvar/testdata .
    23  	for_complicated_esc_address()
    24  	for_esc_address()
    25  	for_esc_closure()
    26  	for_esc_method()
    27  }
    28  
    29  // After go1.22, each i will have a distinct address and value.
    30  var distinct = func(m, n int) []*int {
    31  	var r []*int
    32  	for i := m; i <= n; i++ {
    33  		r = append(r, &i)
    34  	}
    35  	return r
    36  }(3, 5)
    37  
    38  func test_init() {
    39  	if len(distinct) != 3 {
    40  		panic(distinct)
    41  	}
    42  	for i, v := range []int{3, 4, 5} {
    43  		if v != *(distinct[i]) {
    44  			panic(distinct)
    45  		}
    46  	}
    47  }
    48  
    49  func bound() {
    50  	b := func(k int) func() int {
    51  		var f func() int
    52  		for i := 0; i < k; i++ {
    53  			f = func() int { return i } // address before post updates i. So last value in the body.
    54  		}
    55  		return f
    56  	}
    57  
    58  	if got := b(0); got != nil {
    59  		panic(got)
    60  	}
    61  	if got := b(5); got() != 4 {
    62  		panic(got())
    63  	}
    64  }
    65  
    66  func manyvars() {
    67  	// Tests declaring many variables and having one in the middle escape.
    68  	var f func() int
    69  	for i, j, k, l, m, n, o, p := 7, 6, 5, 4, 3, 2, 1, 0; p < 6; l, p = l+1, p+1 {
    70  		_, _, _, _, _, _, _, _ = i, j, k, l, m, n, o, p
    71  		f = func() int { return l } // address *before* post updates l
    72  	}
    73  	if f() != 9 { // l == p+4
    74  		panic(f())
    75  	}
    76  }
    77  
    78  func nocond() {
    79  	var c, b, e *int
    80  	for p := 0; ; p++ {
    81  		if p%7 == 0 {
    82  			c = &p
    83  			continue
    84  		} else if p == 20 {
    85  			b = &p
    86  			break
    87  		}
    88  		e = &p
    89  	}
    90  
    91  	if *c != 14 {
    92  		panic(c)
    93  	}
    94  	if *b != 20 {
    95  		panic(b)
    96  	}
    97  	if *e != 19 {
    98  		panic(e)
    99  	}
   100  }
   101  
   102  func nopost() {
   103  	var first, last *int
   104  	for p := 0; p < 20; {
   105  		if first == nil {
   106  			first = &p
   107  		}
   108  		last = &p
   109  
   110  		p++
   111  	}
   112  
   113  	if *first != 1 {
   114  		panic(first)
   115  	}
   116  	if *last != 20 {
   117  		panic(last)
   118  	}
   119  }
   120  
   121  func address_sequences() {
   122  	var c, b, p []*int
   123  
   124  	cond := func(x *int) bool {
   125  		c = append(c, x)
   126  		return *x < 5
   127  	}
   128  	body := func(x *int) {
   129  		b = append(b, x)
   130  	}
   131  	post := func(x *int) {
   132  		p = append(p, x)
   133  		(*x)++
   134  	}
   135  	for i := 0; cond(&i); post(&i) {
   136  		body(&i)
   137  	}
   138  
   139  	if c[0] == c[1] {
   140  		panic(c)
   141  	}
   142  
   143  	if !reflect.DeepEqual(c[:5], b) {
   144  		panic(c)
   145  	}
   146  
   147  	if !reflect.DeepEqual(c[1:], p) {
   148  		panic(c)
   149  	}
   150  
   151  	if !reflect.DeepEqual(b[1:], p[:4]) {
   152  		panic(b)
   153  	}
   154  }
   155  
   156  func post_escapes() {
   157  	var p []*int
   158  	post := func(x *int) {
   159  		p = append(p, x)
   160  		(*x)++
   161  	}
   162  
   163  	for i := 0; i < 5; post(&i) {
   164  	}
   165  
   166  	var got []int
   167  	for _, x := range p {
   168  		got = append(got, *x)
   169  	}
   170  	if want := []int{1, 2, 3, 4, 5}; !reflect.DeepEqual(got, want) {
   171  		panic(got)
   172  	}
   173  }
   174  
   175  func for_complicated_esc_address() {
   176  	// Clone of for_complicated_esc_adress.go
   177  	ss, sa := shared(23)
   178  	ps, pa := private(23)
   179  	es, ea := experiment(23)
   180  
   181  	if ss != ps || ss != es || ea != pa || sa == pa {
   182  		println("shared s, a", ss, sa, "; private, s, a", ps, pa, "; experiment s, a", es, ea)
   183  		panic("for_complicated_esc_address")
   184  	}
   185  }
   186  
   187  func experiment(x int) (int, int) {
   188  	sum := 0
   189  	var is []*int
   190  	for i := x; i != 1; i = i / 2 {
   191  		for j := 0; j < 10; j++ {
   192  			if i == j { // 10 skips
   193  				continue
   194  			}
   195  			sum++
   196  		}
   197  		i = i*3 + 1
   198  		if i&1 == 0 {
   199  			is = append(is, &i)
   200  			for i&2 == 0 {
   201  				i = i >> 1
   202  			}
   203  		} else {
   204  			i = i + i
   205  		}
   206  	}
   207  
   208  	asum := 0
   209  	for _, pi := range is {
   210  		asum += *pi
   211  	}
   212  
   213  	return sum, asum
   214  }
   215  
   216  func private(x int) (int, int) {
   217  	sum := 0
   218  	var is []*int
   219  	I := x
   220  	for ; I != 1; I = I / 2 {
   221  		i := I
   222  		for j := 0; j < 10; j++ {
   223  			if i == j { // 10 skips
   224  				I = i
   225  				continue
   226  			}
   227  			sum++
   228  		}
   229  		i = i*3 + 1
   230  		if i&1 == 0 {
   231  			is = append(is, &i)
   232  			for i&2 == 0 {
   233  				i = i >> 1
   234  			}
   235  		} else {
   236  			i = i + i
   237  		}
   238  		I = i
   239  	}
   240  
   241  	asum := 0
   242  	for _, pi := range is {
   243  		asum += *pi
   244  	}
   245  
   246  	return sum, asum
   247  }
   248  
   249  func shared(x int) (int, int) {
   250  	sum := 0
   251  	var is []*int
   252  	i := x
   253  	for ; i != 1; i = i / 2 {
   254  		for j := 0; j < 10; j++ {
   255  			if i == j { // 10 skips
   256  				continue
   257  			}
   258  			sum++
   259  		}
   260  		i = i*3 + 1
   261  		if i&1 == 0 {
   262  			is = append(is, &i)
   263  			for i&2 == 0 {
   264  				i = i >> 1
   265  			}
   266  		} else {
   267  			i = i + i
   268  		}
   269  	}
   270  
   271  	asum := 0
   272  	for _, pi := range is {
   273  		asum += *pi
   274  	}
   275  	return sum, asum
   276  }
   277  
   278  func for_esc_address() {
   279  	// Clone of for_esc_address.go
   280  	sum := 0
   281  	var is []*int
   282  	for i := 0; i < 10; i++ {
   283  		for j := 0; j < 10; j++ {
   284  			if i == j { // 10 skips
   285  				continue
   286  			}
   287  			sum++
   288  		}
   289  		if i&1 == 0 {
   290  			is = append(is, &i)
   291  		}
   292  	}
   293  
   294  	bug := false
   295  	if sum != 100-10 {
   296  		println("wrong sum, expected", 90, ", saw", sum)
   297  		bug = true
   298  	}
   299  	if len(is) != 5 {
   300  		println("wrong iterations, expected ", 5, ", saw", len(is))
   301  		bug = true
   302  	}
   303  	sum = 0
   304  	for _, pi := range is {
   305  		sum += *pi
   306  	}
   307  	if sum != 0+2+4+6+8 {
   308  		println("wrong sum, expected ", 20, ", saw ", sum)
   309  		bug = true
   310  	}
   311  	if bug {
   312  		panic("for_esc_address")
   313  	}
   314  }
   315  
   316  func for_esc_closure() {
   317  	var is []func() int
   318  
   319  	// Clone of for_esc_closure.go
   320  	sum := 0
   321  	for i := 0; i < 10; i++ {
   322  		for j := 0; j < 10; j++ {
   323  			if i == j { // 10 skips
   324  				continue
   325  			}
   326  			sum++
   327  		}
   328  		if i&1 == 0 {
   329  			is = append(is, func() int {
   330  				if i%17 == 15 {
   331  					i++
   332  				}
   333  				return i
   334  			})
   335  		}
   336  	}
   337  
   338  	bug := false
   339  	if sum != 100-10 {
   340  		println("wrong sum, expected ", 90, ", saw", sum)
   341  		bug = true
   342  	}
   343  	if len(is) != 5 {
   344  		println("wrong iterations, expected ", 5, ", saw", len(is))
   345  		bug = true
   346  	}
   347  	sum = 0
   348  	for _, f := range is {
   349  		sum += f()
   350  	}
   351  	if sum != 0+2+4+6+8 {
   352  		println("wrong sum, expected ", 20, ", saw ", sum)
   353  		bug = true
   354  	}
   355  	if bug {
   356  		panic("for_esc_closure")
   357  	}
   358  }
   359  
   360  type I int
   361  
   362  func (x *I) method() int {
   363  	return int(*x)
   364  }
   365  
   366  func for_esc_method() {
   367  	// Clone of for_esc_method.go
   368  	var is []func() int
   369  	sum := 0
   370  	for i := I(0); int(i) < 10; i++ {
   371  		for j := 0; j < 10; j++ {
   372  			if int(i) == j { // 10 skips
   373  				continue
   374  			}
   375  			sum++
   376  		}
   377  		if i&1 == 0 {
   378  			is = append(is, i.method)
   379  		}
   380  	}
   381  
   382  	bug := false
   383  	if sum != 100-10 {
   384  		println("wrong sum, expected ", 90, ", saw ", sum)
   385  		bug = true
   386  	}
   387  	if len(is) != 5 {
   388  		println("wrong iterations, expected ", 5, ", saw", len(is))
   389  		bug = true
   390  	}
   391  	sum = 0
   392  	for _, m := range is {
   393  		sum += m()
   394  	}
   395  	if sum != 0+2+4+6+8 {
   396  		println("wrong sum, expected ", 20, ", saw ", sum)
   397  		bug = true
   398  	}
   399  	if bug {
   400  		panic("for_esc_method")
   401  	}
   402  }
   403  

View as plain text