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 5package typecheck 6 7import ( 8 "fmt" 9 "go/constant" 10 "go/token" 11 "internal/types/errors" 12 "strings" 13 14 "cmd/compile/internal/base" 15 "cmd/compile/internal/ir" 16 "cmd/compile/internal/types" 17 "cmd/internal/src" 18) 19 20func tcShift(n, l, r ir.Node) (ir.Node, ir.Node, *types.Type) { 21 if l.Type() == nil || r.Type() == nil { 22 return l, r, nil 23 } 24 25 r = DefaultLit(r, types.Types[types.TUINT]) 26 t := r.Type() 27 if !t.IsInteger() { 28 base.Errorf("invalid operation: %v (shift count type %v, must be integer)", n, r.Type()) 29 return l, r, nil 30 } 31 t = l.Type() 32 if t != nil && t.Kind() != types.TIDEAL && !t.IsInteger() { 33 base.Errorf("invalid operation: %v (shift of type %v)", n, t) 34 return l, r, nil 35 } 36 37 // no DefaultLit for left 38 // the outer context gives the type 39 t = l.Type() 40 if (l.Type() == types.UntypedFloat || l.Type() == types.UntypedComplex) && r.Op() == ir.OLITERAL { 41 t = types.UntypedInt 42 } 43 return l, r, t 44} 45 46// tcArith typechecks operands of a binary arithmetic expression. 47// The result of tcArith MUST be assigned back to original operands, 48// t is the type of the expression, and should be set by the caller. e.g: 49// 50// n.X, n.Y, t = tcArith(n, op, n.X, n.Y) 51// n.SetType(t) 52func tcArith(n ir.Node, op ir.Op, l, r ir.Node) (ir.Node, ir.Node, *types.Type) { 53 l, r = defaultlit2(l, r, false) 54 if l.Type() == nil || r.Type() == nil { 55 return l, r, nil 56 } 57 t := l.Type() 58 if t.Kind() == types.TIDEAL { 59 t = r.Type() 60 } 61 aop := ir.OXXX 62 if n.Op().IsCmp() && t.Kind() != types.TIDEAL && !types.Identical(l.Type(), r.Type()) { 63 // comparison is okay as long as one side is 64 // assignable to the other. convert so they have 65 // the same type. 66 // 67 // the only conversion that isn't a no-op is concrete == interface. 68 // in that case, check comparability of the concrete type. 69 // The conversion allocates, so only do it if the concrete type is huge. 70 converted := false 71 if r.Type().Kind() != types.TBLANK { 72 aop, _ = assignOp(l.Type(), r.Type()) 73 if aop != ir.OXXX { 74 if r.Type().IsInterface() && !l.Type().IsInterface() && !types.IsComparable(l.Type()) { 75 base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(l.Type())) 76 return l, r, nil 77 } 78 79 types.CalcSize(l.Type()) 80 if r.Type().IsInterface() == l.Type().IsInterface() || l.Type().Size() >= 1<<16 { 81 l = ir.NewConvExpr(base.Pos, aop, r.Type(), l) 82 l.SetTypecheck(1) 83 } 84 85 t = r.Type() 86 converted = true 87 } 88 } 89 90 if !converted && l.Type().Kind() != types.TBLANK { 91 aop, _ = assignOp(r.Type(), l.Type()) 92 if aop != ir.OXXX { 93 if l.Type().IsInterface() && !r.Type().IsInterface() && !types.IsComparable(r.Type()) { 94 base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(r.Type())) 95 return l, r, nil 96 } 97 98 types.CalcSize(r.Type()) 99 if r.Type().IsInterface() == l.Type().IsInterface() || r.Type().Size() >= 1<<16 { 100 r = ir.NewConvExpr(base.Pos, aop, l.Type(), r) 101 r.SetTypecheck(1) 102 } 103 104 t = l.Type() 105 } 106 } 107 } 108 109 if t.Kind() != types.TIDEAL && !types.Identical(l.Type(), r.Type()) { 110 l, r = defaultlit2(l, r, true) 111 if l.Type() == nil || r.Type() == nil { 112 return l, r, nil 113 } 114 if l.Type().IsInterface() == r.Type().IsInterface() || aop == 0 { 115 base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type()) 116 return l, r, nil 117 } 118 } 119 120 if t.Kind() == types.TIDEAL { 121 t = mixUntyped(l.Type(), r.Type()) 122 } 123 if dt := defaultType(t); !okfor[op][dt.Kind()] { 124 base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(t)) 125 return l, r, nil 126 } 127 128 // okfor allows any array == array, map == map, func == func. 129 // restrict to slice/map/func == nil and nil == slice/map/func. 130 if l.Type().IsArray() && !types.IsComparable(l.Type()) { 131 base.Errorf("invalid operation: %v (%v cannot be compared)", n, l.Type()) 132 return l, r, nil 133 } 134 135 if l.Type().IsSlice() && !ir.IsNil(l) && !ir.IsNil(r) { 136 base.Errorf("invalid operation: %v (slice can only be compared to nil)", n) 137 return l, r, nil 138 } 139 140 if l.Type().IsMap() && !ir.IsNil(l) && !ir.IsNil(r) { 141 base.Errorf("invalid operation: %v (map can only be compared to nil)", n) 142 return l, r, nil 143 } 144 145 if l.Type().Kind() == types.TFUNC && !ir.IsNil(l) && !ir.IsNil(r) { 146 base.Errorf("invalid operation: %v (func can only be compared to nil)", n) 147 return l, r, nil 148 } 149 150 if l.Type().IsStruct() { 151 if f := types.IncomparableField(l.Type()); f != nil { 152 base.Errorf("invalid operation: %v (struct containing %v cannot be compared)", n, f.Type) 153 return l, r, nil 154 } 155 } 156 157 return l, r, t 158} 159 160// The result of tcCompLit MUST be assigned back to n, e.g. 161// 162// n.Left = tcCompLit(n.Left) 163func tcCompLit(n *ir.CompLitExpr) (res ir.Node) { 164 if base.EnableTrace && base.Flag.LowerT { 165 defer tracePrint("tcCompLit", n)(&res) 166 } 167 168 lno := base.Pos 169 defer func() { 170 base.Pos = lno 171 }() 172 173 ir.SetPos(n) 174 175 t := n.Type() 176 base.AssertfAt(t != nil, n.Pos(), "missing type in composite literal") 177 178 switch t.Kind() { 179 default: 180 base.Errorf("invalid composite literal type %v", t) 181 n.SetType(nil) 182 183 case types.TARRAY: 184 typecheckarraylit(t.Elem(), t.NumElem(), n.List, "array literal") 185 n.SetOp(ir.OARRAYLIT) 186 187 case types.TSLICE: 188 length := typecheckarraylit(t.Elem(), -1, n.List, "slice literal") 189 n.SetOp(ir.OSLICELIT) 190 n.Len = length 191 192 case types.TMAP: 193 for i3, l := range n.List { 194 ir.SetPos(l) 195 if l.Op() != ir.OKEY { 196 n.List[i3] = Expr(l) 197 base.Errorf("missing key in map literal") 198 continue 199 } 200 l := l.(*ir.KeyExpr) 201 202 r := l.Key 203 r = Expr(r) 204 l.Key = AssignConv(r, t.Key(), "map key") 205 206 r = l.Value 207 r = Expr(r) 208 l.Value = AssignConv(r, t.Elem(), "map value") 209 } 210 211 n.SetOp(ir.OMAPLIT) 212 213 case types.TSTRUCT: 214 // Need valid field offsets for Xoffset below. 215 types.CalcSize(t) 216 217 errored := false 218 if len(n.List) != 0 && nokeys(n.List) { 219 // simple list of variables 220 ls := n.List 221 for i, n1 := range ls { 222 ir.SetPos(n1) 223 n1 = Expr(n1) 224 ls[i] = n1 225 if i >= t.NumFields() { 226 if !errored { 227 base.Errorf("too many values in %v", n) 228 errored = true 229 } 230 continue 231 } 232 233 f := t.Field(i) 234 s := f.Sym 235 236 // Do the test for assigning to unexported fields. 237 // But if this is an instantiated function, then 238 // the function has already been typechecked. In 239 // that case, don't do the test, since it can fail 240 // for the closure structs created in 241 // walkClosure(), because the instantiated 242 // function is compiled as if in the source 243 // package of the generic function. 244 if !(ir.CurFunc != nil && strings.Contains(ir.CurFunc.Nname.Sym().Name, "[")) { 245 if s != nil && !types.IsExported(s.Name) && s.Pkg != types.LocalPkg { 246 base.Errorf("implicit assignment of unexported field '%s' in %v literal", s.Name, t) 247 } 248 } 249 // No pushtype allowed here. Must name fields for that. 250 n1 = AssignConv(n1, f.Type, "field value") 251 ls[i] = ir.NewStructKeyExpr(base.Pos, f, n1) 252 } 253 if len(ls) < t.NumFields() { 254 base.Errorf("too few values in %v", n) 255 } 256 } else { 257 hash := make(map[string]bool) 258 259 // keyed list 260 ls := n.List 261 for i, n := range ls { 262 ir.SetPos(n) 263 264 sk, ok := n.(*ir.StructKeyExpr) 265 if !ok { 266 kv, ok := n.(*ir.KeyExpr) 267 if !ok { 268 if !errored { 269 base.Errorf("mixture of field:value and value initializers") 270 errored = true 271 } 272 ls[i] = Expr(n) 273 continue 274 } 275 276 sk = tcStructLitKey(t, kv) 277 if sk == nil { 278 continue 279 } 280 281 fielddup(sk.Sym().Name, hash) 282 } 283 284 // No pushtype allowed here. Tried and rejected. 285 sk.Value = Expr(sk.Value) 286 sk.Value = AssignConv(sk.Value, sk.Field.Type, "field value") 287 ls[i] = sk 288 } 289 } 290 291 n.SetOp(ir.OSTRUCTLIT) 292 } 293 294 return n 295} 296 297// tcStructLitKey typechecks an OKEY node that appeared within a 298// struct literal. 299func tcStructLitKey(typ *types.Type, kv *ir.KeyExpr) *ir.StructKeyExpr { 300 key := kv.Key 301 302 sym := key.Sym() 303 304 // An OXDOT uses the Sym field to hold 305 // the field to the right of the dot, 306 // so s will be non-nil, but an OXDOT 307 // is never a valid struct literal key. 308 if sym == nil || sym.Pkg != types.LocalPkg || key.Op() == ir.OXDOT || sym.IsBlank() { 309 base.Errorf("invalid field name %v in struct initializer", key) 310 return nil 311 } 312 313 if f := Lookdot1(nil, sym, typ, typ.Fields(), 0); f != nil { 314 return ir.NewStructKeyExpr(kv.Pos(), f, kv.Value) 315 } 316 317 if ci := Lookdot1(nil, sym, typ, typ.Fields(), 2); ci != nil { // Case-insensitive lookup. 318 if visible(ci.Sym) { 319 base.Errorf("unknown field '%v' in struct literal of type %v (but does have %v)", sym, typ, ci.Sym) 320 } else if nonexported(sym) && sym.Name == ci.Sym.Name { // Ensure exactness before the suggestion. 321 base.Errorf("cannot refer to unexported field '%v' in struct literal of type %v", sym, typ) 322 } else { 323 base.Errorf("unknown field '%v' in struct literal of type %v", sym, typ) 324 } 325 return nil 326 } 327 328 var f *types.Field 329 p, _ := dotpath(sym, typ, &f, true) 330 if p == nil || f.IsMethod() { 331 base.Errorf("unknown field '%v' in struct literal of type %v", sym, typ) 332 return nil 333 } 334 335 // dotpath returns the parent embedded types in reverse order. 336 var ep []string 337 for ei := len(p) - 1; ei >= 0; ei-- { 338 ep = append(ep, p[ei].field.Sym.Name) 339 } 340 ep = append(ep, sym.Name) 341 base.Errorf("cannot use promoted field %v in struct literal of type %v", strings.Join(ep, "."), typ) 342 return nil 343} 344 345// tcConv typechecks an OCONV node. 346func tcConv(n *ir.ConvExpr) ir.Node { 347 types.CheckSize(n.Type()) // ensure width is calculated for backend 348 n.X = Expr(n.X) 349 n.X = convlit1(n.X, n.Type(), true, nil) 350 t := n.X.Type() 351 if t == nil || n.Type() == nil { 352 n.SetType(nil) 353 return n 354 } 355 op, why := convertOp(n.X.Op() == ir.OLITERAL, t, n.Type()) 356 if op == ir.OXXX { 357 // Due to //go:nointerface, we may be stricter than types2 here (#63333). 358 base.ErrorfAt(n.Pos(), errors.InvalidConversion, "cannot convert %L to type %v%s", n.X, n.Type(), why) 359 n.SetType(nil) 360 return n 361 } 362 363 n.SetOp(op) 364 switch n.Op() { 365 case ir.OCONVNOP: 366 if t.Kind() == n.Type().Kind() { 367 switch t.Kind() { 368 case types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128: 369 // Floating point casts imply rounding and 370 // so the conversion must be kept. 371 n.SetOp(ir.OCONV) 372 } 373 } 374 375 // do not convert to []byte literal. See CL 125796. 376 // generated code and compiler memory footprint is better without it. 377 case ir.OSTR2BYTES: 378 // ok 379 380 case ir.OSTR2RUNES: 381 if n.X.Op() == ir.OLITERAL { 382 return stringtoruneslit(n) 383 } 384 385 case ir.OBYTES2STR: 386 if t.Elem() != types.ByteType && t.Elem() != types.Types[types.TUINT8] { 387 // If t is a slice of a user-defined byte type B (not uint8 388 // or byte), then add an extra CONVNOP from []B to []byte, so 389 // that the call to slicebytetostring() added in walk will 390 // typecheck correctly. 391 n.X = ir.NewConvExpr(n.X.Pos(), ir.OCONVNOP, types.NewSlice(types.ByteType), n.X) 392 n.X.SetTypecheck(1) 393 } 394 395 case ir.ORUNES2STR: 396 if t.Elem() != types.RuneType && t.Elem() != types.Types[types.TINT32] { 397 // If t is a slice of a user-defined rune type B (not uint32 398 // or rune), then add an extra CONVNOP from []B to []rune, so 399 // that the call to slicerunetostring() added in walk will 400 // typecheck correctly. 401 n.X = ir.NewConvExpr(n.X.Pos(), ir.OCONVNOP, types.NewSlice(types.RuneType), n.X) 402 n.X.SetTypecheck(1) 403 } 404 405 } 406 return n 407} 408 409// DotField returns a field selector expression that selects the 410// index'th field of the given expression, which must be of struct or 411// pointer-to-struct type. 412func DotField(pos src.XPos, x ir.Node, index int) *ir.SelectorExpr { 413 op, typ := ir.ODOT, x.Type() 414 if typ.IsPtr() { 415 op, typ = ir.ODOTPTR, typ.Elem() 416 } 417 if !typ.IsStruct() { 418 base.FatalfAt(pos, "DotField of non-struct: %L", x) 419 } 420 421 // TODO(mdempsky): This is the backend's responsibility. 422 types.CalcSize(typ) 423 424 field := typ.Field(index) 425 return dot(pos, field.Type, op, x, field) 426} 427 428func dot(pos src.XPos, typ *types.Type, op ir.Op, x ir.Node, selection *types.Field) *ir.SelectorExpr { 429 n := ir.NewSelectorExpr(pos, op, x, selection.Sym) 430 n.Selection = selection 431 n.SetType(typ) 432 n.SetTypecheck(1) 433 return n 434} 435 436// XDotField returns an expression representing the field selection 437// x.sym. If any implicit field selection are necessary, those are 438// inserted too. 439func XDotField(pos src.XPos, x ir.Node, sym *types.Sym) *ir.SelectorExpr { 440 n := Expr(ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)).(*ir.SelectorExpr) 441 if n.Op() != ir.ODOT && n.Op() != ir.ODOTPTR { 442 base.FatalfAt(pos, "unexpected result op: %v (%v)", n.Op(), n) 443 } 444 return n 445} 446 447// XDotMethod returns an expression representing the method value 448// x.sym (i.e., x is a value, not a type). If any implicit field 449// selection are necessary, those are inserted too. 450// 451// If callee is true, the result is an ODOTMETH/ODOTINTER, otherwise 452// an OMETHVALUE. 453func XDotMethod(pos src.XPos, x ir.Node, sym *types.Sym, callee bool) *ir.SelectorExpr { 454 n := ir.NewSelectorExpr(pos, ir.OXDOT, x, sym) 455 if callee { 456 n = Callee(n).(*ir.SelectorExpr) 457 if n.Op() != ir.ODOTMETH && n.Op() != ir.ODOTINTER { 458 base.FatalfAt(pos, "unexpected result op: %v (%v)", n.Op(), n) 459 } 460 } else { 461 n = Expr(n).(*ir.SelectorExpr) 462 if n.Op() != ir.OMETHVALUE { 463 base.FatalfAt(pos, "unexpected result op: %v (%v)", n.Op(), n) 464 } 465 } 466 return n 467} 468 469// tcDot typechecks an OXDOT or ODOT node. 470func tcDot(n *ir.SelectorExpr, top int) ir.Node { 471 if n.Op() == ir.OXDOT { 472 n = AddImplicitDots(n) 473 n.SetOp(ir.ODOT) 474 if n.X == nil { 475 n.SetType(nil) 476 return n 477 } 478 } 479 480 n.X = Expr(n.X) 481 n.X = DefaultLit(n.X, nil) 482 483 t := n.X.Type() 484 if t == nil { 485 base.UpdateErrorDot(ir.Line(n), fmt.Sprint(n.X), fmt.Sprint(n)) 486 n.SetType(nil) 487 return n 488 } 489 490 if n.X.Op() == ir.OTYPE { 491 base.FatalfAt(n.Pos(), "use NewMethodExpr to construct OMETHEXPR") 492 } 493 494 if t.IsPtr() && !t.Elem().IsInterface() { 495 t = t.Elem() 496 if t == nil { 497 n.SetType(nil) 498 return n 499 } 500 n.SetOp(ir.ODOTPTR) 501 types.CheckSize(t) 502 } 503 504 if n.Sel.IsBlank() { 505 base.Errorf("cannot refer to blank field or method") 506 n.SetType(nil) 507 return n 508 } 509 510 if Lookdot(n, t, 0) == nil { 511 // Legitimate field or method lookup failed, try to explain the error 512 switch { 513 case t.IsEmptyInterface(): 514 base.Errorf("%v undefined (type %v is interface with no methods)", n, n.X.Type()) 515 516 case t.IsPtr() && t.Elem().IsInterface(): 517 // Pointer to interface is almost always a mistake. 518 base.Errorf("%v undefined (type %v is pointer to interface, not interface)", n, n.X.Type()) 519 520 case Lookdot(n, t, 1) != nil: 521 // Field or method matches by name, but it is not exported. 522 base.Errorf("%v undefined (cannot refer to unexported field or method %v)", n, n.Sel) 523 524 default: 525 if mt := Lookdot(n, t, 2); mt != nil && visible(mt.Sym) { // Case-insensitive lookup. 526 base.Errorf("%v undefined (type %v has no field or method %v, but does have %v)", n, n.X.Type(), n.Sel, mt.Sym) 527 } else { 528 base.Errorf("%v undefined (type %v has no field or method %v)", n, n.X.Type(), n.Sel) 529 } 530 } 531 n.SetType(nil) 532 return n 533 } 534 535 if (n.Op() == ir.ODOTINTER || n.Op() == ir.ODOTMETH) && top&ctxCallee == 0 { 536 n.SetOp(ir.OMETHVALUE) 537 n.SetType(NewMethodType(n.Type(), nil)) 538 } 539 return n 540} 541 542// tcDotType typechecks an ODOTTYPE node. 543func tcDotType(n *ir.TypeAssertExpr) ir.Node { 544 n.X = Expr(n.X) 545 n.X = DefaultLit(n.X, nil) 546 l := n.X 547 t := l.Type() 548 if t == nil { 549 n.SetType(nil) 550 return n 551 } 552 if !t.IsInterface() { 553 base.Errorf("invalid type assertion: %v (non-interface type %v on left)", n, t) 554 n.SetType(nil) 555 return n 556 } 557 558 base.AssertfAt(n.Type() != nil, n.Pos(), "missing type: %v", n) 559 560 if n.Type() != nil && !n.Type().IsInterface() { 561 why := ImplementsExplain(n.Type(), t) 562 if why != "" { 563 base.Fatalf("impossible type assertion:\n\t%s", why) 564 n.SetType(nil) 565 return n 566 } 567 } 568 return n 569} 570 571// tcITab typechecks an OITAB node. 572func tcITab(n *ir.UnaryExpr) ir.Node { 573 n.X = Expr(n.X) 574 t := n.X.Type() 575 if t == nil { 576 n.SetType(nil) 577 return n 578 } 579 if !t.IsInterface() { 580 base.Fatalf("OITAB of %v", t) 581 } 582 n.SetType(types.NewPtr(types.Types[types.TUINTPTR])) 583 return n 584} 585 586// tcIndex typechecks an OINDEX node. 587func tcIndex(n *ir.IndexExpr) ir.Node { 588 n.X = Expr(n.X) 589 n.X = DefaultLit(n.X, nil) 590 n.X = implicitstar(n.X) 591 l := n.X 592 n.Index = Expr(n.Index) 593 r := n.Index 594 t := l.Type() 595 if t == nil || r.Type() == nil { 596 n.SetType(nil) 597 return n 598 } 599 switch t.Kind() { 600 default: 601 base.Errorf("invalid operation: %v (type %v does not support indexing)", n, t) 602 n.SetType(nil) 603 return n 604 605 case types.TSTRING, types.TARRAY, types.TSLICE: 606 n.Index = indexlit(n.Index) 607 if t.IsString() { 608 n.SetType(types.ByteType) 609 } else { 610 n.SetType(t.Elem()) 611 } 612 why := "string" 613 if t.IsArray() { 614 why = "array" 615 } else if t.IsSlice() { 616 why = "slice" 617 } 618 619 if n.Index.Type() != nil && !n.Index.Type().IsInteger() { 620 base.Errorf("non-integer %s index %v", why, n.Index) 621 return n 622 } 623 624 case types.TMAP: 625 n.Index = AssignConv(n.Index, t.Key(), "map index") 626 n.SetType(t.Elem()) 627 n.SetOp(ir.OINDEXMAP) 628 n.Assigned = false 629 } 630 return n 631} 632 633// tcLenCap typechecks an OLEN or OCAP node. 634func tcLenCap(n *ir.UnaryExpr) ir.Node { 635 n.X = Expr(n.X) 636 n.X = DefaultLit(n.X, nil) 637 n.X = implicitstar(n.X) 638 l := n.X 639 t := l.Type() 640 if t == nil { 641 n.SetType(nil) 642 return n 643 } 644 645 var ok bool 646 if n.Op() == ir.OLEN { 647 ok = okforlen[t.Kind()] 648 } else { 649 ok = okforcap[t.Kind()] 650 } 651 if !ok { 652 base.Errorf("invalid argument %L for %v", l, n.Op()) 653 n.SetType(nil) 654 return n 655 } 656 657 n.SetType(types.Types[types.TINT]) 658 return n 659} 660 661// tcUnsafeData typechecks an OUNSAFESLICEDATA or OUNSAFESTRINGDATA node. 662func tcUnsafeData(n *ir.UnaryExpr) ir.Node { 663 n.X = Expr(n.X) 664 n.X = DefaultLit(n.X, nil) 665 l := n.X 666 t := l.Type() 667 if t == nil { 668 n.SetType(nil) 669 return n 670 } 671 672 var kind types.Kind 673 if n.Op() == ir.OUNSAFESLICEDATA { 674 kind = types.TSLICE 675 } else { 676 /* kind is string */ 677 kind = types.TSTRING 678 } 679 680 if t.Kind() != kind { 681 base.Errorf("invalid argument %L for %v", l, n.Op()) 682 n.SetType(nil) 683 return n 684 } 685 686 if kind == types.TSTRING { 687 t = types.ByteType 688 } else { 689 t = t.Elem() 690 } 691 n.SetType(types.NewPtr(t)) 692 return n 693} 694 695// tcRecv typechecks an ORECV node. 696func tcRecv(n *ir.UnaryExpr) ir.Node { 697 n.X = Expr(n.X) 698 n.X = DefaultLit(n.X, nil) 699 l := n.X 700 t := l.Type() 701 if t == nil { 702 n.SetType(nil) 703 return n 704 } 705 if !t.IsChan() { 706 base.Errorf("invalid operation: %v (receive from non-chan type %v)", n, t) 707 n.SetType(nil) 708 return n 709 } 710 711 if !t.ChanDir().CanRecv() { 712 base.Errorf("invalid operation: %v (receive from send-only type %v)", n, t) 713 n.SetType(nil) 714 return n 715 } 716 717 n.SetType(t.Elem()) 718 return n 719} 720 721// tcSPtr typechecks an OSPTR node. 722func tcSPtr(n *ir.UnaryExpr) ir.Node { 723 n.X = Expr(n.X) 724 t := n.X.Type() 725 if t == nil { 726 n.SetType(nil) 727 return n 728 } 729 if !t.IsSlice() && !t.IsString() { 730 base.Fatalf("OSPTR of %v", t) 731 } 732 if t.IsString() { 733 n.SetType(types.NewPtr(types.Types[types.TUINT8])) 734 } else { 735 n.SetType(types.NewPtr(t.Elem())) 736 } 737 return n 738} 739 740// tcSlice typechecks an OSLICE or OSLICE3 node. 741func tcSlice(n *ir.SliceExpr) ir.Node { 742 n.X = DefaultLit(Expr(n.X), nil) 743 n.Low = indexlit(Expr(n.Low)) 744 n.High = indexlit(Expr(n.High)) 745 n.Max = indexlit(Expr(n.Max)) 746 hasmax := n.Op().IsSlice3() 747 l := n.X 748 if l.Type() == nil { 749 n.SetType(nil) 750 return n 751 } 752 if l.Type().IsArray() { 753 if !ir.IsAddressable(n.X) { 754 base.Errorf("invalid operation %v (slice of unaddressable value)", n) 755 n.SetType(nil) 756 return n 757 } 758 759 addr := NodAddr(n.X) 760 addr.SetImplicit(true) 761 n.X = Expr(addr) 762 l = n.X 763 } 764 t := l.Type() 765 var tp *types.Type 766 if t.IsString() { 767 if hasmax { 768 base.Errorf("invalid operation %v (3-index slice of string)", n) 769 n.SetType(nil) 770 return n 771 } 772 n.SetType(t) 773 n.SetOp(ir.OSLICESTR) 774 } else if t.IsPtr() && t.Elem().IsArray() { 775 tp = t.Elem() 776 n.SetType(types.NewSlice(tp.Elem())) 777 types.CalcSize(n.Type()) 778 if hasmax { 779 n.SetOp(ir.OSLICE3ARR) 780 } else { 781 n.SetOp(ir.OSLICEARR) 782 } 783 } else if t.IsSlice() { 784 n.SetType(t) 785 } else { 786 base.Errorf("cannot slice %v (type %v)", l, t) 787 n.SetType(nil) 788 return n 789 } 790 791 if n.Low != nil && !checksliceindex(l, n.Low, tp) { 792 n.SetType(nil) 793 return n 794 } 795 if n.High != nil && !checksliceindex(l, n.High, tp) { 796 n.SetType(nil) 797 return n 798 } 799 if n.Max != nil && !checksliceindex(l, n.Max, tp) { 800 n.SetType(nil) 801 return n 802 } 803 if !checksliceconst(n.Low, n.High) || !checksliceconst(n.Low, n.Max) || !checksliceconst(n.High, n.Max) { 804 n.SetType(nil) 805 return n 806 } 807 return n 808} 809 810// tcSliceHeader typechecks an OSLICEHEADER node. 811func tcSliceHeader(n *ir.SliceHeaderExpr) ir.Node { 812 // Errors here are Fatalf instead of Errorf because only the compiler 813 // can construct an OSLICEHEADER node. 814 // Components used in OSLICEHEADER that are supplied by parsed source code 815 // have already been typechecked in e.g. OMAKESLICE earlier. 816 t := n.Type() 817 if t == nil { 818 base.Fatalf("no type specified for OSLICEHEADER") 819 } 820 821 if !t.IsSlice() { 822 base.Fatalf("invalid type %v for OSLICEHEADER", n.Type()) 823 } 824 825 if n.Ptr == nil || n.Ptr.Type() == nil || !n.Ptr.Type().IsUnsafePtr() { 826 base.Fatalf("need unsafe.Pointer for OSLICEHEADER") 827 } 828 829 n.Ptr = Expr(n.Ptr) 830 n.Len = DefaultLit(Expr(n.Len), types.Types[types.TINT]) 831 n.Cap = DefaultLit(Expr(n.Cap), types.Types[types.TINT]) 832 833 if ir.IsConst(n.Len, constant.Int) && ir.Int64Val(n.Len) < 0 { 834 base.Fatalf("len for OSLICEHEADER must be non-negative") 835 } 836 837 if ir.IsConst(n.Cap, constant.Int) && ir.Int64Val(n.Cap) < 0 { 838 base.Fatalf("cap for OSLICEHEADER must be non-negative") 839 } 840 841 if ir.IsConst(n.Len, constant.Int) && ir.IsConst(n.Cap, constant.Int) && constant.Compare(n.Len.Val(), token.GTR, n.Cap.Val()) { 842 base.Fatalf("len larger than cap for OSLICEHEADER") 843 } 844 845 return n 846} 847 848// tcStringHeader typechecks an OSTRINGHEADER node. 849func tcStringHeader(n *ir.StringHeaderExpr) ir.Node { 850 t := n.Type() 851 if t == nil { 852 base.Fatalf("no type specified for OSTRINGHEADER") 853 } 854 855 if !t.IsString() { 856 base.Fatalf("invalid type %v for OSTRINGHEADER", n.Type()) 857 } 858 859 if n.Ptr == nil || n.Ptr.Type() == nil || !n.Ptr.Type().IsUnsafePtr() { 860 base.Fatalf("need unsafe.Pointer for OSTRINGHEADER") 861 } 862 863 n.Ptr = Expr(n.Ptr) 864 n.Len = DefaultLit(Expr(n.Len), types.Types[types.TINT]) 865 866 if ir.IsConst(n.Len, constant.Int) && ir.Int64Val(n.Len) < 0 { 867 base.Fatalf("len for OSTRINGHEADER must be non-negative") 868 } 869 870 return n 871} 872 873// tcStar typechecks an ODEREF node, which may be an expression or a type. 874func tcStar(n *ir.StarExpr, top int) ir.Node { 875 n.X = typecheck(n.X, ctxExpr|ctxType) 876 l := n.X 877 t := l.Type() 878 if t == nil { 879 n.SetType(nil) 880 return n 881 } 882 883 // TODO(mdempsky): Remove (along with ctxType above) once I'm 884 // confident this code path isn't needed any more. 885 if l.Op() == ir.OTYPE { 886 base.Fatalf("unexpected type in deref expression: %v", l) 887 } 888 889 if !t.IsPtr() { 890 if top&(ctxExpr|ctxStmt) != 0 { 891 base.Errorf("invalid indirect of %L", n.X) 892 n.SetType(nil) 893 return n 894 } 895 base.Errorf("%v is not a type", l) 896 return n 897 } 898 899 n.SetType(t.Elem()) 900 return n 901} 902 903// tcUnaryArith typechecks a unary arithmetic expression. 904func tcUnaryArith(n *ir.UnaryExpr) ir.Node { 905 n.X = Expr(n.X) 906 l := n.X 907 t := l.Type() 908 if t == nil { 909 n.SetType(nil) 910 return n 911 } 912 if !okfor[n.Op()][defaultType(t).Kind()] { 913 base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, n.Op(), typekind(t)) 914 n.SetType(nil) 915 return n 916 } 917 918 n.SetType(t) 919 return n 920} 921