summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/tools/go/ssa/testdata/objlookup.go
blob: 1aaa417e80755823bbb221d5743f63ad1a7cc800 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//+build ignore

package main

// This file is the input to TestObjValueLookup in source_test.go,
// which ensures that each occurrence of an ident defining or
// referring to a func, var or const object can be mapped to its
// corresponding SSA Value.
//
// For every reference to a var object, we use annotations in comments
// to denote both the expected SSA Value kind, and whether to expect
// its value (x) or its address (&x).
//
// For const and func objects, the results don't vary by reference and
// are always values not addresses, so no annotations are needed.  The
// declaration is enough.

import "fmt"
import "os"

type J int

func (*J) method() {}

const globalConst = 0

var globalVar int // &globalVar::Global

func globalFunc() {}

type I interface {
	interfaceMethod()
}

type S struct {
	x int // x::nil
}

func main() {
	print(globalVar) // globalVar::UnOp
	globalVar = 1    // globalVar::Const

	var v0 int = 1 // v0::Const (simple local value spec)
	if v0 > 0 {    // v0::Const
		v0 = 2 // v0::Const
	}
	print(v0) // v0::Phi

	// v1 is captured and thus implicitly address-taken.
	var v1 int = 1         // v1::Const
	v1 = 2                 // v1::Const
	fmt.Println(v1)        // v1::UnOp (load)
	f := func(param int) { // f::MakeClosure param::Parameter
		if y := 1; y > 0 { // y::Const
			print(v1, param) // v1::UnOp (load) param::Parameter
		}
		param = 2      // param::Const
		println(param) // param::Const
	}

	f(0) // f::MakeClosure

	var v2 int // v2::Const (implicitly zero-initialized local value spec)
	print(v2)  // v2::Const

	m := make(map[string]int) // m::MakeMap

	// Local value spec with multi-valued RHS:
	var v3, v4 = m[""] // v3::Extract v4::Extract m::MakeMap
	print(v3)          // v3::Extract
	print(v4)          // v4::Extract

	v3++    // v3::BinOp (assign with op)
	v3 += 2 // v3::BinOp (assign with op)

	v5, v6 := false, "" // v5::Const v6::Const (defining assignment)
	print(v5)           // v5::Const
	print(v6)           // v6::Const

	var v7 S    // &v7::Alloc
	v7.x = 1    // &v7::Alloc &x::FieldAddr
	print(v7.x) // &v7::Alloc &x::FieldAddr

	var v8 [1]int // &v8::Alloc
	v8[0] = 0     // &v8::Alloc
	print(v8[:])  // &v8::Alloc
	_ = v8[0]     // &v8::Alloc
	_ = v8[:][0]  // &v8::Alloc
	v8ptr := &v8  // v8ptr::Alloc &v8::Alloc
	_ = v8ptr[0]  // v8ptr::Alloc
	_ = *v8ptr    // v8ptr::Alloc

	v8a := make([]int, 1) // v8a::Slice
	v8a[0] = 0            // v8a::Slice
	print(v8a[:])         // v8a::Slice

	v9 := S{} // &v9::Alloc

	v10 := &v9 // v10::Alloc &v9::Alloc
	_ = v10    // v10::Alloc

	var v11 *J = nil // v11::Const
	v11.method()     // v11::Const

	var v12 J    // &v12::Alloc
	v12.method() // &v12::Alloc (implicitly address-taken)

	// NB, in the following, 'method' resolves to the *types.Func
	// of (*J).method, so it doesn't help us locate the specific
	// ssa.Values here: a bound-method closure and a promotion
	// wrapper.
	_ = v11.method            // v11::Const
	_ = (*struct{ J }).method // J::nil

	// These vars are not optimised away.
	if false {
		v13 := 0     // v13::Const
		println(v13) // v13::Const
	}

	switch x := 1; x { // x::Const
	case v0: // v0::Phi
	}

	for k, v := range m { // k::Extract v::Extract m::MakeMap
		_ = k // k::Extract
		v++   // v::BinOp
	}

	if y := 0; y > 1 { // y::Const y::Const
	}

	var i interface{}      // i::Const (nil interface)
	i = 1                  // i::MakeInterface
	switch i := i.(type) { // i::MakeInterface i::MakeInterface
	case int:
		println(i) // i::Extract
	}

	ch := make(chan int) // ch::MakeChan
	select {
	case x := <-ch: // x::UnOp (receive) ch::MakeChan
		_ = x // x::UnOp
	}

	// .Op is an inter-package FieldVal-selection.
	var err os.PathError // &err::Alloc
	_ = err.Op           // &err::Alloc &Op::FieldAddr
	_ = &err.Op          // &err::Alloc &Op::FieldAddr

	// Exercise corner-cases of lvalues vs rvalues.
	// (Guessing IsAddr from the 'pointerness' won't cut it here.)
	type N *N
	var n N    // n::Const
	n1 := n    // n1::Const n::Const
	n2 := &n1  // n2::Alloc &n1::Alloc
	n3 := *n2  // n3::UnOp n2::Alloc
	n4 := **n3 // n4::UnOp n3::UnOp
	_ = n4     // n4::UnOp
}