github.com/kdevb0x/go@v0.0.0-20180115030120-39687051e9e7/test/inline.go (about)

     1  // errorcheck -0 -m
     2  
     3  // Copyright 2015 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // Test, using compiler diagnostic flags, that inlining is working.
     8  // Compiles but does not run.
     9  
    10  package foo
    11  
    12  import (
    13  	"errors"
    14  	"unsafe"
    15  )
    16  
    17  func add2(p *byte, n uintptr) *byte { // ERROR "can inline add2" "leaking param: p to result"
    18  	return (*byte)(add1(unsafe.Pointer(p), n)) // ERROR "inlining call to add1"
    19  }
    20  
    21  func add1(p unsafe.Pointer, x uintptr) unsafe.Pointer { // ERROR "can inline add1" "leaking param: p to result"
    22  	return unsafe.Pointer(uintptr(p) + x)
    23  }
    24  
    25  func f(x *byte) *byte { // ERROR "can inline f" "leaking param: x to result"
    26  	return add2(x, 1) // ERROR "inlining call to add2" "inlining call to add1"
    27  }
    28  
    29  //go:noinline
    30  func g(x int) int {
    31  	return x + 1
    32  }
    33  
    34  func h(x int) int { // ERROR "can inline h"
    35  	return x + 2
    36  }
    37  
    38  func i(x int) int { // ERROR "can inline i"
    39  	const y = 2
    40  	return x + y
    41  }
    42  
    43  func j(x int) int { // ERROR "can inline j"
    44  	switch {
    45  	case x > 0:
    46  		return x + 2
    47  	default:
    48  		return x + 1
    49  	}
    50  }
    51  
    52  var somethingWrong error = errors.New("something went wrong")
    53  
    54  // local closures can be inlined
    55  func l(x, y int) (int, int, error) {
    56  	e := func(err error) (int, int, error) { // ERROR "can inline l.func1" "func literal does not escape" "leaking param: err to result"
    57  		return 0, 0, err
    58  	}
    59  	if x == y {
    60  		e(somethingWrong) // ERROR "inlining call to l.func1"
    61  	}
    62  	return y, x, nil
    63  }
    64  
    65  // any re-assignment prevents closure inlining
    66  func m() int {
    67  	foo := func() int { return 1 } // ERROR "can inline m.func1" "func literal does not escape"
    68  	x := foo()
    69  	foo = func() int { return 2 } // ERROR "can inline m.func2" "func literal does not escape"
    70  	return x + foo()
    71  }
    72  
    73  // address taking prevents closure inlining
    74  func n() int {
    75  	foo := func() int { return 1 } // ERROR "can inline n.func1" "func literal does not escape"
    76  	bar := &foo                    // ERROR "&foo does not escape"
    77  	x := (*bar)() + foo()
    78  	return x
    79  }
    80  
    81  // make sure assignment inside closure is detected
    82  func o() int {
    83  	foo := func() int { return 1 } // ERROR "can inline o.func1" "func literal does not escape"
    84  	func(x int) {                  // ERROR "func literal does not escape"
    85  		if x > 10 {
    86  			foo = func() int { return 2 } // ERROR "can inline o.func2" "func literal escapes"
    87  		}
    88  	}(11)
    89  	return foo()
    90  }
    91  
    92  func p() int {
    93  	return func() int { return 42 }() // ERROR "can inline p.func1" "inlining call to p.func1"
    94  }
    95  
    96  func q(x int) int {
    97  	foo := func() int { return x * 2 } // ERROR "can inline q.func1" "q func literal does not escape"
    98  	return foo()                       // ERROR "inlining call to q.func1"
    99  }
   100  
   101  func r(z int) int {
   102  	foo := func(x int) int { // ERROR "can inline r.func1" "r func literal does not escape"
   103  		return x + z
   104  	}
   105  	bar := func(x int) int { // ERROR "r func literal does not escape"
   106  		return x + func(y int) int { // ERROR "can inline r.func2.1"
   107  			return 2*y + x*z
   108  		}(x) // ERROR "inlining call to r.func2.1"
   109  	}
   110  	return foo(42) + bar(42) // ERROR "inlining call to r.func1"
   111  }
   112  
   113  func s0(x int) int {
   114  	foo := func() { // ERROR "can inline s0.func1" "s0 func literal does not escape"
   115  		x = x + 1
   116  	}
   117  	foo() // ERROR "inlining call to s0.func1" "&x does not escape"
   118  	return x
   119  }
   120  
   121  func s1(x int) int {
   122  	foo := func() int { // ERROR "can inline s1.func1" "s1 func literal does not escape"
   123  		return x
   124  	}
   125  	x = x + 1
   126  	return foo() // ERROR "inlining call to s1.func1" "&x does not escape"
   127  }
   128  
   129  // can't currently inline functions with a break statement
   130  func switchBreak(x, y int) int {
   131  	var n int
   132  	switch x {
   133  	case 0:
   134  		n = 1
   135  	Done:
   136  		switch y {
   137  		case 0:
   138  			n += 10
   139  			break Done
   140  		}
   141  		n = 2
   142  	}
   143  	return n
   144  }
   145  
   146  // can't currently inline functions with a type switch
   147  func switchType(x interface{}) int { // ERROR "switchType x does not escape"
   148  	switch x.(type) {
   149  	case int:
   150  		return x.(int)
   151  	default:
   152  		return 0
   153  	}
   154  }
   155  
   156  type T struct{}
   157  
   158  func (T) meth(int, int) {} // ERROR "can inline T.meth"
   159  
   160  func k() (T, int, int) { return T{}, 0, 0 } // ERROR "can inline k"
   161  
   162  func _() { // ERROR "can inline _"
   163  	T.meth(k()) // ERROR "inlining call to k" "inlining call to T.meth"
   164  }