summaryrefslogtreecommitdiffstats
path: root/llgo/third_party/gotools/go/pointer/testdata/interfaces.go
blob: 91c0fa9a9036fea7004cfae40c975e0aa4e2bc06 (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
// +build ignore

package main

type I interface {
	f()
}

type C int

func (*C) f() {}

type D struct{ ptr *int }

func (D) f() {}

type E struct{}

func (*E) f() {}

var a, b int

var unknown bool // defeat dead-code elimination

func interface1() {
	var i interface{} = &a
	var j interface{} = D{&b}
	k := j
	if unknown {
		k = i
	}

	print(i) // @types *int
	print(j) // @types D
	print(k) // @types *int | D

	print(i.(*int)) // @pointsto main.a
	print(j.(*int)) // @pointsto
	print(k.(*int)) // @pointsto main.a

	print(i.(D).ptr) // @pointsto
	print(j.(D).ptr) // @pointsto main.b
	print(k.(D).ptr) // @pointsto main.b
}

func interface2() {
	var i I = (*C)(&a)
	var j I = D{&a}
	k := j
	if unknown {
		k = i
	}

	print(i) // @types *C
	print(j) // @types D
	print(k) // @types *C | D
	print(k) // @pointsto makeinterface:main.D | makeinterface:*main.C

	k.f()
	// @calls main.interface2 -> (*main.C).f
	// @calls main.interface2 -> (main.D).f

	print(i.(*C))    // @pointsto main.a
	print(j.(D).ptr) // @pointsto main.a
	print(k.(*C))    // @pointsto main.a

	switch x := k.(type) {
	case *C:
		print(x) // @pointsto main.a
	case D:
		print(x.ptr) // @pointsto main.a
	case *E:
		print(x) // @pointsto
	}
}

func interface3() {
	// There should be no backflow of concrete types from the type-switch to x.
	var x interface{} = 0
	print(x) // @types int
	switch x.(type) {
	case int:
	case string:
	}
}

func interface4() {
	var i interface{} = D{&a}
	if unknown {
		i = 123
	}

	print(i) // @types int | D

	j := i.(I)       // interface narrowing type-assertion
	print(j)         // @types D
	print(j.(D).ptr) // @pointsto main.a

	var l interface{} = j // interface widening assignment.
	print(l)              // @types D
	print(l.(D).ptr)      // @pointsto main.a

	m := j.(interface{}) // interface widening type-assertion.
	print(m)             // @types D
	print(m.(D).ptr)     // @pointsto main.a
}

// Interface method calls and value flow:

type J interface {
	f(*int) *int
}

type P struct {
	x int
}

func (p *P) f(pi *int) *int {
	print(p)  // @pointsto p@i5p:6
	print(pi) // @pointsto i@i5i:6
	return &p.x
}

func interface5() {
	var p P // @line i5p
	var j J = &p
	var i int      // @line i5i
	print(j.f(&i)) // @pointsto p.x@i5p:6
	print(&i)      // @pointsto i@i5i:6

	print(j) // @pointsto makeinterface:*main.P
}

// @calls main.interface5 -> (*main.P).f

func interface6() {
	f := I.f
	print(f) // @pointsto (main.I).f$thunk
	f(new(struct{ D }))
}

// @calls main.interface6 -> (main.I).f$thunk
// @calls (main.I).f$thunk -> (*struct{main.D}).f

func main() {
	interface1()
	interface2()
	interface3()
	interface4()
	interface5()
	interface6()
}
OpenPOWER on IntegriCloud