compiler: rationalize external symbol names
[official-gcc.git] / gcc / testsuite / go.go-torture / execute / names-1.go
blobbac91945bc76c20ebf00b8f1e76ec59f17b0854b
1 // names-1 is a change detector for Go symbol names. We don't want
2 // the name mangling to change silently.
3 package main
5 import (
6 "bytes"
7 "debug/elf"
8 "debug/macho"
9 "debug/pe"
10 "debug/xcoff"
11 "fmt"
12 "os"
13 "strings"
16 type Type int
17 type Alias = int
19 //go:noinline
20 func Function1(out *bytes.Buffer) int {
21 var f2 func(int) int
22 f1 := func(i int) int {
23 if i == 0 {
24 return 0
26 type NestedType struct { a int }
27 t := NestedType{f2(i-1)}
28 fmt.Fprint(out, t)
29 return t.a
31 f2 = func(i int) int {
32 if i == 0 {
33 return 0
35 type NestedType struct { a int }
36 t := NestedType{f1(i-1)}
37 fmt.Fprint(out, t)
38 return t.a
40 return f1(10) + f2(10)
43 //go:noinline
44 func Function2(out *bytes.Buffer) {
46 type T struct { b int }
47 fmt.Fprint(out, T{1})
50 type T struct { b int }
51 fmt.Fprint(out, T{2})
55 func (t Type) M(bool, int8, float32, complex64, string, func(), func(int16) (float64, complex128), *byte, struct { f int "tag #$%^&{}: 世界" }, []int32, [24]int64, map[uint8]uint16, chan uint32, <-chan uint64, chan <- uintptr, Type, Alias) {
58 //go:noinline
59 func Function3(out *bytes.Buffer) {
60 fmt.Fprintf(out, "%T", Type(0))
63 func main() {
64 var b bytes.Buffer
65 Function1(&b)
66 Function2(&b)
67 Function3(&b)
68 _ = len(b.String())
70 for _, n := range []string{"/proc/self/exe", os.Args[0]} {
71 if f, err := os.Open(n); err == nil {
72 checkFile(f)
73 return
76 fmt.Println("checksyms: could not find executable")
77 fmt.Println("UNSUPPORTED: checksyms")
80 func checkFile(f *os.File) {
81 var syms []string
82 if ef, err := elf.NewFile(f); err == nil {
83 esyms, err := ef.Symbols()
84 if err != nil {
85 panic(err)
87 for _, esym := range esyms {
88 syms = append(syms, esym.Name)
90 } else if mf, err := macho.NewFile(f); err == nil {
91 for _, msym := range mf.Symtab.Syms {
92 syms = append(syms, msym.Name)
94 } else if pf, err := pe.NewFile(f); err == nil {
95 for _, psym := range pf.Symbols {
96 syms = append(syms, psym.Name)
98 } else if xf, err := xcoff.NewFile(f); err == nil {
99 for _, xsym := range xf.Symbols {
100 syms = append(syms, xsym.Name)
102 } else {
103 fmt.Println("checksyms: could not parse executable")
104 fmt.Println("UNSUPPORTED: checksyms")
105 return
107 checkSyms(syms)
110 var want = []string{
111 "main.Function1",
112 "main.Function1..f",
113 "main.Function1..func1",
114 "main.Function1..func1.main.NestedType..d",
115 "main.Function1..func2",
116 "main.Function1..func2.main.NestedType..d",
117 "main.Function2",
118 "main.Function2..f",
119 "main.Function2.main.T..d",
120 "main.Function2.main.T..i1..d",
121 "main.Function3",
122 "main.Function3..f",
123 "main.Type..d",
124 "main.Type.M",
125 "main.main",
126 "main.want",
127 "type...1.1main.Type", // Why is this here?
128 "type...1main.Function1..func1.NestedType",
129 "type...1main.Function1..func2.NestedType",
130 "type...1main.Function2.T",
131 "type...1main.Function2.T..i1",
132 "type...1main.Type",
133 "type..func.8.1main.Type.3bool.3int8.3float32.3complex64.3string.3func.8.9.8.9.3func.8int16.9.8float64.3complex128.9.3.1uint8.3struct.4.main.f.0int.4tag.x20.x23.x24.x25.x5e.x26.x7b.x7d.x3a.x20..u4e16..u754c.5.5.3.6.7int32.3.624.7int64.3map.6uint8.7uint16.3chan.0uint32.3.4.5chan.0uint64.3chan.4.5.0uintptr.3main.Type.3int.9.8.9",
134 "type..func.8bool.3int8.3float32.3complex64.3string.3func.8.9.8.9.3func.8int16.9.8float64.3complex128.9.3.1uint8.3struct.4.main.f.0int.4tag.x20.x23.x24.x25.x5e.x26.x7b.x7d.x3a.x20..u4e16..u754c.5.5.3.6.7int32.3.624.7int64.3map.6uint8.7uint16.3chan.0uint32.3.4.5chan.0uint64.3chan.4.5.0uintptr.3main.Type.3int.9.8.9",
135 "type..func.8main.Type.3bool.3int8.3float32.3complex64.3string.3func.8.9.8.9.3func.8int16.9.8float64.3complex128.9.3.1uint8.3struct.4.main.f.0int.4tag.x20.x23.x24.x25.x5e.x26.x7b.x7d.x3a.x20..u4e16..u754c.5.5.3.6.7int32.3.624.7int64.3map.6uint8.7uint16.3chan.0uint32.3.4.5chan.0uint64.3chan.4.5.0uintptr.3main.Type.3int.9.8.9",
136 "type..struct.4.main.f.0int.4tag.x20.x23.x24.x25.x5e.x26.x7b.x7d.x3a.x20..u4e16..u754c.5.5",
139 func checkSyms(syms []string) {
140 m := make(map[string]bool)
141 for _, sym := range syms {
142 if strings.Contains(sym, ".") {
143 m[sym] = true
147 ok := true
148 for _, w := range want {
149 if m[w] {
150 delete(m, w)
151 } else {
152 fmt.Printf("checksyms: missing expected symbol %q\n", w)
153 ok = false
157 for sym := range m {
158 if !strings.Contains(sym, "main") {
159 continue
162 // Skip some symbols we may see but know are unimportant.
163 if sym == "go-main.c" {
164 continue
166 if strings.HasPrefix(sym, "runtime.") {
167 continue
170 // We can see a lot of spurious .eq and .hash
171 // functions for types defined in other packages.
172 // This is a bug but skip them for now.
173 if strings.Contains(sym, "..eq") || strings.Contains(sym, "..hash") {
174 continue
177 // Skip closure types by skipping incomparable structs.
178 // This may be a bug, not sure.
179 if strings.Contains(sym, ".4x.5") {
180 continue
183 // These functions may be inlined.
184 if sym == "main.checkFile" || sym == "main.checkSyms" {
185 continue
188 fmt.Printf("checksyms: found unexpected symbol %q\n", sym)
189 ok = false
192 if !ok {
193 fmt.Println("FAIL: checksyms")