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