Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1 | // Copyright 2009 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 | package gc |
| 6 | |
| 7 | import ( |
| 8 | "cmd/internal/obj" |
| 9 | "fmt" |
| 10 | "strings" |
| 11 | ) |
| 12 | |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 13 | func dflag() bool { |
| 14 | if Debug['d'] == 0 { |
| 15 | return false |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 16 | } |
| 17 | if Debug['y'] != 0 { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 18 | return true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 19 | } |
| 20 | if incannedimport != 0 { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 21 | return false |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 22 | } |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 23 | return true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 24 | } |
| 25 | |
| 26 | /* |
| 27 | * declaration stack & operations |
| 28 | */ |
| 29 | func dcopy(a *Sym, b *Sym) { |
| 30 | a.Pkg = b.Pkg |
| 31 | a.Name = b.Name |
| 32 | a.Def = b.Def |
| 33 | a.Block = b.Block |
| 34 | a.Lastlineno = b.Lastlineno |
| 35 | } |
| 36 | |
| 37 | func push() *Sym { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 38 | d := new(Sym) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 39 | d.Lastlineno = lineno |
| 40 | d.Link = dclstack |
| 41 | dclstack = d |
| 42 | return d |
| 43 | } |
| 44 | |
| 45 | func pushdcl(s *Sym) *Sym { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 46 | d := push() |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 47 | dcopy(d, s) |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 48 | if dflag() { |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 49 | fmt.Printf("\t%v push %v %p\n", Ctxt.Line(int(lineno)), s, s.Def) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 50 | } |
| 51 | return d |
| 52 | } |
| 53 | |
| 54 | func popdcl() { |
| 55 | var d *Sym |
| 56 | var s *Sym |
| 57 | var lno int |
| 58 | |
| 59 | // if(dflag()) |
| 60 | // print("revert\n"); |
| 61 | |
| 62 | for d = dclstack; d != nil; d = d.Link { |
| 63 | if d.Name == "" { |
| 64 | break |
| 65 | } |
| 66 | s = Pkglookup(d.Name, d.Pkg) |
| 67 | lno = int(s.Lastlineno) |
| 68 | dcopy(s, d) |
| 69 | d.Lastlineno = int32(lno) |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 70 | if dflag() { |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 71 | fmt.Printf("\t%v pop %v %p\n", Ctxt.Line(int(lineno)), s, s.Def) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 72 | } |
| 73 | } |
| 74 | |
| 75 | if d == nil { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 76 | Fatalf("popdcl: no mark") |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 77 | } |
| 78 | dclstack = d.Link |
| 79 | block = d.Block |
| 80 | } |
| 81 | |
| 82 | func poptodcl() { |
| 83 | // pop the old marker and push a new one |
| 84 | // (cannot reuse the existing one) |
| 85 | // because we use the markers to identify blocks |
| 86 | // for the goto restriction checks. |
| 87 | popdcl() |
| 88 | |
| 89 | markdcl() |
| 90 | } |
| 91 | |
| 92 | func markdcl() { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 93 | d := push() |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 94 | d.Name = "" // used as a mark in fifo |
| 95 | d.Block = block |
| 96 | |
| 97 | blockgen++ |
| 98 | block = blockgen |
| 99 | } |
| 100 | |
| 101 | // if(dflag()) |
| 102 | // print("markdcl\n"); |
| 103 | func dumpdcl(st string) { |
| 104 | var s *Sym |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 105 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 106 | i := 0 |
| 107 | for d := dclstack; d != nil; d = d.Link { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 108 | i++ |
| 109 | fmt.Printf(" %.2d %p", i, d) |
| 110 | if d.Name == "" { |
| 111 | fmt.Printf("\n") |
| 112 | continue |
| 113 | } |
| 114 | |
| 115 | fmt.Printf(" '%s'", d.Name) |
| 116 | s = Pkglookup(d.Name, d.Pkg) |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 117 | fmt.Printf(" %v\n", s) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 118 | } |
| 119 | } |
| 120 | |
| 121 | func testdclstack() { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 122 | for d := dclstack; d != nil; d = d.Link { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 123 | if d.Name == "" { |
| 124 | if nerrors != 0 { |
| 125 | errorexit() |
| 126 | } |
| 127 | Yyerror("mark left on the stack") |
| 128 | continue |
| 129 | } |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | func redeclare(s *Sym, where string) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 134 | if s.Lastlineno == 0 { |
Russ Cox | bed1f90 | 2015-03-02 16:03:26 -0500 | [diff] [blame] | 135 | var tmp string |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 136 | if s.Origpkg != nil { |
| 137 | tmp = s.Origpkg.Path |
| 138 | } else { |
| 139 | tmp = s.Pkg.Path |
| 140 | } |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 141 | pkgstr := tmp |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 142 | Yyerror("%v redeclared %s\n"+"\tprevious declaration during import %q", s, where, pkgstr) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 143 | } else { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 144 | line1 := parserline() |
| 145 | line2 := int(s.Lastlineno) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 146 | |
| 147 | // When an import and a declaration collide in separate files, |
| 148 | // present the import as the "redeclared", because the declaration |
| 149 | // is visible where the import is, but not vice versa. |
| 150 | // See issue 4510. |
| 151 | if s.Def == nil { |
| 152 | line2 = line1 |
| 153 | line1 = int(s.Lastlineno) |
| 154 | } |
| 155 | |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 156 | yyerrorl(int(line1), "%v redeclared %s\n"+"\tprevious declaration at %v", s, where, Ctxt.Line(line2)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 157 | } |
| 158 | } |
| 159 | |
| 160 | var vargen int |
| 161 | |
| 162 | /* |
| 163 | * declare individual names - var, typ, const |
| 164 | */ |
| 165 | |
| 166 | var declare_typegen int |
| 167 | |
Josh Bleecher Snyder | 102b806 | 2015-03-27 12:00:07 -0700 | [diff] [blame] | 168 | func declare(n *Node, ctxt uint8) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 169 | if ctxt == PDISCARD { |
| 170 | return |
| 171 | } |
| 172 | |
| 173 | if isblank(n) { |
| 174 | return |
| 175 | } |
| 176 | |
Russ Cox | 140ef3c | 2015-05-26 23:08:39 -0400 | [diff] [blame] | 177 | if n.Name == nil { |
| 178 | // named OLITERAL needs Name; most OLITERALs don't. |
| 179 | n.Name = new(Name) |
| 180 | } |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 181 | n.Lineno = int32(parserline()) |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 182 | s := n.Sym |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 183 | |
| 184 | // kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later. |
Håvard Haugen | dc3540d | 2015-08-30 23:56:40 +0200 | [diff] [blame] | 185 | if importpkg == nil && !typecheckok && s.Pkg != localpkg { |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 186 | Yyerror("cannot declare name %v", s) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 187 | } |
| 188 | |
| 189 | if ctxt == PEXTERN && s.Name == "init" { |
Shenghou Ma | b3fb0fd | 2015-05-13 19:05:50 -0400 | [diff] [blame] | 190 | Yyerror("cannot declare init - must be func") |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 191 | } |
| 192 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 193 | gen := 0 |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 194 | if ctxt == PEXTERN { |
| 195 | externdcl = list(externdcl, n) |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 196 | if dflag() { |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 197 | fmt.Printf("\t%v global decl %v %p\n", Ctxt.Line(int(lineno)), s, n) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 198 | } |
| 199 | } else { |
| 200 | if Curfn == nil && ctxt == PAUTO { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 201 | Fatalf("automatic outside function") |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 202 | } |
| 203 | if Curfn != nil { |
Josh Bleecher Snyder | 3ed9e4c | 2015-03-25 19:33:01 -0700 | [diff] [blame] | 204 | Curfn.Func.Dcl = list(Curfn.Func.Dcl, n) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 205 | } |
| 206 | if n.Op == OTYPE { |
| 207 | declare_typegen++ |
| 208 | gen = declare_typegen |
| 209 | } else if n.Op == ONAME && ctxt == PAUTO && !strings.Contains(s.Name, "·") { |
| 210 | vargen++ |
| 211 | gen = vargen |
| 212 | } |
| 213 | pushdcl(s) |
Russ Cox | fd2154f | 2015-05-27 07:31:56 -0400 | [diff] [blame] | 214 | n.Name.Curfn = Curfn |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 215 | } |
| 216 | |
| 217 | if ctxt == PAUTO { |
| 218 | n.Xoffset = 0 |
| 219 | } |
| 220 | |
| 221 | if s.Block == block { |
| 222 | // functype will print errors about duplicate function arguments. |
| 223 | // Don't repeat the error here. |
| 224 | if ctxt != PPARAM && ctxt != PPARAMOUT { |
| 225 | redeclare(s, "in this block") |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | s.Block = block |
| 230 | s.Lastlineno = int32(parserline()) |
| 231 | s.Def = n |
Russ Cox | 11322d4 | 2015-05-26 23:56:14 -0400 | [diff] [blame] | 232 | n.Name.Vargen = int32(gen) |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 233 | n.Name.Funcdepth = Funcdepth |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 234 | n.Class = uint8(ctxt) |
| 235 | |
| 236 | autoexport(n, ctxt) |
| 237 | } |
| 238 | |
Josh Bleecher Snyder | 102b806 | 2015-03-27 12:00:07 -0700 | [diff] [blame] | 239 | func addvar(n *Node, t *Type, ctxt uint8) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 240 | if n == nil || n.Sym == nil || (n.Op != ONAME && n.Op != ONONAME) || t == nil { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 241 | Fatalf("addvar: n=%v t=%v nil", n, t) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 242 | } |
| 243 | |
| 244 | n.Op = ONAME |
| 245 | declare(n, ctxt) |
| 246 | n.Type = t |
| 247 | } |
| 248 | |
| 249 | /* |
| 250 | * declare variables from grammar |
| 251 | * new_name_list (type | [type] = expr_list) |
| 252 | */ |
| 253 | func variter(vl *NodeList, t *Node, el *NodeList) *NodeList { |
Russ Cox | 175929b | 2015-03-02 14:22:05 -0500 | [diff] [blame] | 254 | var init *NodeList |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 255 | doexpr := el != nil |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 256 | |
| 257 | if count(el) == 1 && count(vl) > 1 { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 258 | e := el.N |
| 259 | as2 := Nod(OAS2, nil, nil) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 260 | as2.List = vl |
| 261 | as2.Rlist = list1(e) |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 262 | var v *Node |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 263 | for ; vl != nil; vl = vl.Next { |
| 264 | v = vl.N |
| 265 | v.Op = ONAME |
| 266 | declare(v, dclcontext) |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 267 | v.Name.Param.Ntype = t |
Russ Cox | 4fdd536 | 2015-05-26 22:19:27 -0400 | [diff] [blame] | 268 | v.Name.Defn = as2 |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 269 | if Funcdepth > 0 { |
| 270 | init = list(init, Nod(ODCL, v, nil)) |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | return list(init, as2) |
| 275 | } |
| 276 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 277 | var v *Node |
| 278 | var e *Node |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 279 | for ; vl != nil; vl = vl.Next { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 280 | if doexpr { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 281 | if el == nil { |
| 282 | Yyerror("missing expression in var declaration") |
| 283 | break |
| 284 | } |
| 285 | |
| 286 | e = el.N |
| 287 | el = el.Next |
| 288 | } else { |
| 289 | e = nil |
| 290 | } |
| 291 | |
| 292 | v = vl.N |
| 293 | v.Op = ONAME |
| 294 | declare(v, dclcontext) |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 295 | v.Name.Param.Ntype = t |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 296 | |
| 297 | if e != nil || Funcdepth > 0 || isblank(v) { |
| 298 | if Funcdepth > 0 { |
| 299 | init = list(init, Nod(ODCL, v, nil)) |
| 300 | } |
| 301 | e = Nod(OAS, v, e) |
| 302 | init = list(init, e) |
| 303 | if e.Right != nil { |
Russ Cox | 4fdd536 | 2015-05-26 22:19:27 -0400 | [diff] [blame] | 304 | v.Name.Defn = e |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 305 | } |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | if el != nil { |
| 310 | Yyerror("extra expression in var declaration") |
| 311 | } |
| 312 | return init |
| 313 | } |
| 314 | |
| 315 | /* |
| 316 | * declare constants from grammar |
| 317 | * new_name_list [[type] = expr_list] |
| 318 | */ |
| 319 | func constiter(vl *NodeList, t *Node, cl *NodeList) *NodeList { |
David Chase | 05d8f1d | 2015-05-22 22:01:01 -0400 | [diff] [blame] | 320 | lno := int32(0) // default is to leave line number alone in listtreecopy |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 321 | if cl == nil { |
| 322 | if t != nil { |
| 323 | Yyerror("const declaration cannot have type without expression") |
| 324 | } |
| 325 | cl = lastconst |
| 326 | t = lasttype |
David Chase | 05d8f1d | 2015-05-22 22:01:01 -0400 | [diff] [blame] | 327 | lno = vl.N.Lineno |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 328 | } else { |
| 329 | lastconst = cl |
| 330 | lasttype = t |
| 331 | } |
David Chase | 05d8f1d | 2015-05-22 22:01:01 -0400 | [diff] [blame] | 332 | cl = listtreecopy(cl, lno) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 333 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 334 | var v *Node |
| 335 | var c *Node |
Russ Cox | 4492811 | 2015-03-02 20:34:22 -0500 | [diff] [blame] | 336 | var vv *NodeList |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 337 | for ; vl != nil; vl = vl.Next { |
| 338 | if cl == nil { |
| 339 | Yyerror("missing value in const declaration") |
| 340 | break |
| 341 | } |
| 342 | |
| 343 | c = cl.N |
| 344 | cl = cl.Next |
| 345 | |
| 346 | v = vl.N |
| 347 | v.Op = OLITERAL |
| 348 | declare(v, dclcontext) |
| 349 | |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 350 | v.Name.Param.Ntype = t |
Russ Cox | 4fdd536 | 2015-05-26 22:19:27 -0400 | [diff] [blame] | 351 | v.Name.Defn = c |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 352 | |
| 353 | vv = list(vv, Nod(ODCLCONST, v, nil)) |
| 354 | } |
| 355 | |
| 356 | if cl != nil { |
| 357 | Yyerror("extra expression in const declaration") |
| 358 | } |
| 359 | iota_ += 1 |
| 360 | return vv |
| 361 | } |
| 362 | |
| 363 | /* |
| 364 | * this generates a new name node, |
| 365 | * typically for labels or other one-off names. |
| 366 | */ |
| 367 | func newname(s *Sym) *Node { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 368 | if s == nil { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 369 | Fatalf("newname nil") |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 370 | } |
| 371 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 372 | n := Nod(ONAME, nil, nil) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 373 | n.Sym = s |
| 374 | n.Type = nil |
Josh Bleecher Snyder | 75883ba | 2015-04-02 19:58:37 -0700 | [diff] [blame] | 375 | n.Addable = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 376 | n.Ullman = 1 |
| 377 | n.Xoffset = 0 |
| 378 | return n |
| 379 | } |
| 380 | |
Josh Bleecher Snyder | 57279ba | 2015-03-10 21:37:13 -0700 | [diff] [blame] | 381 | // newfuncname generates a new name node for a function or method. |
| 382 | // TODO(rsc): Use an ODCLFUNC node instead. See comment in CL 7360. |
| 383 | func newfuncname(s *Sym) *Node { |
| 384 | n := newname(s) |
| 385 | n.Func = new(Func) |
Russ Cox | fd2154f | 2015-05-27 07:31:56 -0400 | [diff] [blame] | 386 | n.Func.FCurfn = Curfn |
Josh Bleecher Snyder | 57279ba | 2015-03-10 21:37:13 -0700 | [diff] [blame] | 387 | return n |
| 388 | } |
| 389 | |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 390 | /* |
| 391 | * this generates a new name node for a name |
| 392 | * being declared. |
| 393 | */ |
| 394 | func dclname(s *Sym) *Node { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 395 | n := newname(s) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 396 | n.Op = ONONAME // caller will correct it |
| 397 | return n |
| 398 | } |
| 399 | |
| 400 | func typenod(t *Type) *Node { |
| 401 | // if we copied another type with *t = *u |
| 402 | // then t->nod might be out of date, so |
| 403 | // check t->nod->type too |
| 404 | if t.Nod == nil || t.Nod.Type != t { |
| 405 | t.Nod = Nod(OTYPE, nil, nil) |
| 406 | t.Nod.Type = t |
| 407 | t.Nod.Sym = t.Sym |
| 408 | } |
| 409 | |
| 410 | return t.Nod |
| 411 | } |
| 412 | |
| 413 | /* |
| 414 | * this will return an old name |
| 415 | * that has already been pushed on the |
| 416 | * declaration list. a diagnostic is |
| 417 | * generated if no name has been defined. |
| 418 | */ |
| 419 | func oldname(s *Sym) *Node { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 420 | n := s.Def |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 421 | if n == nil { |
| 422 | // maybe a top-level name will come along |
| 423 | // to give this a definition later. |
| 424 | // walkdef will check s->def again once |
| 425 | // all the input source has been processed. |
| 426 | n = newname(s) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 427 | n.Op = ONONAME |
Russ Cox | 11322d4 | 2015-05-26 23:56:14 -0400 | [diff] [blame] | 428 | n.Name.Iota = iota_ // save current iota value in const declarations |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 429 | } |
| 430 | |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 431 | if Curfn != nil && n.Op == ONAME && n.Name.Funcdepth > 0 && n.Name.Funcdepth != Funcdepth { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 432 | // inner func is referring to var in outer func. |
| 433 | // |
| 434 | // TODO(rsc): If there is an outer variable x and we |
| 435 | // are parsing x := 5 inside the closure, until we get to |
| 436 | // the := it looks like a reference to the outer x so we'll |
| 437 | // make x a closure variable unnecessarily. |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 438 | if n.Name.Param.Closure == nil || n.Name.Param.Closure.Name.Funcdepth != Funcdepth { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 439 | // create new closure var. |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 440 | c := Nod(ONAME, nil, nil) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 441 | |
| 442 | c.Sym = s |
| 443 | c.Class = PPARAMREF |
| 444 | c.Isddd = n.Isddd |
Russ Cox | 4fdd536 | 2015-05-26 22:19:27 -0400 | [diff] [blame] | 445 | c.Name.Defn = n |
Josh Bleecher Snyder | 75883ba | 2015-04-02 19:58:37 -0700 | [diff] [blame] | 446 | c.Addable = false |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 447 | c.Ullman = 2 |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 448 | c.Name.Funcdepth = Funcdepth |
| 449 | c.Name.Param.Outer = n.Name.Param.Closure |
| 450 | n.Name.Param.Closure = c |
| 451 | c.Name.Param.Closure = n |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 452 | c.Xoffset = 0 |
Josh Bleecher Snyder | 3ed9e4c | 2015-03-25 19:33:01 -0700 | [diff] [blame] | 453 | Curfn.Func.Cvars = list(Curfn.Func.Cvars, c) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 454 | } |
| 455 | |
| 456 | // return ref to closure var, not original |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 457 | return n.Name.Param.Closure |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 458 | } |
| 459 | |
| 460 | return n |
| 461 | } |
| 462 | |
| 463 | /* |
| 464 | * := declarations |
| 465 | */ |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 466 | func colasname(n *Node) bool { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 467 | switch n.Op { |
| 468 | case ONAME, |
| 469 | ONONAME, |
| 470 | OPACK, |
| 471 | OTYPE, |
| 472 | OLITERAL: |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 473 | return n.Sym != nil |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 474 | } |
| 475 | |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 476 | return false |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 477 | } |
| 478 | |
| 479 | func colasdefn(left *NodeList, defn *Node) { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 480 | for l := left; l != nil; l = l.Next { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 481 | if l.N.Sym != nil { |
| 482 | l.N.Sym.Flags |= SymUniq |
| 483 | } |
| 484 | } |
| 485 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 486 | nnew := 0 |
| 487 | nerr := 0 |
| 488 | var n *Node |
| 489 | for l := left; l != nil; l = l.Next { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 490 | n = l.N |
| 491 | if isblank(n) { |
| 492 | continue |
| 493 | } |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 494 | if !colasname(n) { |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 495 | yyerrorl(int(defn.Lineno), "non-name %v on left side of :=", n) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 496 | nerr++ |
| 497 | continue |
| 498 | } |
| 499 | |
| 500 | if n.Sym.Flags&SymUniq == 0 { |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 501 | yyerrorl(int(defn.Lineno), "%v repeated on left side of :=", n.Sym) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 502 | n.Diag++ |
| 503 | nerr++ |
| 504 | continue |
| 505 | } |
| 506 | |
| 507 | n.Sym.Flags &^= SymUniq |
| 508 | if n.Sym.Block == block { |
| 509 | continue |
| 510 | } |
| 511 | |
| 512 | nnew++ |
| 513 | n = newname(n.Sym) |
| 514 | declare(n, dclcontext) |
Russ Cox | 4fdd536 | 2015-05-26 22:19:27 -0400 | [diff] [blame] | 515 | n.Name.Defn = defn |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 516 | defn.Ninit = list(defn.Ninit, Nod(ODCL, n, nil)) |
| 517 | l.N = n |
| 518 | } |
| 519 | |
| 520 | if nnew == 0 && nerr == 0 { |
| 521 | yyerrorl(int(defn.Lineno), "no new variables on left side of :=") |
| 522 | } |
| 523 | } |
| 524 | |
| 525 | func colas(left *NodeList, right *NodeList, lno int32) *Node { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 526 | as := Nod(OAS2, nil, nil) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 527 | as.List = left |
| 528 | as.Rlist = right |
Josh Bleecher Snyder | 75883ba | 2015-04-02 19:58:37 -0700 | [diff] [blame] | 529 | as.Colas = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 530 | as.Lineno = lno |
| 531 | colasdefn(left, as) |
| 532 | |
| 533 | // make the tree prettier; not necessary |
| 534 | if count(left) == 1 && count(right) == 1 { |
| 535 | as.Left = as.List.N |
| 536 | as.Right = as.Rlist.N |
| 537 | as.List = nil |
| 538 | as.Rlist = nil |
| 539 | as.Op = OAS |
| 540 | } |
| 541 | |
| 542 | return as |
| 543 | } |
| 544 | |
| 545 | /* |
| 546 | * declare the arguments in an |
| 547 | * interface field declaration. |
| 548 | */ |
| 549 | func ifacedcl(n *Node) { |
| 550 | if n.Op != ODCLFIELD || n.Right == nil { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 551 | Fatalf("ifacedcl") |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 552 | } |
| 553 | |
| 554 | if isblank(n.Left) { |
| 555 | Yyerror("methods must have a unique non-blank name") |
| 556 | } |
| 557 | |
Josh Bleecher Snyder | 57279ba | 2015-03-10 21:37:13 -0700 | [diff] [blame] | 558 | n.Func = new(Func) |
Russ Cox | fd2154f | 2015-05-27 07:31:56 -0400 | [diff] [blame] | 559 | n.Func.FCurfn = Curfn |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 560 | dclcontext = PPARAM |
| 561 | markdcl() |
| 562 | Funcdepth++ |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 563 | n.Func.Outer = Curfn |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 564 | Curfn = n |
| 565 | funcargs(n.Right) |
| 566 | |
| 567 | // funcbody is normally called after the parser has |
| 568 | // seen the body of a function but since an interface |
| 569 | // field declaration does not have a body, we must |
| 570 | // call it now to pop the current declaration context. |
| 571 | dclcontext = PAUTO |
| 572 | |
| 573 | funcbody(n) |
| 574 | } |
| 575 | |
| 576 | /* |
| 577 | * declare the function proper |
| 578 | * and declare the arguments. |
| 579 | * called in extern-declaration context |
| 580 | * returns in auto-declaration context. |
| 581 | */ |
| 582 | func funchdr(n *Node) { |
| 583 | // change the declaration context from extern to auto |
| 584 | if Funcdepth == 0 && dclcontext != PEXTERN { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 585 | Fatalf("funchdr: dclcontext") |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 586 | } |
| 587 | |
Michael Hudson-Doyle | 1125cd4 | 2015-07-15 11:31:30 +1200 | [diff] [blame] | 588 | if importpkg == nil && n.Func.Nname != nil { |
| 589 | makefuncsym(n.Func.Nname.Sym) |
| 590 | } |
| 591 | |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 592 | dclcontext = PAUTO |
| 593 | markdcl() |
| 594 | Funcdepth++ |
| 595 | |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 596 | n.Func.Outer = Curfn |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 597 | Curfn = n |
| 598 | |
Russ Cox | bd4fff6 | 2015-05-27 10:42:55 -0400 | [diff] [blame] | 599 | if n.Func.Nname != nil { |
| 600 | funcargs(n.Func.Nname.Name.Param.Ntype) |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 601 | } else if n.Func.Ntype != nil { |
| 602 | funcargs(n.Func.Ntype) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 603 | } else { |
| 604 | funcargs2(n.Type) |
| 605 | } |
| 606 | } |
| 607 | |
| 608 | func funcargs(nt *Node) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 609 | if nt.Op != OTFUNC { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 610 | Fatalf("funcargs %v", Oconv(int(nt.Op), 0)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 611 | } |
| 612 | |
| 613 | // re-start the variable generation number |
| 614 | // we want to use small numbers for the return variables, |
| 615 | // so let them have the chunk starting at 1. |
| 616 | vargen = count(nt.Rlist) |
| 617 | |
| 618 | // declare the receiver and in arguments. |
| 619 | // no n->defn because type checking of func header |
| 620 | // will not fill in the types until later |
| 621 | if nt.Left != nil { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 622 | n := nt.Left |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 623 | if n.Op != ODCLFIELD { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 624 | Fatalf("funcargs receiver %v", Oconv(int(n.Op), 0)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 625 | } |
| 626 | if n.Left != nil { |
| 627 | n.Left.Op = ONAME |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 628 | n.Left.Name.Param.Ntype = n.Right |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 629 | declare(n.Left, PPARAM) |
| 630 | if dclcontext == PAUTO { |
| 631 | vargen++ |
Russ Cox | 11322d4 | 2015-05-26 23:56:14 -0400 | [diff] [blame] | 632 | n.Left.Name.Vargen = int32(vargen) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 633 | } |
| 634 | } |
| 635 | } |
| 636 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 637 | var n *Node |
| 638 | for l := nt.List; l != nil; l = l.Next { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 639 | n = l.N |
| 640 | if n.Op != ODCLFIELD { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 641 | Fatalf("funcargs in %v", Oconv(int(n.Op), 0)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 642 | } |
| 643 | if n.Left != nil { |
| 644 | n.Left.Op = ONAME |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 645 | n.Left.Name.Param.Ntype = n.Right |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 646 | declare(n.Left, PPARAM) |
| 647 | if dclcontext == PAUTO { |
| 648 | vargen++ |
Russ Cox | 11322d4 | 2015-05-26 23:56:14 -0400 | [diff] [blame] | 649 | n.Left.Name.Vargen = int32(vargen) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 650 | } |
| 651 | } |
| 652 | } |
| 653 | |
| 654 | // declare the out arguments. |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 655 | gen := count(nt.List) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 656 | var i int = 0 |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 657 | var nn *Node |
| 658 | for l := nt.Rlist; l != nil; l = l.Next { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 659 | n = l.N |
| 660 | |
| 661 | if n.Op != ODCLFIELD { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 662 | Fatalf("funcargs out %v", Oconv(int(n.Op), 0)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 663 | } |
| 664 | |
| 665 | if n.Left == nil { |
| 666 | // Name so that escape analysis can track it. ~r stands for 'result'. |
Matthew Dempsky | 8b3670f | 2015-03-06 12:02:24 -0800 | [diff] [blame] | 667 | n.Left = newname(Lookupf("~r%d", gen)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 668 | gen++ |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 669 | } |
| 670 | |
| 671 | // TODO: n->left->missing = 1; |
| 672 | n.Left.Op = ONAME |
| 673 | |
| 674 | if isblank(n.Left) { |
| 675 | // Give it a name so we can assign to it during return. ~b stands for 'blank'. |
| 676 | // The name must be different from ~r above because if you have |
| 677 | // func f() (_ int) |
| 678 | // func g() int |
| 679 | // f is allowed to use a plain 'return' with no arguments, while g is not. |
| 680 | // So the two cases must be distinguished. |
| 681 | // We do not record a pointer to the original node (n->orig). |
| 682 | // Having multiple names causes too much confusion in later passes. |
| 683 | nn = Nod(OXXX, nil, nil) |
| 684 | |
| 685 | *nn = *n.Left |
| 686 | nn.Orig = nn |
Matthew Dempsky | 8b3670f | 2015-03-06 12:02:24 -0800 | [diff] [blame] | 687 | nn.Sym = Lookupf("~b%d", gen) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 688 | gen++ |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 689 | n.Left = nn |
| 690 | } |
| 691 | |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 692 | n.Left.Name.Param.Ntype = n.Right |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 693 | declare(n.Left, PPARAMOUT) |
| 694 | if dclcontext == PAUTO { |
| 695 | i++ |
Russ Cox | 11322d4 | 2015-05-26 23:56:14 -0400 | [diff] [blame] | 696 | n.Left.Name.Vargen = int32(i) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 697 | } |
| 698 | } |
| 699 | } |
| 700 | |
| 701 | /* |
| 702 | * Same as funcargs, except run over an already constructed TFUNC. |
| 703 | * This happens during import, where the hidden_fndcl rule has |
| 704 | * used functype directly to parse the function's type. |
| 705 | */ |
| 706 | func funcargs2(t *Type) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 707 | if t.Etype != TFUNC { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 708 | Fatalf("funcargs2 %v", t) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 709 | } |
| 710 | |
| 711 | if t.Thistuple != 0 { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 712 | var n *Node |
| 713 | for ft := getthisx(t).Type; ft != nil; ft = ft.Down { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 714 | if ft.Nname == nil || ft.Nname.Sym == nil { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 715 | continue |
| 716 | } |
| 717 | n = ft.Nname // no need for newname(ft->nname->sym) |
| 718 | n.Type = ft.Type |
| 719 | declare(n, PPARAM) |
| 720 | } |
| 721 | } |
| 722 | |
| 723 | if t.Intuple != 0 { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 724 | var n *Node |
| 725 | for ft := getinargx(t).Type; ft != nil; ft = ft.Down { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 726 | if ft.Nname == nil || ft.Nname.Sym == nil { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 727 | continue |
| 728 | } |
| 729 | n = ft.Nname |
| 730 | n.Type = ft.Type |
| 731 | declare(n, PPARAM) |
| 732 | } |
| 733 | } |
| 734 | |
| 735 | if t.Outtuple != 0 { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 736 | var n *Node |
| 737 | for ft := getoutargx(t).Type; ft != nil; ft = ft.Down { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 738 | if ft.Nname == nil || ft.Nname.Sym == nil { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 739 | continue |
| 740 | } |
| 741 | n = ft.Nname |
| 742 | n.Type = ft.Type |
| 743 | declare(n, PPARAMOUT) |
| 744 | } |
| 745 | } |
| 746 | } |
| 747 | |
| 748 | /* |
| 749 | * finish the body. |
| 750 | * called in auto-declaration context. |
| 751 | * returns in extern-declaration context. |
| 752 | */ |
| 753 | func funcbody(n *Node) { |
| 754 | // change the declaration context from auto to extern |
| 755 | if dclcontext != PAUTO { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 756 | Fatalf("funcbody: dclcontext") |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 757 | } |
| 758 | popdcl() |
| 759 | Funcdepth-- |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 760 | Curfn = n.Func.Outer |
| 761 | n.Func.Outer = nil |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 762 | if Funcdepth == 0 { |
| 763 | dclcontext = PEXTERN |
| 764 | } |
| 765 | } |
| 766 | |
| 767 | /* |
| 768 | * new type being defined with name s. |
| 769 | */ |
| 770 | func typedcl0(s *Sym) *Node { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 771 | n := newname(s) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 772 | n.Op = OTYPE |
| 773 | declare(n, dclcontext) |
| 774 | return n |
| 775 | } |
| 776 | |
| 777 | /* |
| 778 | * node n, which was returned by typedcl0 |
| 779 | * is being declared to have uncompiled type t. |
| 780 | * return the ODCLTYPE node to use. |
| 781 | */ |
Dave Cheney | e498181 | 2015-03-10 09:58:01 +1100 | [diff] [blame] | 782 | func typedcl1(n *Node, t *Node, local bool) *Node { |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 783 | n.Name.Param.Ntype = t |
Dave Cheney | e498181 | 2015-03-10 09:58:01 +1100 | [diff] [blame] | 784 | n.Local = local |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 785 | return Nod(ODCLTYPE, n, nil) |
| 786 | } |
| 787 | |
| 788 | /* |
| 789 | * structs, functions, and methods. |
| 790 | * they don't belong here, but where do they belong? |
| 791 | */ |
| 792 | func checkembeddedtype(t *Type) { |
| 793 | if t == nil { |
| 794 | return |
| 795 | } |
| 796 | |
Josh Bleecher Snyder | 25da594 | 2015-03-01 07:54:01 +0000 | [diff] [blame] | 797 | if t.Sym == nil && Isptr[t.Etype] { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 798 | t = t.Type |
| 799 | if t.Etype == TINTER { |
| 800 | Yyerror("embedded type cannot be a pointer to interface") |
| 801 | } |
| 802 | } |
| 803 | |
Josh Bleecher Snyder | 25da594 | 2015-03-01 07:54:01 +0000 | [diff] [blame] | 804 | if Isptr[t.Etype] { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 805 | Yyerror("embedded type cannot be a pointer") |
| 806 | } else if t.Etype == TFORW && t.Embedlineno == 0 { |
| 807 | t.Embedlineno = lineno |
| 808 | } |
| 809 | } |
| 810 | |
| 811 | func structfield(n *Node) *Type { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 812 | lno := int(lineno) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 813 | lineno = n.Lineno |
| 814 | |
| 815 | if n.Op != ODCLFIELD { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 816 | Fatalf("structfield: oops %v\n", n) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 817 | } |
| 818 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 819 | f := typ(TFIELD) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 820 | f.Isddd = n.Isddd |
| 821 | |
| 822 | if n.Right != nil { |
| 823 | typecheck(&n.Right, Etype) |
| 824 | n.Type = n.Right.Type |
| 825 | if n.Left != nil { |
| 826 | n.Left.Type = n.Type |
| 827 | } |
| 828 | if n.Embedded != 0 { |
| 829 | checkembeddedtype(n.Type) |
| 830 | } |
| 831 | } |
| 832 | |
| 833 | n.Right = nil |
| 834 | |
| 835 | f.Type = n.Type |
| 836 | if f.Type == nil { |
Dave Cheney | 8937780 | 2015-09-07 10:37:26 +1000 | [diff] [blame] | 837 | f.Broke = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 838 | } |
| 839 | |
Russ Cox | 81d5810 | 2015-05-27 00:47:05 -0400 | [diff] [blame] | 840 | switch n.Val().Ctype() { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 841 | case CTSTR: |
Russ Cox | bed1f90 | 2015-03-02 16:03:26 -0500 | [diff] [blame] | 842 | f.Note = new(string) |
Russ Cox | 81d5810 | 2015-05-27 00:47:05 -0400 | [diff] [blame] | 843 | *f.Note = n.Val().U.(string) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 844 | |
| 845 | default: |
| 846 | Yyerror("field annotation must be string") |
| 847 | fallthrough |
| 848 | |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 849 | case CTxxx: |
| 850 | f.Note = nil |
| 851 | } |
| 852 | |
| 853 | if n.Left != nil && n.Left.Op == ONAME { |
| 854 | f.Nname = n.Left |
| 855 | f.Embedded = n.Embedded |
| 856 | f.Sym = f.Nname.Sym |
| 857 | } |
| 858 | |
| 859 | lineno = int32(lno) |
| 860 | return f |
| 861 | } |
| 862 | |
| 863 | var uniqgen uint32 |
| 864 | |
| 865 | func checkdupfields(t *Type, what string) { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 866 | lno := int(lineno) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 867 | |
| 868 | for ; t != nil; t = t.Down { |
| 869 | if t.Sym != nil && t.Nname != nil && !isblank(t.Nname) { |
| 870 | if t.Sym.Uniqgen == uniqgen { |
| 871 | lineno = t.Nname.Lineno |
| 872 | Yyerror("duplicate %s %s", what, t.Sym.Name) |
| 873 | } else { |
| 874 | t.Sym.Uniqgen = uniqgen |
| 875 | } |
| 876 | } |
| 877 | } |
| 878 | |
| 879 | lineno = int32(lno) |
| 880 | } |
| 881 | |
| 882 | /* |
| 883 | * convert a parsed id/type list into |
| 884 | * a type for struct/interface/arglist |
| 885 | */ |
| 886 | func tostruct(l *NodeList) *Type { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 887 | var f *Type |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 888 | t := typ(TSTRUCT) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 889 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 890 | for tp := &t.Type; l != nil; l = l.Next { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 891 | f = structfield(l.N) |
| 892 | |
| 893 | *tp = f |
| 894 | tp = &f.Down |
| 895 | } |
| 896 | |
Dave Cheney | 8937780 | 2015-09-07 10:37:26 +1000 | [diff] [blame] | 897 | for f := t.Type; f != nil && !t.Broke; f = f.Down { |
| 898 | if f.Broke { |
| 899 | t.Broke = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 900 | } |
| 901 | } |
| 902 | |
| 903 | uniqgen++ |
| 904 | checkdupfields(t.Type, "field") |
| 905 | |
Dave Cheney | 8937780 | 2015-09-07 10:37:26 +1000 | [diff] [blame] | 906 | if !t.Broke { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 907 | checkwidth(t) |
| 908 | } |
| 909 | |
| 910 | return t |
| 911 | } |
| 912 | |
| 913 | func tofunargs(l *NodeList) *Type { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 914 | var f *Type |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 915 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 916 | t := typ(TSTRUCT) |
Marvin Stenger | 9ac0fff | 2015-09-08 03:51:30 +0200 | [diff] [blame] | 917 | t.Funarg = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 918 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 919 | for tp := &t.Type; l != nil; l = l.Next { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 920 | f = structfield(l.N) |
Marvin Stenger | 9ac0fff | 2015-09-08 03:51:30 +0200 | [diff] [blame] | 921 | f.Funarg = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 922 | |
| 923 | // esc.c needs to find f given a PPARAM to add the tag. |
| 924 | if l.N.Left != nil && l.N.Left.Class == PPARAM { |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 925 | l.N.Left.Name.Param.Field = f |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 926 | } |
| 927 | |
| 928 | *tp = f |
| 929 | tp = &f.Down |
| 930 | } |
| 931 | |
Dave Cheney | 8937780 | 2015-09-07 10:37:26 +1000 | [diff] [blame] | 932 | for f := t.Type; f != nil && !t.Broke; f = f.Down { |
| 933 | if f.Broke { |
| 934 | t.Broke = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 935 | } |
| 936 | } |
| 937 | |
| 938 | return t |
| 939 | } |
| 940 | |
| 941 | func interfacefield(n *Node) *Type { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 942 | lno := int(lineno) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 943 | lineno = n.Lineno |
| 944 | |
| 945 | if n.Op != ODCLFIELD { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 946 | Fatalf("interfacefield: oops %v\n", n) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 947 | } |
| 948 | |
Russ Cox | 81d5810 | 2015-05-27 00:47:05 -0400 | [diff] [blame] | 949 | if n.Val().Ctype() != CTxxx { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 950 | Yyerror("interface method cannot have annotation") |
| 951 | } |
| 952 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 953 | f := typ(TFIELD) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 954 | f.Isddd = n.Isddd |
| 955 | |
| 956 | if n.Right != nil { |
| 957 | if n.Left != nil { |
| 958 | // queue resolution of method type for later. |
| 959 | // right now all we need is the name list. |
| 960 | // avoids cycles for recursive interface types. |
| 961 | n.Type = typ(TINTERMETH) |
| 962 | |
| 963 | n.Type.Nname = n.Right |
| 964 | n.Left.Type = n.Type |
| 965 | queuemethod(n) |
| 966 | |
| 967 | if n.Left.Op == ONAME { |
| 968 | f.Nname = n.Left |
| 969 | f.Embedded = n.Embedded |
| 970 | f.Sym = f.Nname.Sym |
| 971 | } |
| 972 | } else { |
| 973 | typecheck(&n.Right, Etype) |
| 974 | n.Type = n.Right.Type |
| 975 | |
| 976 | if n.Embedded != 0 { |
| 977 | checkembeddedtype(n.Type) |
| 978 | } |
| 979 | |
| 980 | if n.Type != nil { |
| 981 | switch n.Type.Etype { |
| 982 | case TINTER: |
| 983 | break |
| 984 | |
| 985 | case TFORW: |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 986 | Yyerror("interface type loop involving %v", n.Type) |
Dave Cheney | 8937780 | 2015-09-07 10:37:26 +1000 | [diff] [blame] | 987 | f.Broke = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 988 | |
| 989 | default: |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 990 | Yyerror("interface contains embedded non-interface %v", n.Type) |
Dave Cheney | 8937780 | 2015-09-07 10:37:26 +1000 | [diff] [blame] | 991 | f.Broke = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 992 | } |
| 993 | } |
| 994 | } |
| 995 | } |
| 996 | |
| 997 | n.Right = nil |
| 998 | |
| 999 | f.Type = n.Type |
| 1000 | if f.Type == nil { |
Dave Cheney | 8937780 | 2015-09-07 10:37:26 +1000 | [diff] [blame] | 1001 | f.Broke = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1002 | } |
| 1003 | |
| 1004 | lineno = int32(lno) |
| 1005 | return f |
| 1006 | } |
| 1007 | |
| 1008 | func tointerface(l *NodeList) *Type { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1009 | var f *Type |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1010 | var t1 *Type |
| 1011 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1012 | t := typ(TINTER) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1013 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1014 | tp := &t.Type |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1015 | for ; l != nil; l = l.Next { |
| 1016 | f = interfacefield(l.N) |
| 1017 | |
| 1018 | if l.N.Left == nil && f.Type.Etype == TINTER { |
| 1019 | // embedded interface, inline methods |
| 1020 | for t1 = f.Type.Type; t1 != nil; t1 = t1.Down { |
| 1021 | f = typ(TFIELD) |
| 1022 | f.Type = t1.Type |
| 1023 | f.Broke = t1.Broke |
| 1024 | f.Sym = t1.Sym |
| 1025 | if f.Sym != nil { |
| 1026 | f.Nname = newname(f.Sym) |
| 1027 | } |
| 1028 | *tp = f |
| 1029 | tp = &f.Down |
| 1030 | } |
| 1031 | } else { |
| 1032 | *tp = f |
| 1033 | tp = &f.Down |
| 1034 | } |
| 1035 | } |
| 1036 | |
Dave Cheney | 8937780 | 2015-09-07 10:37:26 +1000 | [diff] [blame] | 1037 | for f := t.Type; f != nil && !t.Broke; f = f.Down { |
| 1038 | if f.Broke { |
| 1039 | t.Broke = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1040 | } |
| 1041 | } |
| 1042 | |
| 1043 | uniqgen++ |
| 1044 | checkdupfields(t.Type, "method") |
| 1045 | t = sortinter(t) |
| 1046 | checkwidth(t) |
| 1047 | |
| 1048 | return t |
| 1049 | } |
| 1050 | |
| 1051 | func embedded(s *Sym, pkg *Pkg) *Node { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1052 | const ( |
| 1053 | CenterDot = 0xB7 |
| 1054 | ) |
| 1055 | // Names sometimes have disambiguation junk |
| 1056 | // appended after a center dot. Discard it when |
| 1057 | // making the name for the embedded struct field. |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1058 | name := s.Name |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1059 | |
| 1060 | if i := strings.Index(s.Name, string(CenterDot)); i >= 0 { |
| 1061 | name = s.Name[:i] |
| 1062 | } |
| 1063 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1064 | var n *Node |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1065 | if exportname(name) { |
| 1066 | n = newname(Lookup(name)) |
| 1067 | } else if s.Pkg == builtinpkg { |
| 1068 | // The name of embedded builtins belongs to pkg. |
| 1069 | n = newname(Pkglookup(name, pkg)) |
| 1070 | } else { |
| 1071 | n = newname(Pkglookup(name, s.Pkg)) |
| 1072 | } |
| 1073 | n = Nod(ODCLFIELD, n, oldname(s)) |
| 1074 | n.Embedded = 1 |
| 1075 | return n |
| 1076 | } |
| 1077 | |
| 1078 | /* |
| 1079 | * check that the list of declarations is either all anonymous or all named |
| 1080 | */ |
| 1081 | func findtype(l *NodeList) *Node { |
| 1082 | for ; l != nil; l = l.Next { |
| 1083 | if l.N.Op == OKEY { |
| 1084 | return l.N.Right |
| 1085 | } |
| 1086 | } |
| 1087 | return nil |
| 1088 | } |
| 1089 | |
| 1090 | func checkarglist(all *NodeList, input int) *NodeList { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1091 | named := 0 |
| 1092 | for l := all; l != nil; l = l.Next { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1093 | if l.N.Op == OKEY { |
| 1094 | named = 1 |
| 1095 | break |
| 1096 | } |
| 1097 | } |
| 1098 | |
| 1099 | if named != 0 { |
Russ Cox | 175929b | 2015-03-02 14:22:05 -0500 | [diff] [blame] | 1100 | var n *Node |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1101 | var l *NodeList |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1102 | for l = all; l != nil; l = l.Next { |
| 1103 | n = l.N |
| 1104 | if n.Op != OKEY && n.Sym == nil { |
| 1105 | Yyerror("mixed named and unnamed function parameters") |
| 1106 | break |
| 1107 | } |
| 1108 | } |
| 1109 | |
| 1110 | if l == nil && n != nil && n.Op != OKEY { |
| 1111 | Yyerror("final function parameter must have type") |
| 1112 | } |
| 1113 | } |
| 1114 | |
Russ Cox | 175929b | 2015-03-02 14:22:05 -0500 | [diff] [blame] | 1115 | var nextt *Node |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1116 | var t *Node |
| 1117 | var n *Node |
| 1118 | for l := all; l != nil; l = l.Next { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1119 | // can cache result from findtype to avoid |
| 1120 | // quadratic behavior here, but unlikely to matter. |
| 1121 | n = l.N |
| 1122 | |
| 1123 | if named != 0 { |
| 1124 | if n.Op == OKEY { |
| 1125 | t = n.Right |
| 1126 | n = n.Left |
| 1127 | nextt = nil |
| 1128 | } else { |
| 1129 | if nextt == nil { |
| 1130 | nextt = findtype(l) |
| 1131 | } |
| 1132 | t = nextt |
| 1133 | } |
| 1134 | } else { |
| 1135 | t = n |
| 1136 | n = nil |
| 1137 | } |
| 1138 | |
| 1139 | // during import l->n->op is OKEY, but l->n->left->sym == S |
| 1140 | // means it was a '?', not that it was |
| 1141 | // a lone type This doesn't matter for the exported |
| 1142 | // declarations, which are parsed by rules that don't |
| 1143 | // use checkargs, but can happen for func literals in |
| 1144 | // the inline bodies. |
| 1145 | // TODO(rsc) this can go when typefmt case TFIELD in exportmode fmt.c prints _ instead of ? |
| 1146 | if importpkg != nil && n.Sym == nil { |
| 1147 | n = nil |
| 1148 | } |
| 1149 | |
| 1150 | if n != nil && n.Sym == nil { |
| 1151 | t = n |
| 1152 | n = nil |
| 1153 | } |
| 1154 | |
| 1155 | if n != nil { |
| 1156 | n = newname(n.Sym) |
| 1157 | } |
| 1158 | n = Nod(ODCLFIELD, n, t) |
| 1159 | if n.Right != nil && n.Right.Op == ODDD { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 1160 | if input == 0 { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1161 | Yyerror("cannot use ... in output argument list") |
| 1162 | } else if l.Next != nil { |
| 1163 | Yyerror("can only use ... as final argument in list") |
| 1164 | } |
| 1165 | n.Right.Op = OTARRAY |
| 1166 | n.Right.Right = n.Right.Left |
| 1167 | n.Right.Left = nil |
Dave Cheney | d328756 | 2015-03-09 16:24:07 +1100 | [diff] [blame] | 1168 | n.Isddd = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1169 | if n.Left != nil { |
Dave Cheney | d328756 | 2015-03-09 16:24:07 +1100 | [diff] [blame] | 1170 | n.Left.Isddd = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1171 | } |
| 1172 | } |
| 1173 | |
| 1174 | l.N = n |
| 1175 | } |
| 1176 | |
| 1177 | return all |
| 1178 | } |
| 1179 | |
| 1180 | func fakethis() *Node { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1181 | n := Nod(ODCLFIELD, nil, typenod(Ptrto(typ(TSTRUCT)))) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1182 | return n |
| 1183 | } |
| 1184 | |
| 1185 | /* |
| 1186 | * Is this field a method on an interface? |
| 1187 | * Those methods have an anonymous |
| 1188 | * *struct{} as the receiver. |
| 1189 | * (See fakethis above.) |
| 1190 | */ |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 1191 | func isifacemethod(f *Type) bool { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1192 | rcvr := getthisx(f).Type |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1193 | if rcvr.Sym != nil { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 1194 | return false |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1195 | } |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1196 | t := rcvr.Type |
Josh Bleecher Snyder | 25da594 | 2015-03-01 07:54:01 +0000 | [diff] [blame] | 1197 | if !Isptr[t.Etype] { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 1198 | return false |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1199 | } |
| 1200 | t = t.Type |
| 1201 | if t.Sym != nil || t.Etype != TSTRUCT || t.Type != nil { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 1202 | return false |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1203 | } |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 1204 | return true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1205 | } |
| 1206 | |
| 1207 | /* |
| 1208 | * turn a parsed function declaration |
| 1209 | * into a type |
| 1210 | */ |
| 1211 | func functype(this *Node, in *NodeList, out *NodeList) *Type { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1212 | t := typ(TFUNC) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1213 | |
Russ Cox | 175929b | 2015-03-02 14:22:05 -0500 | [diff] [blame] | 1214 | var rcvr *NodeList |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1215 | if this != nil { |
| 1216 | rcvr = list1(this) |
| 1217 | } |
| 1218 | t.Type = tofunargs(rcvr) |
| 1219 | t.Type.Down = tofunargs(out) |
| 1220 | t.Type.Down.Down = tofunargs(in) |
| 1221 | |
| 1222 | uniqgen++ |
| 1223 | checkdupfields(t.Type.Type, "argument") |
| 1224 | checkdupfields(t.Type.Down.Type, "argument") |
| 1225 | checkdupfields(t.Type.Down.Down.Type, "argument") |
| 1226 | |
Dave Cheney | 8937780 | 2015-09-07 10:37:26 +1000 | [diff] [blame] | 1227 | if t.Type.Broke || t.Type.Down.Broke || t.Type.Down.Down.Broke { |
| 1228 | t.Broke = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1229 | } |
| 1230 | |
| 1231 | if this != nil { |
| 1232 | t.Thistuple = 1 |
| 1233 | } |
| 1234 | t.Outtuple = count(out) |
| 1235 | t.Intuple = count(in) |
Marvin Stenger | 9ac0fff | 2015-09-08 03:51:30 +0200 | [diff] [blame] | 1236 | t.Outnamed = false |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1237 | if t.Outtuple > 0 && out.N.Left != nil && out.N.Left.Orig != nil { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1238 | s := out.N.Left.Orig.Sym |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1239 | if s != nil && (s.Name[0] != '~' || s.Name[1] != 'r') { // ~r%d is the name invented for an unnamed result |
Marvin Stenger | 9ac0fff | 2015-09-08 03:51:30 +0200 | [diff] [blame] | 1240 | t.Outnamed = true |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1241 | } |
| 1242 | } |
| 1243 | |
| 1244 | return t |
| 1245 | } |
| 1246 | |
| 1247 | var methodsym_toppkg *Pkg |
| 1248 | |
| 1249 | func methodsym(nsym *Sym, t0 *Type, iface int) *Sym { |
| 1250 | var s *Sym |
| 1251 | var p string |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1252 | var suffix string |
| 1253 | var spkg *Pkg |
| 1254 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1255 | t := t0 |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1256 | if t == nil { |
| 1257 | goto bad |
| 1258 | } |
| 1259 | s = t.Sym |
Josh Bleecher Snyder | 25da594 | 2015-03-01 07:54:01 +0000 | [diff] [blame] | 1260 | if s == nil && Isptr[t.Etype] { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1261 | t = t.Type |
| 1262 | if t == nil { |
| 1263 | goto bad |
| 1264 | } |
| 1265 | s = t.Sym |
| 1266 | } |
| 1267 | |
| 1268 | spkg = nil |
| 1269 | if s != nil { |
| 1270 | spkg = s.Pkg |
| 1271 | } |
| 1272 | |
| 1273 | // if t0 == *t and t0 has a sym, |
| 1274 | // we want to see *t, not t0, in the method name. |
| 1275 | if t != t0 && t0.Sym != nil { |
| 1276 | t0 = Ptrto(t) |
| 1277 | } |
| 1278 | |
| 1279 | suffix = "" |
| 1280 | if iface != 0 { |
| 1281 | dowidth(t0) |
| 1282 | if t0.Width < Types[Tptr].Width { |
| 1283 | suffix = "·i" |
| 1284 | } |
| 1285 | } |
| 1286 | |
| 1287 | if (spkg == nil || nsym.Pkg != spkg) && !exportname(nsym.Name) { |
Josh Bleecher Snyder | 25da594 | 2015-03-01 07:54:01 +0000 | [diff] [blame] | 1288 | if t0.Sym == nil && Isptr[t0.Etype] { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1289 | p = fmt.Sprintf("(%v).%s.%s%s", Tconv(t0, obj.FmtLeft|obj.FmtShort), nsym.Pkg.Prefix, nsym.Name, suffix) |
| 1290 | } else { |
| 1291 | p = fmt.Sprintf("%v.%s.%s%s", Tconv(t0, obj.FmtLeft|obj.FmtShort), nsym.Pkg.Prefix, nsym.Name, suffix) |
| 1292 | } |
| 1293 | } else { |
Josh Bleecher Snyder | 25da594 | 2015-03-01 07:54:01 +0000 | [diff] [blame] | 1294 | if t0.Sym == nil && Isptr[t0.Etype] { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1295 | p = fmt.Sprintf("(%v).%s%s", Tconv(t0, obj.FmtLeft|obj.FmtShort), nsym.Name, suffix) |
| 1296 | } else { |
| 1297 | p = fmt.Sprintf("%v.%s%s", Tconv(t0, obj.FmtLeft|obj.FmtShort), nsym.Name, suffix) |
| 1298 | } |
| 1299 | } |
| 1300 | |
| 1301 | if spkg == nil { |
| 1302 | if methodsym_toppkg == nil { |
Russ Cox | bed1f90 | 2015-03-02 16:03:26 -0500 | [diff] [blame] | 1303 | methodsym_toppkg = mkpkg("go") |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1304 | } |
| 1305 | spkg = methodsym_toppkg |
| 1306 | } |
| 1307 | |
| 1308 | s = Pkglookup(p, spkg) |
| 1309 | |
| 1310 | return s |
| 1311 | |
| 1312 | bad: |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 1313 | Yyerror("illegal receiver type: %v", t0) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1314 | return nil |
| 1315 | } |
| 1316 | |
| 1317 | func methodname(n *Node, t *Type) *Node { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1318 | s := methodsym(n.Sym, t, 0) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1319 | if s == nil { |
| 1320 | return n |
| 1321 | } |
| 1322 | return newname(s) |
| 1323 | } |
| 1324 | |
| 1325 | func methodname1(n *Node, t *Node) *Node { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1326 | star := "" |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1327 | if t.Op == OIND { |
| 1328 | star = "*" |
| 1329 | t = t.Left |
| 1330 | } |
| 1331 | |
| 1332 | if t.Sym == nil || isblank(n) { |
Josh Bleecher Snyder | 57279ba | 2015-03-10 21:37:13 -0700 | [diff] [blame] | 1333 | return newfuncname(n.Sym) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1334 | } |
| 1335 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1336 | var p string |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1337 | if star != "" { |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 1338 | p = fmt.Sprintf("(%s%v).%v", star, t.Sym, n.Sym) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1339 | } else { |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 1340 | p = fmt.Sprintf("%v.%v", t.Sym, n.Sym) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1341 | } |
| 1342 | |
| 1343 | if exportname(t.Sym.Name) { |
Josh Bleecher Snyder | 57279ba | 2015-03-10 21:37:13 -0700 | [diff] [blame] | 1344 | n = newfuncname(Lookup(p)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1345 | } else { |
Josh Bleecher Snyder | 57279ba | 2015-03-10 21:37:13 -0700 | [diff] [blame] | 1346 | n = newfuncname(Pkglookup(p, t.Sym.Pkg)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1347 | } |
| 1348 | |
| 1349 | return n |
| 1350 | } |
| 1351 | |
| 1352 | /* |
| 1353 | * add a method, declared as a function, |
| 1354 | * n is fieldname, pa is base type, t is function type |
| 1355 | */ |
| 1356 | func addmethod(sf *Sym, t *Type, local bool, nointerface bool) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1357 | // get field sym |
| 1358 | if sf == nil { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 1359 | Fatalf("no method symbol") |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1360 | } |
| 1361 | |
| 1362 | // get parent type sym |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1363 | pa := getthisx(t).Type // ptr to this structure |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1364 | if pa == nil { |
| 1365 | Yyerror("missing receiver") |
| 1366 | return |
| 1367 | } |
| 1368 | |
| 1369 | pa = pa.Type |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1370 | f := methtype(pa, 1) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1371 | if f == nil { |
| 1372 | t = pa |
| 1373 | if t == nil { // rely on typecheck having complained before |
| 1374 | return |
| 1375 | } |
| 1376 | if t != nil { |
Josh Bleecher Snyder | 25da594 | 2015-03-01 07:54:01 +0000 | [diff] [blame] | 1377 | if Isptr[t.Etype] { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1378 | if t.Sym != nil { |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 1379 | Yyerror("invalid receiver type %v (%v is a pointer type)", pa, t) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1380 | return |
| 1381 | } |
| 1382 | |
| 1383 | t = t.Type |
| 1384 | } |
| 1385 | |
Dave Cheney | 8937780 | 2015-09-07 10:37:26 +1000 | [diff] [blame] | 1386 | if t.Broke { // rely on typecheck having complained before |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1387 | return |
| 1388 | } |
| 1389 | if t.Sym == nil { |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 1390 | Yyerror("invalid receiver type %v (%v is an unnamed type)", pa, t) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1391 | return |
| 1392 | } |
| 1393 | |
Josh Bleecher Snyder | 25da594 | 2015-03-01 07:54:01 +0000 | [diff] [blame] | 1394 | if Isptr[t.Etype] { |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 1395 | Yyerror("invalid receiver type %v (%v is a pointer type)", pa, t) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1396 | return |
| 1397 | } |
| 1398 | |
| 1399 | if t.Etype == TINTER { |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 1400 | Yyerror("invalid receiver type %v (%v is an interface type)", pa, t) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1401 | return |
| 1402 | } |
| 1403 | } |
| 1404 | |
| 1405 | // Should have picked off all the reasons above, |
| 1406 | // but just in case, fall back to generic error. |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 1407 | Yyerror("invalid receiver type %v (%v / %v)", pa, Tconv(pa, obj.FmtLong), Tconv(t, obj.FmtLong)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1408 | |
| 1409 | return |
| 1410 | } |
| 1411 | |
| 1412 | pa = f |
| 1413 | if pa.Etype == TSTRUCT { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1414 | for f := pa.Type; f != nil; f = f.Down { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1415 | if f.Sym == sf { |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 1416 | Yyerror("type %v has both field and method named %v", pa, sf) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1417 | return |
| 1418 | } |
| 1419 | } |
| 1420 | } |
| 1421 | |
Dave Cheney | e498181 | 2015-03-10 09:58:01 +1100 | [diff] [blame] | 1422 | if local && !pa.Local { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1423 | // defining method on non-local type. |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 1424 | Yyerror("cannot define new methods on non-local type %v", pa) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1425 | |
| 1426 | return |
| 1427 | } |
| 1428 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1429 | n := Nod(ODCLFIELD, newname(sf), nil) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1430 | n.Type = t |
| 1431 | |
Russ Cox | 175929b | 2015-03-02 14:22:05 -0500 | [diff] [blame] | 1432 | var d *Type // last found |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 1433 | for f := pa.Method; f != nil; f = f.Down { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1434 | d = f |
| 1435 | if f.Etype != TFIELD { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 1436 | Fatalf("addmethod: not TFIELD: %v", Tconv(f, obj.FmtLong)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1437 | } |
| 1438 | if sf.Name != f.Sym.Name { |
| 1439 | continue |
| 1440 | } |
| 1441 | if !Eqtype(t, f.Type) { |
Russ Cox | 17228f4 | 2015-04-17 12:03:22 -0400 | [diff] [blame] | 1442 | Yyerror("method redeclared: %v.%v\n\t%v\n\t%v", pa, sf, f.Type, t) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1443 | } |
| 1444 | return |
| 1445 | } |
| 1446 | |
| 1447 | f = structfield(n) |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 1448 | f.Nointerface = nointerface |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1449 | |
| 1450 | // during import unexported method names should be in the type's package |
| 1451 | if importpkg != nil && f.Sym != nil && !exportname(f.Sym.Name) && f.Sym.Pkg != structpkg { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 1452 | Fatalf("imported method name %v in wrong package %s\n", Sconv(f.Sym, obj.FmtSign), structpkg.Name) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1453 | } |
| 1454 | |
| 1455 | if d == nil { |
| 1456 | pa.Method = f |
| 1457 | } else { |
| 1458 | d.Down = f |
| 1459 | } |
| 1460 | return |
| 1461 | } |
| 1462 | |
| 1463 | func funccompile(n *Node) { |
| 1464 | Stksize = BADWIDTH |
| 1465 | Maxarg = 0 |
| 1466 | |
| 1467 | if n.Type == nil { |
| 1468 | if nerrors == 0 { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 1469 | Fatalf("funccompile missing type") |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1470 | } |
| 1471 | return |
| 1472 | } |
| 1473 | |
| 1474 | // assign parameter offsets |
| 1475 | checkwidth(n.Type) |
| 1476 | |
| 1477 | if Curfn != nil { |
Håvard Haugen | 3c9fa38 | 2015-08-30 23:10:03 +0200 | [diff] [blame] | 1478 | Fatalf("funccompile %v inside %v", n.Func.Nname.Sym, Curfn.Func.Nname.Sym) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1479 | } |
| 1480 | |
| 1481 | Stksize = 0 |
| 1482 | dclcontext = PAUTO |
Russ Cox | 3c3019a | 2015-05-27 00:44:05 -0400 | [diff] [blame] | 1483 | Funcdepth = n.Func.Depth + 1 |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1484 | compile(n) |
| 1485 | Curfn = nil |
| 1486 | Funcdepth = 0 |
| 1487 | dclcontext = PEXTERN |
| 1488 | } |
| 1489 | |
| 1490 | func funcsym(s *Sym) *Sym { |
Russ Cox | c819834 | 2015-03-12 18:45:30 -0400 | [diff] [blame] | 1491 | if s.Fsym != nil { |
| 1492 | return s.Fsym |
| 1493 | } |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1494 | |
Russ Cox | c819834 | 2015-03-12 18:45:30 -0400 | [diff] [blame] | 1495 | s1 := Pkglookup(s.Name+"·f", s.Pkg) |
Russ Cox | ea918ef | 2015-07-15 04:11:26 +0000 | [diff] [blame] | 1496 | s.Fsym = s1 |
Russ Cox | ea918ef | 2015-07-15 04:11:26 +0000 | [diff] [blame] | 1497 | return s1 |
Russ Cox | fa1ea49 | 2015-07-13 20:50:51 -0400 | [diff] [blame] | 1498 | } |
Michael Hudson-Doyle | 1125cd4 | 2015-07-15 11:31:30 +1200 | [diff] [blame] | 1499 | |
| 1500 | func makefuncsym(s *Sym) { |
| 1501 | if isblanksym(s) { |
| 1502 | return |
| 1503 | } |
| 1504 | if compiling_runtime != 0 && s.Name == "getg" { |
| 1505 | // runtime.getg() is not a real function and so does |
| 1506 | // not get a funcsym. |
| 1507 | return |
| 1508 | } |
| 1509 | s1 := funcsym(s) |
| 1510 | s1.Def = newfuncname(s1) |
| 1511 | s1.Def.Func.Shortname = newname(s) |
| 1512 | funcsyms = list(funcsyms, s1.Def) |
| 1513 | } |