github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/compile/internal/gc/noder.go (about) 1 // Copyright 2016 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 "fmt" 9 "os" 10 "path/filepath" 11 "runtime" 12 "strconv" 13 "strings" 14 "unicode/utf8" 15 16 "github.com/gagliardetto/golang-go/cmd/compile/internal/syntax" 17 "github.com/gagliardetto/golang-go/cmd/compile/internal/types" 18 "github.com/gagliardetto/golang-go/cmd/internal/obj" 19 "github.com/gagliardetto/golang-go/cmd/internal/objabi" 20 "github.com/gagliardetto/golang-go/cmd/internal/src" 21 ) 22 23 // parseFiles concurrently parses files into *syntax.File structures. 24 // Each declaration in every *syntax.File is converted to a syntax tree 25 // and its root represented by *Node is appended to xtop. 26 // Returns the total count of parsed lines. 27 func parseFiles(filenames []string) uint { 28 noders := make([]*noder, 0, len(filenames)) 29 // Limit the number of simultaneously open files. 30 sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10) 31 32 for _, filename := range filenames { 33 p := &noder{ 34 basemap: make(map[*syntax.PosBase]*src.PosBase), 35 err: make(chan syntax.Error), 36 } 37 noders = append(noders, p) 38 39 go func(filename string) { 40 sem <- struct{}{} 41 defer func() { <-sem }() 42 defer close(p.err) 43 base := syntax.NewFileBase(filename) 44 45 f, err := os.Open(filename) 46 if err != nil { 47 p.error(syntax.Error{Pos: syntax.MakePos(base, 0, 0), Msg: err.Error()}) 48 return 49 } 50 defer f.Close() 51 52 p.file, _ = syntax.Parse(base, f, p.error, p.pragma, syntax.CheckBranches) // errors are tracked via p.error 53 }(filename) 54 } 55 56 var lines uint 57 for _, p := range noders { 58 for e := range p.err { 59 p.yyerrorpos(e.Pos, "%s", e.Msg) 60 } 61 62 p.node() 63 lines += p.file.Lines 64 p.file = nil // release memory 65 66 if nsyntaxerrors != 0 { 67 errorexit() 68 } 69 // Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure. 70 testdclstack() 71 } 72 73 localpkg.Height = myheight 74 75 return lines 76 } 77 78 // makeSrcPosBase translates from a *syntax.PosBase to a *src.PosBase. 79 func (p *noder) makeSrcPosBase(b0 *syntax.PosBase) *src.PosBase { 80 // fast path: most likely PosBase hasn't changed 81 if p.basecache.last == b0 { 82 return p.basecache.base 83 } 84 85 b1, ok := p.basemap[b0] 86 if !ok { 87 fn := b0.Filename() 88 if b0.IsFileBase() { 89 b1 = src.NewFileBase(fn, absFilename(fn)) 90 } else { 91 // line directive base 92 p0 := b0.Pos() 93 p1 := src.MakePos(p.makeSrcPosBase(p0.Base()), p0.Line(), p0.Col()) 94 b1 = src.NewLinePragmaBase(p1, fn, fileh(fn), b0.Line(), b0.Col()) 95 } 96 p.basemap[b0] = b1 97 } 98 99 // update cache 100 p.basecache.last = b0 101 p.basecache.base = b1 102 103 return b1 104 } 105 106 func (p *noder) makeXPos(pos syntax.Pos) (_ src.XPos) { 107 return Ctxt.PosTable.XPos(src.MakePos(p.makeSrcPosBase(pos.Base()), pos.Line(), pos.Col())) 108 } 109 110 func (p *noder) yyerrorpos(pos syntax.Pos, format string, args ...interface{}) { 111 yyerrorl(p.makeXPos(pos), format, args...) 112 } 113 114 var pathPrefix string 115 116 // TODO(gri) Can we eliminate fileh in favor of absFilename? 117 func fileh(name string) string { 118 return objabi.AbsFile("", name, pathPrefix) 119 } 120 121 func absFilename(name string) string { 122 return objabi.AbsFile(Ctxt.Pathname, name, pathPrefix) 123 } 124 125 // noder transforms package syntax's AST into a Node tree. 126 type noder struct { 127 basemap map[*syntax.PosBase]*src.PosBase 128 basecache struct { 129 last *syntax.PosBase 130 base *src.PosBase 131 } 132 133 file *syntax.File 134 linknames []linkname 135 pragcgobuf [][]string 136 err chan syntax.Error 137 scope ScopeID 138 139 // scopeVars is a stack tracking the number of variables declared in the 140 // current function at the moment each open scope was opened. 141 scopeVars []int 142 143 lastCloseScopePos syntax.Pos 144 } 145 146 func (p *noder) funcBody(fn *Node, block *syntax.BlockStmt) { 147 oldScope := p.scope 148 p.scope = 0 149 funchdr(fn) 150 151 if block != nil { 152 body := p.stmts(block.List) 153 if body == nil { 154 body = []*Node{nod(OEMPTY, nil, nil)} 155 } 156 fn.Nbody.Set(body) 157 158 lineno = p.makeXPos(block.Rbrace) 159 fn.Func.Endlineno = lineno 160 } 161 162 funcbody() 163 p.scope = oldScope 164 } 165 166 func (p *noder) openScope(pos syntax.Pos) { 167 types.Markdcl() 168 169 if trackScopes { 170 Curfn.Func.Parents = append(Curfn.Func.Parents, p.scope) 171 p.scopeVars = append(p.scopeVars, len(Curfn.Func.Dcl)) 172 p.scope = ScopeID(len(Curfn.Func.Parents)) 173 174 p.markScope(pos) 175 } 176 } 177 178 func (p *noder) closeScope(pos syntax.Pos) { 179 p.lastCloseScopePos = pos 180 types.Popdcl() 181 182 if trackScopes { 183 scopeVars := p.scopeVars[len(p.scopeVars)-1] 184 p.scopeVars = p.scopeVars[:len(p.scopeVars)-1] 185 if scopeVars == len(Curfn.Func.Dcl) { 186 // no variables were declared in this scope, so we can retract it. 187 188 if int(p.scope) != len(Curfn.Func.Parents) { 189 Fatalf("scope tracking inconsistency, no variables declared but scopes were not retracted") 190 } 191 192 p.scope = Curfn.Func.Parents[p.scope-1] 193 Curfn.Func.Parents = Curfn.Func.Parents[:len(Curfn.Func.Parents)-1] 194 195 nmarks := len(Curfn.Func.Marks) 196 Curfn.Func.Marks[nmarks-1].Scope = p.scope 197 prevScope := ScopeID(0) 198 if nmarks >= 2 { 199 prevScope = Curfn.Func.Marks[nmarks-2].Scope 200 } 201 if Curfn.Func.Marks[nmarks-1].Scope == prevScope { 202 Curfn.Func.Marks = Curfn.Func.Marks[:nmarks-1] 203 } 204 return 205 } 206 207 p.scope = Curfn.Func.Parents[p.scope-1] 208 209 p.markScope(pos) 210 } 211 } 212 213 func (p *noder) markScope(pos syntax.Pos) { 214 xpos := p.makeXPos(pos) 215 if i := len(Curfn.Func.Marks); i > 0 && Curfn.Func.Marks[i-1].Pos == xpos { 216 Curfn.Func.Marks[i-1].Scope = p.scope 217 } else { 218 Curfn.Func.Marks = append(Curfn.Func.Marks, Mark{xpos, p.scope}) 219 } 220 } 221 222 // closeAnotherScope is like closeScope, but it reuses the same mark 223 // position as the last closeScope call. This is useful for "for" and 224 // "if" statements, as their implicit blocks always end at the same 225 // position as an explicit block. 226 func (p *noder) closeAnotherScope() { 227 p.closeScope(p.lastCloseScopePos) 228 } 229 230 // linkname records a //go:linkname directive. 231 type linkname struct { 232 pos syntax.Pos 233 local string 234 remote string 235 } 236 237 func (p *noder) node() { 238 types.Block = 1 239 imported_unsafe = false 240 241 p.setlineno(p.file.PkgName) 242 mkpackage(p.file.PkgName.Value) 243 244 xtop = append(xtop, p.decls(p.file.DeclList)...) 245 246 for _, n := range p.linknames { 247 if !imported_unsafe { 248 p.yyerrorpos(n.pos, "//go:linkname only allowed in Go files that import \"unsafe\"") 249 continue 250 } 251 s := lookup(n.local) 252 if n.remote != "" { 253 s.Linkname = n.remote 254 } else { 255 // Use the default object symbol name if the 256 // user didn't provide one. 257 if myimportpath == "" { 258 p.yyerrorpos(n.pos, "//go:linkname requires linkname argument or -p compiler flag") 259 } else { 260 s.Linkname = objabi.PathToPrefix(myimportpath) + "." + n.local 261 } 262 } 263 } 264 265 // The linker expects an ABI0 wrapper for all cgo-exported 266 // functions. 267 for _, prag := range p.pragcgobuf { 268 switch prag[0] { 269 case "cgo_export_static", "cgo_export_dynamic": 270 if symabiRefs == nil { 271 symabiRefs = make(map[string]obj.ABI) 272 } 273 symabiRefs[prag[1]] = obj.ABI0 274 } 275 } 276 277 pragcgobuf = append(pragcgobuf, p.pragcgobuf...) 278 lineno = src.NoXPos 279 clearImports() 280 } 281 282 func (p *noder) decls(decls []syntax.Decl) (l []*Node) { 283 var cs constState 284 285 for _, decl := range decls { 286 p.setlineno(decl) 287 switch decl := decl.(type) { 288 case *syntax.ImportDecl: 289 p.importDecl(decl) 290 291 case *syntax.VarDecl: 292 l = append(l, p.varDecl(decl)...) 293 294 case *syntax.ConstDecl: 295 l = append(l, p.constDecl(decl, &cs)...) 296 297 case *syntax.TypeDecl: 298 l = append(l, p.typeDecl(decl)) 299 300 case *syntax.FuncDecl: 301 l = append(l, p.funcDecl(decl)) 302 303 default: 304 panic("unhandled Decl") 305 } 306 } 307 308 return 309 } 310 311 func (p *noder) importDecl(imp *syntax.ImportDecl) { 312 if imp.Path.Bad { 313 return // avoid follow-on errors if there was a syntax error 314 } 315 316 val := p.basicLit(imp.Path) 317 ipkg := importfile(&val) 318 319 if ipkg == nil { 320 if nerrors == 0 { 321 Fatalf("phase error in import") 322 } 323 return 324 } 325 326 ipkg.Direct = true 327 328 var my *types.Sym 329 if imp.LocalPkgName != nil { 330 my = p.name(imp.LocalPkgName) 331 } else { 332 my = lookup(ipkg.Name) 333 } 334 335 pack := p.nod(imp, OPACK, nil, nil) 336 pack.Sym = my 337 pack.Name.Pkg = ipkg 338 339 switch my.Name { 340 case ".": 341 importdot(ipkg, pack) 342 return 343 case "init": 344 yyerrorl(pack.Pos, "cannot import package as init - init must be a func") 345 return 346 case "_": 347 return 348 } 349 if my.Def != nil { 350 redeclare(pack.Pos, my, "as imported package name") 351 } 352 my.Def = asTypesNode(pack) 353 my.Lastlineno = pack.Pos 354 my.Block = 1 // at top level 355 } 356 357 func (p *noder) varDecl(decl *syntax.VarDecl) []*Node { 358 names := p.declNames(decl.NameList) 359 typ := p.typeExprOrNil(decl.Type) 360 361 var exprs []*Node 362 if decl.Values != nil { 363 exprs = p.exprList(decl.Values) 364 } 365 366 p.setlineno(decl) 367 return variter(names, typ, exprs) 368 } 369 370 // constState tracks state between constant specifiers within a 371 // declaration group. This state is kept separate from noder so nested 372 // constant declarations are handled correctly (e.g., issue 15550). 373 type constState struct { 374 group *syntax.Group 375 typ *Node 376 values []*Node 377 iota int64 378 } 379 380 func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []*Node { 381 if decl.Group == nil || decl.Group != cs.group { 382 *cs = constState{ 383 group: decl.Group, 384 } 385 } 386 387 names := p.declNames(decl.NameList) 388 typ := p.typeExprOrNil(decl.Type) 389 390 var values []*Node 391 if decl.Values != nil { 392 values = p.exprList(decl.Values) 393 cs.typ, cs.values = typ, values 394 } else { 395 if typ != nil { 396 yyerror("const declaration cannot have type without expression") 397 } 398 typ, values = cs.typ, cs.values 399 } 400 401 nn := make([]*Node, 0, len(names)) 402 for i, n := range names { 403 if i >= len(values) { 404 yyerror("missing value in const declaration") 405 break 406 } 407 v := values[i] 408 if decl.Values == nil { 409 v = treecopy(v, n.Pos) 410 } 411 412 n.Op = OLITERAL 413 declare(n, dclcontext) 414 415 n.Name.Param.Ntype = typ 416 n.Name.Defn = v 417 n.SetIota(cs.iota) 418 419 nn = append(nn, p.nod(decl, ODCLCONST, n, nil)) 420 } 421 422 if len(values) > len(names) { 423 yyerror("extra expression in const declaration") 424 } 425 426 cs.iota++ 427 428 return nn 429 } 430 431 func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node { 432 n := p.declName(decl.Name) 433 n.Op = OTYPE 434 declare(n, dclcontext) 435 436 // decl.Type may be nil but in that case we got a syntax error during parsing 437 typ := p.typeExprOrNil(decl.Type) 438 439 param := n.Name.Param 440 param.Ntype = typ 441 param.Pragma = decl.Pragma 442 param.Alias = decl.Alias 443 if param.Alias && param.Pragma != 0 { 444 yyerror("cannot specify directive with type alias") 445 param.Pragma = 0 446 } 447 448 nod := p.nod(decl, ODCLTYPE, n, nil) 449 if param.Alias && !langSupported(1, 9, localpkg) { 450 yyerrorl(nod.Pos, "type aliases only supported as of -lang=go1.9") 451 } 452 return nod 453 } 454 455 func (p *noder) declNames(names []*syntax.Name) []*Node { 456 nodes := make([]*Node, 0, len(names)) 457 for _, name := range names { 458 nodes = append(nodes, p.declName(name)) 459 } 460 return nodes 461 } 462 463 func (p *noder) declName(name *syntax.Name) *Node { 464 n := dclname(p.name(name)) 465 n.Pos = p.pos(name) 466 return n 467 } 468 469 func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node { 470 name := p.name(fun.Name) 471 t := p.signature(fun.Recv, fun.Type) 472 f := p.nod(fun, ODCLFUNC, nil, nil) 473 474 if fun.Recv == nil { 475 if name.Name == "init" { 476 name = renameinit() 477 if t.List.Len() > 0 || t.Rlist.Len() > 0 { 478 yyerrorl(f.Pos, "func init must have no arguments and no return values") 479 } 480 } 481 482 if localpkg.Name == "main" && name.Name == "main" { 483 if t.List.Len() > 0 || t.Rlist.Len() > 0 { 484 yyerrorl(f.Pos, "func main must have no arguments and no return values") 485 } 486 } 487 } else { 488 f.Func.Shortname = name 489 name = nblank.Sym // filled in by typecheckfunc 490 } 491 492 f.Func.Nname = newfuncnamel(p.pos(fun.Name), name) 493 f.Func.Nname.Name.Defn = f 494 f.Func.Nname.Name.Param.Ntype = t 495 496 pragma := fun.Pragma 497 f.Func.Pragma = fun.Pragma 498 if pragma&Systemstack != 0 && pragma&Nosplit != 0 { 499 yyerrorl(f.Pos, "go:nosplit and go:systemstack cannot be combined") 500 } 501 502 if fun.Recv == nil { 503 declare(f.Func.Nname, PFUNC) 504 } 505 506 p.funcBody(f, fun.Body) 507 508 if fun.Body != nil { 509 if f.Func.Pragma&Noescape != 0 { 510 yyerrorl(f.Pos, "can only use //go:noescape with external func implementations") 511 } 512 } else { 513 if pure_go || strings.HasPrefix(f.funcname(), "init.") { 514 // Linknamed functions are allowed to have no body. Hopefully 515 // the linkname target has a body. See issue 23311. 516 isLinknamed := false 517 for _, n := range p.linknames { 518 if f.funcname() == n.local { 519 isLinknamed = true 520 break 521 } 522 } 523 if !isLinknamed { 524 yyerrorl(f.Pos, "missing function body") 525 } 526 } 527 } 528 529 return f 530 } 531 532 func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *Node { 533 n := p.nod(typ, OTFUNC, nil, nil) 534 if recv != nil { 535 n.Left = p.param(recv, false, false) 536 } 537 n.List.Set(p.params(typ.ParamList, true)) 538 n.Rlist.Set(p.params(typ.ResultList, false)) 539 return n 540 } 541 542 func (p *noder) params(params []*syntax.Field, dddOk bool) []*Node { 543 nodes := make([]*Node, 0, len(params)) 544 for i, param := range params { 545 p.setlineno(param) 546 nodes = append(nodes, p.param(param, dddOk, i+1 == len(params))) 547 } 548 return nodes 549 } 550 551 func (p *noder) param(param *syntax.Field, dddOk, final bool) *Node { 552 var name *types.Sym 553 if param.Name != nil { 554 name = p.name(param.Name) 555 } 556 557 typ := p.typeExpr(param.Type) 558 n := p.nodSym(param, ODCLFIELD, typ, name) 559 560 // rewrite ...T parameter 561 if typ.Op == ODDD { 562 if !dddOk { 563 // We mark these as syntax errors to get automatic elimination 564 // of multiple such errors per line (see yyerrorl in subr.go). 565 yyerror("syntax error: cannot use ... in receiver or result parameter list") 566 } else if !final { 567 if param.Name == nil { 568 yyerror("syntax error: cannot use ... with non-final parameter") 569 } else { 570 p.yyerrorpos(param.Name.Pos(), "syntax error: cannot use ... with non-final parameter %s", param.Name.Value) 571 } 572 } 573 typ.Op = OTARRAY 574 typ.Right = typ.Left 575 typ.Left = nil 576 n.SetIsDDD(true) 577 if n.Left != nil { 578 n.Left.SetIsDDD(true) 579 } 580 } 581 582 return n 583 } 584 585 func (p *noder) exprList(expr syntax.Expr) []*Node { 586 if list, ok := expr.(*syntax.ListExpr); ok { 587 return p.exprs(list.ElemList) 588 } 589 return []*Node{p.expr(expr)} 590 } 591 592 func (p *noder) exprs(exprs []syntax.Expr) []*Node { 593 nodes := make([]*Node, 0, len(exprs)) 594 for _, expr := range exprs { 595 nodes = append(nodes, p.expr(expr)) 596 } 597 return nodes 598 } 599 600 func (p *noder) expr(expr syntax.Expr) *Node { 601 p.setlineno(expr) 602 switch expr := expr.(type) { 603 case nil, *syntax.BadExpr: 604 return nil 605 case *syntax.Name: 606 return p.mkname(expr) 607 case *syntax.BasicLit: 608 n := nodlit(p.basicLit(expr)) 609 n.SetDiag(expr.Bad) // avoid follow-on errors if there was a syntax error 610 return n 611 case *syntax.CompositeLit: 612 n := p.nod(expr, OCOMPLIT, nil, nil) 613 if expr.Type != nil { 614 n.Right = p.expr(expr.Type) 615 } 616 l := p.exprs(expr.ElemList) 617 for i, e := range l { 618 l[i] = p.wrapname(expr.ElemList[i], e) 619 } 620 n.List.Set(l) 621 lineno = p.makeXPos(expr.Rbrace) 622 return n 623 case *syntax.KeyValueExpr: 624 // use position of expr.Key rather than of expr (which has position of ':') 625 return p.nod(expr.Key, OKEY, p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value))) 626 case *syntax.FuncLit: 627 return p.funcLit(expr) 628 case *syntax.ParenExpr: 629 return p.nod(expr, OPAREN, p.expr(expr.X), nil) 630 case *syntax.SelectorExpr: 631 // parser.new_dotname 632 obj := p.expr(expr.X) 633 if obj.Op == OPACK { 634 obj.Name.SetUsed(true) 635 return oldname(restrictlookup(expr.Sel.Value, obj.Name.Pkg)) 636 } 637 n := nodSym(OXDOT, obj, p.name(expr.Sel)) 638 n.Pos = p.pos(expr) // lineno may have been changed by p.expr(expr.X) 639 return n 640 case *syntax.IndexExpr: 641 return p.nod(expr, OINDEX, p.expr(expr.X), p.expr(expr.Index)) 642 case *syntax.SliceExpr: 643 op := OSLICE 644 if expr.Full { 645 op = OSLICE3 646 } 647 n := p.nod(expr, op, p.expr(expr.X), nil) 648 var index [3]*Node 649 for i, x := range expr.Index { 650 if x != nil { 651 index[i] = p.expr(x) 652 } 653 } 654 n.SetSliceBounds(index[0], index[1], index[2]) 655 return n 656 case *syntax.AssertExpr: 657 return p.nod(expr, ODOTTYPE, p.expr(expr.X), p.typeExpr(expr.Type)) 658 case *syntax.Operation: 659 if expr.Op == syntax.Add && expr.Y != nil { 660 return p.sum(expr) 661 } 662 x := p.expr(expr.X) 663 if expr.Y == nil { 664 return p.nod(expr, p.unOp(expr.Op), x, nil) 665 } 666 return p.nod(expr, p.binOp(expr.Op), x, p.expr(expr.Y)) 667 case *syntax.CallExpr: 668 n := p.nod(expr, OCALL, p.expr(expr.Fun), nil) 669 n.List.Set(p.exprs(expr.ArgList)) 670 n.SetIsDDD(expr.HasDots) 671 return n 672 673 case *syntax.ArrayType: 674 var len *Node 675 if expr.Len != nil { 676 len = p.expr(expr.Len) 677 } else { 678 len = p.nod(expr, ODDD, nil, nil) 679 } 680 return p.nod(expr, OTARRAY, len, p.typeExpr(expr.Elem)) 681 case *syntax.SliceType: 682 return p.nod(expr, OTARRAY, nil, p.typeExpr(expr.Elem)) 683 case *syntax.DotsType: 684 return p.nod(expr, ODDD, p.typeExpr(expr.Elem), nil) 685 case *syntax.StructType: 686 return p.structType(expr) 687 case *syntax.InterfaceType: 688 return p.interfaceType(expr) 689 case *syntax.FuncType: 690 return p.signature(nil, expr) 691 case *syntax.MapType: 692 return p.nod(expr, OTMAP, p.typeExpr(expr.Key), p.typeExpr(expr.Value)) 693 case *syntax.ChanType: 694 n := p.nod(expr, OTCHAN, p.typeExpr(expr.Elem), nil) 695 n.SetTChanDir(p.chanDir(expr.Dir)) 696 return n 697 698 case *syntax.TypeSwitchGuard: 699 n := p.nod(expr, OTYPESW, nil, p.expr(expr.X)) 700 if expr.Lhs != nil { 701 n.Left = p.declName(expr.Lhs) 702 if n.Left.isBlank() { 703 yyerror("invalid variable name %v in type switch", n.Left) 704 } 705 } 706 return n 707 } 708 panic("unhandled Expr") 709 } 710 711 // sum efficiently handles very large summation expressions (such as 712 // in issue #16394). In particular, it avoids left recursion and 713 // collapses string literals. 714 func (p *noder) sum(x syntax.Expr) *Node { 715 // While we need to handle long sums with asymptotic 716 // efficiency, the vast majority of sums are very small: ~95% 717 // have only 2 or 3 operands, and ~99% of string literals are 718 // never concatenated. 719 720 adds := make([]*syntax.Operation, 0, 2) 721 for { 722 add, ok := x.(*syntax.Operation) 723 if !ok || add.Op != syntax.Add || add.Y == nil { 724 break 725 } 726 adds = append(adds, add) 727 x = add.X 728 } 729 730 // nstr is the current rightmost string literal in the 731 // summation (if any), and chunks holds its accumulated 732 // substrings. 733 // 734 // Consider the expression x + "a" + "b" + "c" + y. When we 735 // reach the string literal "a", we assign nstr to point to 736 // its corresponding Node and initialize chunks to {"a"}. 737 // Visiting the subsequent string literals "b" and "c", we 738 // simply append their values to chunks. Finally, when we 739 // reach the non-constant operand y, we'll join chunks to form 740 // "abc" and reassign the "a" string literal's value. 741 // 742 // N.B., we need to be careful about named string constants 743 // (indicated by Sym != nil) because 1) we can't modify their 744 // value, as doing so would affect other uses of the string 745 // constant, and 2) they may have types, which we need to 746 // handle correctly. For now, we avoid these problems by 747 // treating named string constants the same as non-constant 748 // operands. 749 var nstr *Node 750 chunks := make([]string, 0, 1) 751 752 n := p.expr(x) 753 if Isconst(n, CTSTR) && n.Sym == nil { 754 nstr = n 755 chunks = append(chunks, strlit(nstr)) 756 } 757 758 for i := len(adds) - 1; i >= 0; i-- { 759 add := adds[i] 760 761 r := p.expr(add.Y) 762 if Isconst(r, CTSTR) && r.Sym == nil { 763 if nstr != nil { 764 // Collapse r into nstr instead of adding to n. 765 chunks = append(chunks, strlit(r)) 766 continue 767 } 768 769 nstr = r 770 chunks = append(chunks, strlit(nstr)) 771 } else { 772 if len(chunks) > 1 { 773 nstr.SetVal(Val{U: strings.Join(chunks, "")}) 774 } 775 nstr = nil 776 chunks = chunks[:0] 777 } 778 n = p.nod(add, OADD, n, r) 779 } 780 if len(chunks) > 1 { 781 nstr.SetVal(Val{U: strings.Join(chunks, "")}) 782 } 783 784 return n 785 } 786 787 func (p *noder) typeExpr(typ syntax.Expr) *Node { 788 // TODO(mdempsky): Be stricter? typecheck should handle errors anyway. 789 return p.expr(typ) 790 } 791 792 func (p *noder) typeExprOrNil(typ syntax.Expr) *Node { 793 if typ != nil { 794 return p.expr(typ) 795 } 796 return nil 797 } 798 799 func (p *noder) chanDir(dir syntax.ChanDir) types.ChanDir { 800 switch dir { 801 case 0: 802 return types.Cboth 803 case syntax.SendOnly: 804 return types.Csend 805 case syntax.RecvOnly: 806 return types.Crecv 807 } 808 panic("unhandled ChanDir") 809 } 810 811 func (p *noder) structType(expr *syntax.StructType) *Node { 812 l := make([]*Node, 0, len(expr.FieldList)) 813 for i, field := range expr.FieldList { 814 p.setlineno(field) 815 var n *Node 816 if field.Name == nil { 817 n = p.embedded(field.Type) 818 } else { 819 n = p.nodSym(field, ODCLFIELD, p.typeExpr(field.Type), p.name(field.Name)) 820 } 821 if i < len(expr.TagList) && expr.TagList[i] != nil { 822 n.SetVal(p.basicLit(expr.TagList[i])) 823 } 824 l = append(l, n) 825 } 826 827 p.setlineno(expr) 828 n := p.nod(expr, OTSTRUCT, nil, nil) 829 n.List.Set(l) 830 return n 831 } 832 833 func (p *noder) interfaceType(expr *syntax.InterfaceType) *Node { 834 l := make([]*Node, 0, len(expr.MethodList)) 835 for _, method := range expr.MethodList { 836 p.setlineno(method) 837 var n *Node 838 if method.Name == nil { 839 n = p.nodSym(method, ODCLFIELD, oldname(p.packname(method.Type)), nil) 840 } else { 841 mname := p.name(method.Name) 842 sig := p.typeExpr(method.Type) 843 sig.Left = fakeRecv() 844 n = p.nodSym(method, ODCLFIELD, sig, mname) 845 ifacedcl(n) 846 } 847 l = append(l, n) 848 } 849 850 n := p.nod(expr, OTINTER, nil, nil) 851 n.List.Set(l) 852 return n 853 } 854 855 func (p *noder) packname(expr syntax.Expr) *types.Sym { 856 switch expr := expr.(type) { 857 case *syntax.Name: 858 name := p.name(expr) 859 if n := oldname(name); n.Name != nil && n.Name.Pack != nil { 860 n.Name.Pack.Name.SetUsed(true) 861 } 862 return name 863 case *syntax.SelectorExpr: 864 name := p.name(expr.X.(*syntax.Name)) 865 def := asNode(name.Def) 866 if def == nil { 867 yyerror("undefined: %v", name) 868 return name 869 } 870 var pkg *types.Pkg 871 if def.Op != OPACK { 872 yyerror("%v is not a package", name) 873 pkg = localpkg 874 } else { 875 def.Name.SetUsed(true) 876 pkg = def.Name.Pkg 877 } 878 return restrictlookup(expr.Sel.Value, pkg) 879 } 880 panic(fmt.Sprintf("unexpected packname: %#v", expr)) 881 } 882 883 func (p *noder) embedded(typ syntax.Expr) *Node { 884 op, isStar := typ.(*syntax.Operation) 885 if isStar { 886 if op.Op != syntax.Mul || op.Y != nil { 887 panic("unexpected Operation") 888 } 889 typ = op.X 890 } 891 892 sym := p.packname(typ) 893 n := p.nodSym(typ, ODCLFIELD, oldname(sym), lookup(sym.Name)) 894 n.SetEmbedded(true) 895 896 if isStar { 897 n.Left = p.nod(op, ODEREF, n.Left, nil) 898 } 899 return n 900 } 901 902 func (p *noder) stmts(stmts []syntax.Stmt) []*Node { 903 return p.stmtsFall(stmts, false) 904 } 905 906 func (p *noder) stmtsFall(stmts []syntax.Stmt, fallOK bool) []*Node { 907 var nodes []*Node 908 for i, stmt := range stmts { 909 s := p.stmtFall(stmt, fallOK && i+1 == len(stmts)) 910 if s == nil { 911 } else if s.Op == OBLOCK && s.Ninit.Len() == 0 { 912 nodes = append(nodes, s.List.Slice()...) 913 } else { 914 nodes = append(nodes, s) 915 } 916 } 917 return nodes 918 } 919 920 func (p *noder) stmt(stmt syntax.Stmt) *Node { 921 return p.stmtFall(stmt, false) 922 } 923 924 func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) *Node { 925 p.setlineno(stmt) 926 switch stmt := stmt.(type) { 927 case *syntax.EmptyStmt: 928 return nil 929 case *syntax.LabeledStmt: 930 return p.labeledStmt(stmt, fallOK) 931 case *syntax.BlockStmt: 932 l := p.blockStmt(stmt) 933 if len(l) == 0 { 934 // TODO(mdempsky): Line number? 935 return nod(OEMPTY, nil, nil) 936 } 937 return liststmt(l) 938 case *syntax.ExprStmt: 939 return p.wrapname(stmt, p.expr(stmt.X)) 940 case *syntax.SendStmt: 941 return p.nod(stmt, OSEND, p.expr(stmt.Chan), p.expr(stmt.Value)) 942 case *syntax.DeclStmt: 943 return liststmt(p.decls(stmt.DeclList)) 944 case *syntax.AssignStmt: 945 if stmt.Op != 0 && stmt.Op != syntax.Def { 946 n := p.nod(stmt, OASOP, p.expr(stmt.Lhs), p.expr(stmt.Rhs)) 947 n.SetImplicit(stmt.Rhs == syntax.ImplicitOne) 948 n.SetSubOp(p.binOp(stmt.Op)) 949 return n 950 } 951 952 n := p.nod(stmt, OAS, nil, nil) // assume common case 953 954 rhs := p.exprList(stmt.Rhs) 955 lhs := p.assignList(stmt.Lhs, n, stmt.Op == syntax.Def) 956 957 if len(lhs) == 1 && len(rhs) == 1 { 958 // common case 959 n.Left = lhs[0] 960 n.Right = rhs[0] 961 } else { 962 n.Op = OAS2 963 n.List.Set(lhs) 964 n.Rlist.Set(rhs) 965 } 966 return n 967 968 case *syntax.BranchStmt: 969 var op Op 970 switch stmt.Tok { 971 case syntax.Break: 972 op = OBREAK 973 case syntax.Continue: 974 op = OCONTINUE 975 case syntax.Fallthrough: 976 if !fallOK { 977 yyerror("fallthrough statement out of place") 978 } 979 op = OFALL 980 case syntax.Goto: 981 op = OGOTO 982 default: 983 panic("unhandled BranchStmt") 984 } 985 n := p.nod(stmt, op, nil, nil) 986 if stmt.Label != nil { 987 n.Sym = p.name(stmt.Label) 988 } 989 return n 990 case *syntax.CallStmt: 991 var op Op 992 switch stmt.Tok { 993 case syntax.Defer: 994 op = ODEFER 995 case syntax.Go: 996 op = OGO 997 default: 998 panic("unhandled CallStmt") 999 } 1000 return p.nod(stmt, op, p.expr(stmt.Call), nil) 1001 case *syntax.ReturnStmt: 1002 var results []*Node 1003 if stmt.Results != nil { 1004 results = p.exprList(stmt.Results) 1005 } 1006 n := p.nod(stmt, ORETURN, nil, nil) 1007 n.List.Set(results) 1008 if n.List.Len() == 0 && Curfn != nil { 1009 for _, ln := range Curfn.Func.Dcl { 1010 if ln.Class() == PPARAM { 1011 continue 1012 } 1013 if ln.Class() != PPARAMOUT { 1014 break 1015 } 1016 if asNode(ln.Sym.Def) != ln { 1017 yyerror("%s is shadowed during return", ln.Sym.Name) 1018 } 1019 } 1020 } 1021 return n 1022 case *syntax.IfStmt: 1023 return p.ifStmt(stmt) 1024 case *syntax.ForStmt: 1025 return p.forStmt(stmt) 1026 case *syntax.SwitchStmt: 1027 return p.switchStmt(stmt) 1028 case *syntax.SelectStmt: 1029 return p.selectStmt(stmt) 1030 } 1031 panic("unhandled Stmt") 1032 } 1033 1034 func (p *noder) assignList(expr syntax.Expr, defn *Node, colas bool) []*Node { 1035 if !colas { 1036 return p.exprList(expr) 1037 } 1038 1039 defn.SetColas(true) 1040 1041 var exprs []syntax.Expr 1042 if list, ok := expr.(*syntax.ListExpr); ok { 1043 exprs = list.ElemList 1044 } else { 1045 exprs = []syntax.Expr{expr} 1046 } 1047 1048 res := make([]*Node, len(exprs)) 1049 seen := make(map[*types.Sym]bool, len(exprs)) 1050 1051 newOrErr := false 1052 for i, expr := range exprs { 1053 p.setlineno(expr) 1054 res[i] = nblank 1055 1056 name, ok := expr.(*syntax.Name) 1057 if !ok { 1058 p.yyerrorpos(expr.Pos(), "non-name %v on left side of :=", p.expr(expr)) 1059 newOrErr = true 1060 continue 1061 } 1062 1063 sym := p.name(name) 1064 if sym.IsBlank() { 1065 continue 1066 } 1067 1068 if seen[sym] { 1069 p.yyerrorpos(expr.Pos(), "%v repeated on left side of :=", sym) 1070 newOrErr = true 1071 continue 1072 } 1073 seen[sym] = true 1074 1075 if sym.Block == types.Block { 1076 res[i] = oldname(sym) 1077 continue 1078 } 1079 1080 newOrErr = true 1081 n := newname(sym) 1082 declare(n, dclcontext) 1083 n.Name.Defn = defn 1084 defn.Ninit.Append(nod(ODCL, n, nil)) 1085 res[i] = n 1086 } 1087 1088 if !newOrErr { 1089 yyerrorl(defn.Pos, "no new variables on left side of :=") 1090 } 1091 return res 1092 } 1093 1094 func (p *noder) blockStmt(stmt *syntax.BlockStmt) []*Node { 1095 p.openScope(stmt.Pos()) 1096 nodes := p.stmts(stmt.List) 1097 p.closeScope(stmt.Rbrace) 1098 return nodes 1099 } 1100 1101 func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node { 1102 p.openScope(stmt.Pos()) 1103 n := p.nod(stmt, OIF, nil, nil) 1104 if stmt.Init != nil { 1105 n.Ninit.Set1(p.stmt(stmt.Init)) 1106 } 1107 if stmt.Cond != nil { 1108 n.Left = p.expr(stmt.Cond) 1109 } 1110 n.Nbody.Set(p.blockStmt(stmt.Then)) 1111 if stmt.Else != nil { 1112 e := p.stmt(stmt.Else) 1113 if e.Op == OBLOCK && e.Ninit.Len() == 0 { 1114 n.Rlist.Set(e.List.Slice()) 1115 } else { 1116 n.Rlist.Set1(e) 1117 } 1118 } 1119 p.closeAnotherScope() 1120 return n 1121 } 1122 1123 func (p *noder) forStmt(stmt *syntax.ForStmt) *Node { 1124 p.openScope(stmt.Pos()) 1125 var n *Node 1126 if r, ok := stmt.Init.(*syntax.RangeClause); ok { 1127 if stmt.Cond != nil || stmt.Post != nil { 1128 panic("unexpected RangeClause") 1129 } 1130 1131 n = p.nod(r, ORANGE, nil, p.expr(r.X)) 1132 if r.Lhs != nil { 1133 n.List.Set(p.assignList(r.Lhs, n, r.Def)) 1134 } 1135 } else { 1136 n = p.nod(stmt, OFOR, nil, nil) 1137 if stmt.Init != nil { 1138 n.Ninit.Set1(p.stmt(stmt.Init)) 1139 } 1140 if stmt.Cond != nil { 1141 n.Left = p.expr(stmt.Cond) 1142 } 1143 if stmt.Post != nil { 1144 n.Right = p.stmt(stmt.Post) 1145 } 1146 } 1147 n.Nbody.Set(p.blockStmt(stmt.Body)) 1148 p.closeAnotherScope() 1149 return n 1150 } 1151 1152 func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node { 1153 p.openScope(stmt.Pos()) 1154 n := p.nod(stmt, OSWITCH, nil, nil) 1155 if stmt.Init != nil { 1156 n.Ninit.Set1(p.stmt(stmt.Init)) 1157 } 1158 if stmt.Tag != nil { 1159 n.Left = p.expr(stmt.Tag) 1160 } 1161 1162 tswitch := n.Left 1163 if tswitch != nil && tswitch.Op != OTYPESW { 1164 tswitch = nil 1165 } 1166 n.List.Set(p.caseClauses(stmt.Body, tswitch, stmt.Rbrace)) 1167 1168 p.closeScope(stmt.Rbrace) 1169 return n 1170 } 1171 1172 func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node, rbrace syntax.Pos) []*Node { 1173 nodes := make([]*Node, 0, len(clauses)) 1174 for i, clause := range clauses { 1175 p.setlineno(clause) 1176 if i > 0 { 1177 p.closeScope(clause.Pos()) 1178 } 1179 p.openScope(clause.Pos()) 1180 1181 n := p.nod(clause, OCASE, nil, nil) 1182 if clause.Cases != nil { 1183 n.List.Set(p.exprList(clause.Cases)) 1184 } 1185 if tswitch != nil && tswitch.Left != nil { 1186 nn := newname(tswitch.Left.Sym) 1187 declare(nn, dclcontext) 1188 n.Rlist.Set1(nn) 1189 // keep track of the instances for reporting unused 1190 nn.Name.Defn = tswitch 1191 } 1192 1193 // Trim trailing empty statements. We omit them from 1194 // the Node AST anyway, and it's easier to identify 1195 // out-of-place fallthrough statements without them. 1196 body := clause.Body 1197 for len(body) > 0 { 1198 if _, ok := body[len(body)-1].(*syntax.EmptyStmt); !ok { 1199 break 1200 } 1201 body = body[:len(body)-1] 1202 } 1203 1204 n.Nbody.Set(p.stmtsFall(body, true)) 1205 if l := n.Nbody.Len(); l > 0 && n.Nbody.Index(l-1).Op == OFALL { 1206 if tswitch != nil { 1207 yyerror("cannot fallthrough in type switch") 1208 } 1209 if i+1 == len(clauses) { 1210 yyerror("cannot fallthrough final case in switch") 1211 } 1212 } 1213 1214 nodes = append(nodes, n) 1215 } 1216 if len(clauses) > 0 { 1217 p.closeScope(rbrace) 1218 } 1219 return nodes 1220 } 1221 1222 func (p *noder) selectStmt(stmt *syntax.SelectStmt) *Node { 1223 n := p.nod(stmt, OSELECT, nil, nil) 1224 n.List.Set(p.commClauses(stmt.Body, stmt.Rbrace)) 1225 return n 1226 } 1227 1228 func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*Node { 1229 nodes := make([]*Node, 0, len(clauses)) 1230 for i, clause := range clauses { 1231 p.setlineno(clause) 1232 if i > 0 { 1233 p.closeScope(clause.Pos()) 1234 } 1235 p.openScope(clause.Pos()) 1236 1237 n := p.nod(clause, OCASE, nil, nil) 1238 if clause.Comm != nil { 1239 n.List.Set1(p.stmt(clause.Comm)) 1240 } 1241 n.Nbody.Set(p.stmts(clause.Body)) 1242 nodes = append(nodes, n) 1243 } 1244 if len(clauses) > 0 { 1245 p.closeScope(rbrace) 1246 } 1247 return nodes 1248 } 1249 1250 func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) *Node { 1251 lhs := p.nodSym(label, OLABEL, nil, p.name(label.Label)) 1252 1253 var ls *Node 1254 if label.Stmt != nil { // TODO(mdempsky): Should always be present. 1255 ls = p.stmtFall(label.Stmt, fallOK) 1256 } 1257 1258 lhs.Name.Defn = ls 1259 l := []*Node{lhs} 1260 if ls != nil { 1261 if ls.Op == OBLOCK && ls.Ninit.Len() == 0 { 1262 l = append(l, ls.List.Slice()...) 1263 } else { 1264 l = append(l, ls) 1265 } 1266 } 1267 return liststmt(l) 1268 } 1269 1270 var unOps = [...]Op{ 1271 syntax.Recv: ORECV, 1272 syntax.Mul: ODEREF, 1273 syntax.And: OADDR, 1274 1275 syntax.Not: ONOT, 1276 syntax.Xor: OBITNOT, 1277 syntax.Add: OPLUS, 1278 syntax.Sub: ONEG, 1279 } 1280 1281 func (p *noder) unOp(op syntax.Operator) Op { 1282 if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 { 1283 panic("invalid Operator") 1284 } 1285 return unOps[op] 1286 } 1287 1288 var binOps = [...]Op{ 1289 syntax.OrOr: OOROR, 1290 syntax.AndAnd: OANDAND, 1291 1292 syntax.Eql: OEQ, 1293 syntax.Neq: ONE, 1294 syntax.Lss: OLT, 1295 syntax.Leq: OLE, 1296 syntax.Gtr: OGT, 1297 syntax.Geq: OGE, 1298 1299 syntax.Add: OADD, 1300 syntax.Sub: OSUB, 1301 syntax.Or: OOR, 1302 syntax.Xor: OXOR, 1303 1304 syntax.Mul: OMUL, 1305 syntax.Div: ODIV, 1306 syntax.Rem: OMOD, 1307 syntax.And: OAND, 1308 syntax.AndNot: OANDNOT, 1309 syntax.Shl: OLSH, 1310 syntax.Shr: ORSH, 1311 } 1312 1313 func (p *noder) binOp(op syntax.Operator) Op { 1314 if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 { 1315 panic("invalid Operator") 1316 } 1317 return binOps[op] 1318 } 1319 1320 // checkLangCompat reports an error if the representation of a numeric 1321 // literal is not compatible with the current language version. 1322 func checkLangCompat(lit *syntax.BasicLit) { 1323 s := lit.Value 1324 if len(s) <= 2 || langSupported(1, 13, localpkg) { 1325 return 1326 } 1327 // len(s) > 2 1328 if strings.Contains(s, "_") { 1329 yyerrorv("go1.13", "underscores in numeric literals") 1330 return 1331 } 1332 if s[0] != '0' { 1333 return 1334 } 1335 base := s[1] 1336 if base == 'b' || base == 'B' { 1337 yyerrorv("go1.13", "binary literals") 1338 return 1339 } 1340 if base == 'o' || base == 'O' { 1341 yyerrorv("go1.13", "0o/0O-style octal literals") 1342 return 1343 } 1344 if lit.Kind != syntax.IntLit && (base == 'x' || base == 'X') { 1345 yyerrorv("go1.13", "hexadecimal floating-point literals") 1346 } 1347 } 1348 1349 func (p *noder) basicLit(lit *syntax.BasicLit) Val { 1350 // We don't use the errors of the conversion routines to determine 1351 // if a literal string is valid because the conversion routines may 1352 // accept a wider syntax than the language permits. Rely on lit.Bad 1353 // instead. 1354 switch s := lit.Value; lit.Kind { 1355 case syntax.IntLit: 1356 checkLangCompat(lit) 1357 x := new(Mpint) 1358 if !lit.Bad { 1359 x.SetString(s) 1360 } 1361 return Val{U: x} 1362 1363 case syntax.FloatLit: 1364 checkLangCompat(lit) 1365 x := newMpflt() 1366 if !lit.Bad { 1367 x.SetString(s) 1368 } 1369 return Val{U: x} 1370 1371 case syntax.ImagLit: 1372 checkLangCompat(lit) 1373 x := newMpcmplx() 1374 if !lit.Bad { 1375 x.Imag.SetString(strings.TrimSuffix(s, "i")) 1376 } 1377 return Val{U: x} 1378 1379 case syntax.RuneLit: 1380 x := new(Mpint) 1381 x.Rune = true 1382 if !lit.Bad { 1383 u, _ := strconv.Unquote(s) 1384 var r rune 1385 if len(u) == 1 { 1386 r = rune(u[0]) 1387 } else { 1388 r, _ = utf8.DecodeRuneInString(u) 1389 } 1390 x.SetInt64(int64(r)) 1391 } 1392 return Val{U: x} 1393 1394 case syntax.StringLit: 1395 var x string 1396 if !lit.Bad { 1397 if len(s) > 0 && s[0] == '`' { 1398 // strip carriage returns from raw string 1399 s = strings.Replace(s, "\r", "", -1) 1400 } 1401 x, _ = strconv.Unquote(s) 1402 } 1403 return Val{U: x} 1404 1405 default: 1406 panic("unhandled BasicLit kind") 1407 } 1408 } 1409 1410 func (p *noder) name(name *syntax.Name) *types.Sym { 1411 return lookup(name.Value) 1412 } 1413 1414 func (p *noder) mkname(name *syntax.Name) *Node { 1415 // TODO(mdempsky): Set line number? 1416 return mkname(p.name(name)) 1417 } 1418 1419 func (p *noder) newname(name *syntax.Name) *Node { 1420 // TODO(mdempsky): Set line number? 1421 return newname(p.name(name)) 1422 } 1423 1424 func (p *noder) wrapname(n syntax.Node, x *Node) *Node { 1425 // These nodes do not carry line numbers. 1426 // Introduce a wrapper node to give them the correct line. 1427 switch x.Op { 1428 case OTYPE, OLITERAL: 1429 if x.Sym == nil { 1430 break 1431 } 1432 fallthrough 1433 case ONAME, ONONAME, OPACK: 1434 x = p.nod(n, OPAREN, x, nil) 1435 x.SetImplicit(true) 1436 } 1437 return x 1438 } 1439 1440 func (p *noder) nod(orig syntax.Node, op Op, left, right *Node) *Node { 1441 return nodl(p.pos(orig), op, left, right) 1442 } 1443 1444 func (p *noder) nodSym(orig syntax.Node, op Op, left *Node, sym *types.Sym) *Node { 1445 n := nodSym(op, left, sym) 1446 n.Pos = p.pos(orig) 1447 return n 1448 } 1449 1450 func (p *noder) pos(n syntax.Node) src.XPos { 1451 // TODO(gri): orig.Pos() should always be known - fix package syntax 1452 xpos := lineno 1453 if pos := n.Pos(); pos.IsKnown() { 1454 xpos = p.makeXPos(pos) 1455 } 1456 return xpos 1457 } 1458 1459 func (p *noder) setlineno(n syntax.Node) { 1460 if n != nil { 1461 lineno = p.pos(n) 1462 } 1463 } 1464 1465 // error is called concurrently if files are parsed concurrently. 1466 func (p *noder) error(err error) { 1467 p.err <- err.(syntax.Error) 1468 } 1469 1470 // pragmas that are allowed in the std lib, but don't have 1471 // a syntax.Pragma value (see lex.go) associated with them. 1472 var allowedStdPragmas = map[string]bool{ 1473 "go:cgo_export_static": true, 1474 "go:cgo_export_dynamic": true, 1475 "go:cgo_import_static": true, 1476 "go:cgo_import_dynamic": true, 1477 "go:cgo_ldflag": true, 1478 "go:cgo_dynamic_linker": true, 1479 "go:generate": true, 1480 } 1481 1482 // pragma is called concurrently if files are parsed concurrently. 1483 func (p *noder) pragma(pos syntax.Pos, text string) syntax.Pragma { 1484 switch { 1485 case strings.HasPrefix(text, "line "): 1486 // line directives are handled by syntax package 1487 panic("unreachable") 1488 1489 case strings.HasPrefix(text, "go:linkname "): 1490 f := strings.Fields(text) 1491 if !(2 <= len(f) && len(f) <= 3) { 1492 p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname [linkname]"}) 1493 break 1494 } 1495 // The second argument is optional. If omitted, we use 1496 // the default object symbol name for this and 1497 // linkname only serves to mark this symbol as 1498 // something that may be referenced via the object 1499 // symbol name from another package. 1500 var target string 1501 if len(f) == 3 { 1502 target = f[2] 1503 } 1504 p.linknames = append(p.linknames, linkname{pos, f[1], target}) 1505 1506 case strings.HasPrefix(text, "go:cgo_import_dynamic "): 1507 // This is permitted for general use because Solaris 1508 // code relies on it in golang.org/x/sys/unix and others. 1509 fields := pragmaFields(text) 1510 if len(fields) >= 4 { 1511 lib := strings.Trim(fields[3], `"`) 1512 if lib != "" && !safeArg(lib) && !isCgoGeneratedFile(pos) { 1513 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("invalid library name %q in cgo_import_dynamic directive", lib)}) 1514 } 1515 p.pragcgo(pos, text) 1516 return pragmaValue("go:cgo_import_dynamic") 1517 } 1518 fallthrough 1519 case strings.HasPrefix(text, "go:cgo_"): 1520 // For security, we disallow //go:cgo_* directives other 1521 // than cgo_import_dynamic outside cgo-generated files. 1522 // Exception: they are allowed in the standard library, for runtime and syscall. 1523 if !isCgoGeneratedFile(pos) && !compiling_std { 1524 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)}) 1525 } 1526 p.pragcgo(pos, text) 1527 fallthrough // because of //go:cgo_unsafe_args 1528 default: 1529 verb := text 1530 if i := strings.Index(text, " "); i >= 0 { 1531 verb = verb[:i] 1532 } 1533 prag := pragmaValue(verb) 1534 const runtimePragmas = Systemstack | Nowritebarrier | Nowritebarrierrec | Yeswritebarrierrec 1535 if !compiling_runtime && prag&runtimePragmas != 0 { 1536 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in runtime", verb)}) 1537 } 1538 if prag == 0 && !allowedStdPragmas[verb] && compiling_std { 1539 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s is not allowed in the standard library", verb)}) 1540 } 1541 return prag 1542 } 1543 1544 return 0 1545 } 1546 1547 // isCgoGeneratedFile reports whether pos is in a file 1548 // generated by cgo, which is to say a file with name 1549 // beginning with "_cgo_". Such files are allowed to 1550 // contain cgo directives, and for security reasons 1551 // (primarily misuse of linker flags), other files are not. 1552 // See golang.org/issue/23672. 1553 func isCgoGeneratedFile(pos syntax.Pos) bool { 1554 return strings.HasPrefix(filepath.Base(filepath.Clean(fileh(pos.Base().Filename()))), "_cgo_") 1555 } 1556 1557 // safeArg reports whether arg is a "safe" command-line argument, 1558 // meaning that when it appears in a command-line, it probably 1559 // doesn't have some special meaning other than its own name. 1560 // This is copied from SafeArg in cmd/go/internal/load/pkg.go. 1561 func safeArg(name string) bool { 1562 if name == "" { 1563 return false 1564 } 1565 c := name[0] 1566 return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf 1567 } 1568 1569 func mkname(sym *types.Sym) *Node { 1570 n := oldname(sym) 1571 if n.Name != nil && n.Name.Pack != nil { 1572 n.Name.Pack.Name.SetUsed(true) 1573 } 1574 return n 1575 } 1576 1577 func unparen(x *Node) *Node { 1578 for x.Op == OPAREN { 1579 x = x.Left 1580 } 1581 return x 1582 }