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 "math" 12 "math/big" 13 "strings" 14 "unicode" 15 16 "cmd/compile/internal/base" 17 "cmd/compile/internal/ir" 18 "cmd/compile/internal/types" 19 "cmd/internal/src" 20) 21 22func roundFloat(v constant.Value, sz int64) constant.Value { 23 switch sz { 24 case 4: 25 f, _ := constant.Float32Val(v) 26 return makeFloat64(float64(f)) 27 case 8: 28 f, _ := constant.Float64Val(v) 29 return makeFloat64(f) 30 } 31 base.Fatalf("unexpected size: %v", sz) 32 panic("unreachable") 33} 34 35// truncate float literal fv to 32-bit or 64-bit precision 36// according to type; return truncated value. 37func truncfltlit(v constant.Value, t *types.Type) constant.Value { 38 if t.IsUntyped() || overflow(v, t) { 39 // If there was overflow, simply continuing would set the 40 // value to Inf which in turn would lead to spurious follow-on 41 // errors. Avoid this by returning the existing value. 42 return v 43 } 44 45 return roundFloat(v, t.Size()) 46} 47 48// truncate Real and Imag parts of Mpcplx to 32-bit or 64-bit 49// precision, according to type; return truncated value. In case of 50// overflow, calls Errorf but does not truncate the input value. 51func trunccmplxlit(v constant.Value, t *types.Type) constant.Value { 52 if t.IsUntyped() || overflow(v, t) { 53 // If there was overflow, simply continuing would set the 54 // value to Inf which in turn would lead to spurious follow-on 55 // errors. Avoid this by returning the existing value. 56 return v 57 } 58 59 fsz := t.Size() / 2 60 return makeComplex(roundFloat(constant.Real(v), fsz), roundFloat(constant.Imag(v), fsz)) 61} 62 63// TODO(mdempsky): Replace these with better APIs. 64func convlit(n ir.Node, t *types.Type) ir.Node { return convlit1(n, t, false, nil) } 65func DefaultLit(n ir.Node, t *types.Type) ir.Node { return convlit1(n, t, false, nil) } 66 67// convlit1 converts an untyped expression n to type t. If n already 68// has a type, convlit1 has no effect. 69// 70// For explicit conversions, t must be non-nil, and integer-to-string 71// conversions are allowed. 72// 73// For implicit conversions (e.g., assignments), t may be nil; if so, 74// n is converted to its default type. 75// 76// If there's an error converting n to t, context is used in the error 77// message. 78func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir.Node { 79 if explicit && t == nil { 80 base.Fatalf("explicit conversion missing type") 81 } 82 if t != nil && t.IsUntyped() { 83 base.Fatalf("bad conversion to untyped: %v", t) 84 } 85 86 if n == nil || n.Type() == nil { 87 // Allow sloppy callers. 88 return n 89 } 90 if !n.Type().IsUntyped() { 91 // Already typed; nothing to do. 92 return n 93 } 94 95 // Nil is technically not a constant, so handle it specially. 96 if n.Type().Kind() == types.TNIL { 97 if n.Op() != ir.ONIL { 98 base.Fatalf("unexpected op: %v (%v)", n, n.Op()) 99 } 100 n = ir.Copy(n) 101 if t == nil { 102 base.Errorf("use of untyped nil") 103 n.SetDiag(true) 104 n.SetType(nil) 105 return n 106 } 107 108 if !t.HasNil() { 109 // Leave for caller to handle. 110 return n 111 } 112 113 n.SetType(t) 114 return n 115 } 116 117 if t == nil || !ir.OKForConst[t.Kind()] { 118 t = defaultType(n.Type()) 119 } 120 121 switch n.Op() { 122 default: 123 base.Fatalf("unexpected untyped expression: %v", n) 124 125 case ir.OLITERAL: 126 v := convertVal(n.Val(), t, explicit) 127 if v.Kind() == constant.Unknown { 128 n = ir.NewConstExpr(n.Val(), n) 129 break 130 } 131 n = ir.NewConstExpr(v, n) 132 n.SetType(t) 133 return n 134 135 case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.OREAL, ir.OIMAG: 136 ot := operandType(n.Op(), t) 137 if ot == nil { 138 n = DefaultLit(n, nil) 139 break 140 } 141 142 n := n.(*ir.UnaryExpr) 143 n.X = convlit(n.X, ot) 144 if n.X.Type() == nil { 145 n.SetType(nil) 146 return n 147 } 148 n.SetType(t) 149 return n 150 151 case ir.OADD, ir.OSUB, ir.OMUL, ir.ODIV, ir.OMOD, ir.OOR, ir.OXOR, ir.OAND, ir.OANDNOT, ir.OOROR, ir.OANDAND, ir.OCOMPLEX: 152 ot := operandType(n.Op(), t) 153 if ot == nil { 154 n = DefaultLit(n, nil) 155 break 156 } 157 158 var l, r ir.Node 159 switch n := n.(type) { 160 case *ir.BinaryExpr: 161 n.X = convlit(n.X, ot) 162 n.Y = convlit(n.Y, ot) 163 l, r = n.X, n.Y 164 case *ir.LogicalExpr: 165 n.X = convlit(n.X, ot) 166 n.Y = convlit(n.Y, ot) 167 l, r = n.X, n.Y 168 } 169 170 if l.Type() == nil || r.Type() == nil { 171 n.SetType(nil) 172 return n 173 } 174 if !types.Identical(l.Type(), r.Type()) { 175 base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type()) 176 n.SetType(nil) 177 return n 178 } 179 180 n.SetType(t) 181 return n 182 183 case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: 184 n := n.(*ir.BinaryExpr) 185 if !t.IsBoolean() { 186 break 187 } 188 n.SetType(t) 189 return n 190 191 case ir.OLSH, ir.ORSH: 192 n := n.(*ir.BinaryExpr) 193 n.X = convlit1(n.X, t, explicit, nil) 194 n.SetType(n.X.Type()) 195 if n.Type() != nil && !n.Type().IsInteger() { 196 base.Errorf("invalid operation: %v (shift of type %v)", n, n.Type()) 197 n.SetType(nil) 198 } 199 return n 200 } 201 202 if !n.Diag() { 203 if !t.Broke() { 204 if explicit { 205 base.Errorf("cannot convert %L to type %v", n, t) 206 } else if context != nil { 207 base.Errorf("cannot use %L as type %v in %s", n, t, context()) 208 } else { 209 base.Errorf("cannot use %L as type %v", n, t) 210 } 211 } 212 n.SetDiag(true) 213 } 214 n.SetType(nil) 215 return n 216} 217 218func operandType(op ir.Op, t *types.Type) *types.Type { 219 switch op { 220 case ir.OCOMPLEX: 221 if t.IsComplex() { 222 return types.FloatForComplex(t) 223 } 224 case ir.OREAL, ir.OIMAG: 225 if t.IsFloat() { 226 return types.ComplexForFloat(t) 227 } 228 default: 229 if okfor[op][t.Kind()] { 230 return t 231 } 232 } 233 return nil 234} 235 236// convertVal converts v into a representation appropriate for t. If 237// no such representation exists, it returns Val{} instead. 238// 239// If explicit is true, then conversions from integer to string are 240// also allowed. 241func convertVal(v constant.Value, t *types.Type, explicit bool) constant.Value { 242 switch ct := v.Kind(); ct { 243 case constant.Bool: 244 if t.IsBoolean() { 245 return v 246 } 247 248 case constant.String: 249 if t.IsString() { 250 return v 251 } 252 253 case constant.Int: 254 if explicit && t.IsString() { 255 return tostr(v) 256 } 257 fallthrough 258 case constant.Float, constant.Complex: 259 switch { 260 case t.IsInteger(): 261 v = toint(v) 262 overflow(v, t) 263 return v 264 case t.IsFloat(): 265 v = toflt(v) 266 v = truncfltlit(v, t) 267 return v 268 case t.IsComplex(): 269 v = tocplx(v) 270 v = trunccmplxlit(v, t) 271 return v 272 } 273 } 274 275 return constant.MakeUnknown() 276} 277 278func tocplx(v constant.Value) constant.Value { 279 return constant.ToComplex(v) 280} 281 282func toflt(v constant.Value) constant.Value { 283 if v.Kind() == constant.Complex { 284 if constant.Sign(constant.Imag(v)) != 0 { 285 base.Errorf("constant %v truncated to real", v) 286 } 287 v = constant.Real(v) 288 } 289 290 return constant.ToFloat(v) 291} 292 293func toint(v constant.Value) constant.Value { 294 if v.Kind() == constant.Complex { 295 if constant.Sign(constant.Imag(v)) != 0 { 296 base.Errorf("constant %v truncated to integer", v) 297 } 298 v = constant.Real(v) 299 } 300 301 if v := constant.ToInt(v); v.Kind() == constant.Int { 302 return v 303 } 304 305 // The value of v cannot be represented as an integer; 306 // so we need to print an error message. 307 // Unfortunately some float values cannot be 308 // reasonably formatted for inclusion in an error 309 // message (example: 1 + 1e-100), so first we try to 310 // format the float; if the truncation resulted in 311 // something that looks like an integer we omit the 312 // value from the error message. 313 // (See issue #11371). 314 f := ir.BigFloat(v) 315 if f.MantExp(nil) > 2*ir.ConstPrec { 316 base.Errorf("integer too large") 317 } else { 318 var t big.Float 319 t.Parse(fmt.Sprint(v), 0) 320 if t.IsInt() { 321 base.Errorf("constant truncated to integer") 322 } else { 323 base.Errorf("constant %v truncated to integer", v) 324 } 325 } 326 327 // Prevent follow-on errors. 328 // TODO(mdempsky): Use constant.MakeUnknown() instead. 329 return constant.MakeInt64(1) 330} 331 332// overflow reports whether constant value v is too large 333// to represent with type t, and emits an error message if so. 334func overflow(v constant.Value, t *types.Type) bool { 335 // v has already been converted 336 // to appropriate form for t. 337 if t.IsUntyped() { 338 return false 339 } 340 if v.Kind() == constant.Int && constant.BitLen(v) > ir.ConstPrec { 341 base.Errorf("integer too large") 342 return true 343 } 344 if ir.ConstOverflow(v, t) { 345 base.Errorf("constant %v overflows %v", types.FmtConst(v, false), t) 346 return true 347 } 348 return false 349} 350 351func tostr(v constant.Value) constant.Value { 352 if v.Kind() == constant.Int { 353 r := unicode.ReplacementChar 354 if x, ok := constant.Uint64Val(v); ok && x <= unicode.MaxRune { 355 r = rune(x) 356 } 357 v = constant.MakeString(string(r)) 358 } 359 return v 360} 361 362var tokenForOp = [...]token.Token{ 363 ir.OPLUS: token.ADD, 364 ir.ONEG: token.SUB, 365 ir.ONOT: token.NOT, 366 ir.OBITNOT: token.XOR, 367 368 ir.OADD: token.ADD, 369 ir.OSUB: token.SUB, 370 ir.OMUL: token.MUL, 371 ir.ODIV: token.QUO, 372 ir.OMOD: token.REM, 373 ir.OOR: token.OR, 374 ir.OXOR: token.XOR, 375 ir.OAND: token.AND, 376 ir.OANDNOT: token.AND_NOT, 377 ir.OOROR: token.LOR, 378 ir.OANDAND: token.LAND, 379 380 ir.OEQ: token.EQL, 381 ir.ONE: token.NEQ, 382 ir.OLT: token.LSS, 383 ir.OLE: token.LEQ, 384 ir.OGT: token.GTR, 385 ir.OGE: token.GEQ, 386 387 ir.OLSH: token.SHL, 388 ir.ORSH: token.SHR, 389} 390 391// EvalConst returns a constant-evaluated expression equivalent to n. 392// If n is not a constant, EvalConst returns n. 393// Otherwise, EvalConst returns a new OLITERAL with the same value as n, 394// and with .Orig pointing back to n. 395func EvalConst(n ir.Node) ir.Node { 396 // Pick off just the opcodes that can be constant evaluated. 397 switch n.Op() { 398 case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT: 399 n := n.(*ir.UnaryExpr) 400 nl := n.X 401 if nl.Op() == ir.OLITERAL { 402 var prec uint 403 if n.Type().IsUnsigned() { 404 prec = uint(n.Type().Size() * 8) 405 } 406 return OrigConst(n, constant.UnaryOp(tokenForOp[n.Op()], nl.Val(), prec)) 407 } 408 409 case ir.OADD, ir.OSUB, ir.OMUL, ir.ODIV, ir.OMOD, ir.OOR, ir.OXOR, ir.OAND, ir.OANDNOT: 410 n := n.(*ir.BinaryExpr) 411 nl, nr := n.X, n.Y 412 if nl.Op() == ir.OLITERAL && nr.Op() == ir.OLITERAL { 413 rval := nr.Val() 414 415 // check for divisor underflow in complex division (see issue 20227) 416 if n.Op() == ir.ODIV && n.Type().IsComplex() && constant.Sign(square(constant.Real(rval))) == 0 && constant.Sign(square(constant.Imag(rval))) == 0 { 417 base.Errorf("complex division by zero") 418 n.SetType(nil) 419 return n 420 } 421 if (n.Op() == ir.ODIV || n.Op() == ir.OMOD) && constant.Sign(rval) == 0 { 422 base.Errorf("division by zero") 423 n.SetType(nil) 424 return n 425 } 426 427 tok := tokenForOp[n.Op()] 428 if n.Op() == ir.ODIV && n.Type().IsInteger() { 429 tok = token.QUO_ASSIGN // integer division 430 } 431 return OrigConst(n, constant.BinaryOp(nl.Val(), tok, rval)) 432 } 433 434 case ir.OOROR, ir.OANDAND: 435 n := n.(*ir.LogicalExpr) 436 nl, nr := n.X, n.Y 437 if nl.Op() == ir.OLITERAL && nr.Op() == ir.OLITERAL { 438 return OrigConst(n, constant.BinaryOp(nl.Val(), tokenForOp[n.Op()], nr.Val())) 439 } 440 441 case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE: 442 n := n.(*ir.BinaryExpr) 443 nl, nr := n.X, n.Y 444 if nl.Op() == ir.OLITERAL && nr.Op() == ir.OLITERAL { 445 return OrigBool(n, constant.Compare(nl.Val(), tokenForOp[n.Op()], nr.Val())) 446 } 447 448 case ir.OLSH, ir.ORSH: 449 n := n.(*ir.BinaryExpr) 450 nl, nr := n.X, n.Y 451 if nl.Op() == ir.OLITERAL && nr.Op() == ir.OLITERAL { 452 // shiftBound from go/types; "so we can express smallestFloat64" (see issue #44057) 453 const shiftBound = 1023 - 1 + 52 454 s, ok := constant.Uint64Val(nr.Val()) 455 if !ok || s > shiftBound { 456 base.Errorf("invalid shift count %v", nr) 457 n.SetType(nil) 458 break 459 } 460 return OrigConst(n, constant.Shift(toint(nl.Val()), tokenForOp[n.Op()], uint(s))) 461 } 462 463 case ir.OCONV, ir.ORUNESTR: 464 n := n.(*ir.ConvExpr) 465 nl := n.X 466 if ir.OKForConst[n.Type().Kind()] && nl.Op() == ir.OLITERAL { 467 return OrigConst(n, convertVal(nl.Val(), n.Type(), true)) 468 } 469 470 case ir.OCONVNOP: 471 n := n.(*ir.ConvExpr) 472 nl := n.X 473 if ir.OKForConst[n.Type().Kind()] && nl.Op() == ir.OLITERAL { 474 // set so n.Orig gets OCONV instead of OCONVNOP 475 n.SetOp(ir.OCONV) 476 return OrigConst(n, nl.Val()) 477 } 478 479 case ir.OADDSTR: 480 // Merge adjacent constants in the argument list. 481 n := n.(*ir.AddStringExpr) 482 s := n.List 483 need := 0 484 for i := 0; i < len(s); i++ { 485 if i == 0 || !ir.IsConst(s[i-1], constant.String) || !ir.IsConst(s[i], constant.String) { 486 // Can't merge s[i] into s[i-1]; need a slot in the list. 487 need++ 488 } 489 } 490 if need == len(s) { 491 return n 492 } 493 if need == 1 { 494 var strs []string 495 for _, c := range s { 496 strs = append(strs, ir.StringVal(c)) 497 } 498 return OrigConst(n, constant.MakeString(strings.Join(strs, ""))) 499 } 500 newList := make([]ir.Node, 0, need) 501 for i := 0; i < len(s); i++ { 502 if ir.IsConst(s[i], constant.String) && i+1 < len(s) && ir.IsConst(s[i+1], constant.String) { 503 // merge from i up to but not including i2 504 var strs []string 505 i2 := i 506 for i2 < len(s) && ir.IsConst(s[i2], constant.String) { 507 strs = append(strs, ir.StringVal(s[i2])) 508 i2++ 509 } 510 511 nl := ir.Copy(n).(*ir.AddStringExpr) 512 nl.List = s[i:i2] 513 newList = append(newList, OrigConst(nl, constant.MakeString(strings.Join(strs, "")))) 514 i = i2 - 1 515 } else { 516 newList = append(newList, s[i]) 517 } 518 } 519 520 nn := ir.Copy(n).(*ir.AddStringExpr) 521 nn.List = newList 522 return nn 523 524 case ir.OCAP, ir.OLEN: 525 n := n.(*ir.UnaryExpr) 526 nl := n.X 527 switch nl.Type().Kind() { 528 case types.TSTRING: 529 if ir.IsConst(nl, constant.String) { 530 return OrigInt(n, int64(len(ir.StringVal(nl)))) 531 } 532 case types.TARRAY: 533 if !anyCallOrChan(nl) { 534 return OrigInt(n, nl.Type().NumElem()) 535 } 536 } 537 538 case ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: 539 n := n.(*ir.UnaryExpr) 540 return OrigInt(n, evalunsafe(n)) 541 542 case ir.OREAL: 543 n := n.(*ir.UnaryExpr) 544 nl := n.X 545 if nl.Op() == ir.OLITERAL { 546 return OrigConst(n, constant.Real(nl.Val())) 547 } 548 549 case ir.OIMAG: 550 n := n.(*ir.UnaryExpr) 551 nl := n.X 552 if nl.Op() == ir.OLITERAL { 553 return OrigConst(n, constant.Imag(nl.Val())) 554 } 555 556 case ir.OCOMPLEX: 557 n := n.(*ir.BinaryExpr) 558 nl, nr := n.X, n.Y 559 if nl.Op() == ir.OLITERAL && nr.Op() == ir.OLITERAL { 560 return OrigConst(n, makeComplex(nl.Val(), nr.Val())) 561 } 562 } 563 564 return n 565} 566 567func makeFloat64(f float64) constant.Value { 568 if math.IsInf(f, 0) { 569 base.Fatalf("infinity is not a valid constant") 570 } 571 return constant.MakeFloat64(f) 572} 573 574func makeComplex(real, imag constant.Value) constant.Value { 575 return constant.BinaryOp(constant.ToFloat(real), token.ADD, constant.MakeImag(constant.ToFloat(imag))) 576} 577 578func square(x constant.Value) constant.Value { 579 return constant.BinaryOp(x, token.MUL, x) 580} 581 582// For matching historical "constant OP overflow" error messages. 583// TODO(mdempsky): Replace with error messages like go/types uses. 584var overflowNames = [...]string{ 585 ir.OADD: "addition", 586 ir.OSUB: "subtraction", 587 ir.OMUL: "multiplication", 588 ir.OLSH: "shift", 589 ir.OXOR: "bitwise XOR", 590 ir.OBITNOT: "bitwise complement", 591} 592 593// OrigConst returns an OLITERAL with orig n and value v. 594func OrigConst(n ir.Node, v constant.Value) ir.Node { 595 lno := ir.SetPos(n) 596 v = convertVal(v, n.Type(), false) 597 base.Pos = lno 598 599 switch v.Kind() { 600 case constant.Int: 601 if constant.BitLen(v) <= ir.ConstPrec { 602 break 603 } 604 fallthrough 605 case constant.Unknown: 606 what := overflowNames[n.Op()] 607 if what == "" { 608 base.Fatalf("unexpected overflow: %v", n.Op()) 609 } 610 base.ErrorfAt(n.Pos(), "constant %v overflow", what) 611 n.SetType(nil) 612 return n 613 } 614 615 return ir.NewConstExpr(v, n) 616} 617 618func OrigBool(n ir.Node, v bool) ir.Node { 619 return OrigConst(n, constant.MakeBool(v)) 620} 621 622func OrigInt(n ir.Node, v int64) ir.Node { 623 return OrigConst(n, constant.MakeInt64(v)) 624} 625 626// DefaultLit on both nodes simultaneously; 627// if they're both ideal going in they better 628// get the same type going out. 629// force means must assign concrete (non-ideal) type. 630// The results of defaultlit2 MUST be assigned back to l and r, e.g. 631// n.Left, n.Right = defaultlit2(n.Left, n.Right, force) 632func defaultlit2(l ir.Node, r ir.Node, force bool) (ir.Node, ir.Node) { 633 if l.Type() == nil || r.Type() == nil { 634 return l, r 635 } 636 637 if !l.Type().IsInterface() && !r.Type().IsInterface() { 638 // Can't mix bool with non-bool, string with non-string. 639 if l.Type().IsBoolean() != r.Type().IsBoolean() { 640 return l, r 641 } 642 if l.Type().IsString() != r.Type().IsString() { 643 return l, r 644 } 645 } 646 647 if !l.Type().IsUntyped() { 648 r = convlit(r, l.Type()) 649 return l, r 650 } 651 652 if !r.Type().IsUntyped() { 653 l = convlit(l, r.Type()) 654 return l, r 655 } 656 657 if !force { 658 return l, r 659 } 660 661 // Can't mix nil with anything untyped. 662 if ir.IsNil(l) || ir.IsNil(r) { 663 return l, r 664 } 665 t := defaultType(mixUntyped(l.Type(), r.Type())) 666 l = convlit(l, t) 667 r = convlit(r, t) 668 return l, r 669} 670 671func mixUntyped(t1, t2 *types.Type) *types.Type { 672 if t1 == t2 { 673 return t1 674 } 675 676 rank := func(t *types.Type) int { 677 switch t { 678 case types.UntypedInt: 679 return 0 680 case types.UntypedRune: 681 return 1 682 case types.UntypedFloat: 683 return 2 684 case types.UntypedComplex: 685 return 3 686 } 687 base.Fatalf("bad type %v", t) 688 panic("unreachable") 689 } 690 691 if rank(t2) > rank(t1) { 692 return t2 693 } 694 return t1 695} 696 697func defaultType(t *types.Type) *types.Type { 698 if !t.IsUntyped() || t.Kind() == types.TNIL { 699 return t 700 } 701 702 switch t { 703 case types.UntypedBool: 704 return types.Types[types.TBOOL] 705 case types.UntypedString: 706 return types.Types[types.TSTRING] 707 case types.UntypedInt: 708 return types.Types[types.TINT] 709 case types.UntypedRune: 710 return types.RuneType 711 case types.UntypedFloat: 712 return types.Types[types.TFLOAT64] 713 case types.UntypedComplex: 714 return types.Types[types.TCOMPLEX128] 715 } 716 717 base.Fatalf("bad type %v", t) 718 return nil 719} 720 721// IndexConst checks if Node n contains a constant expression 722// representable as a non-negative int and returns its value. 723// If n is not a constant expression, not representable as an 724// integer, or negative, it returns -1. If n is too large, it 725// returns -2. 726func IndexConst(n ir.Node) int64 { 727 if n.Op() != ir.OLITERAL { 728 return -1 729 } 730 if !n.Type().IsInteger() && n.Type().Kind() != types.TIDEAL { 731 return -1 732 } 733 734 v := toint(n.Val()) 735 if v.Kind() != constant.Int || constant.Sign(v) < 0 { 736 return -1 737 } 738 if ir.ConstOverflow(v, types.Types[types.TINT]) { 739 return -2 740 } 741 return ir.IntVal(types.Types[types.TINT], v) 742} 743 744// anyCallOrChan reports whether n contains any calls or channel operations. 745func anyCallOrChan(n ir.Node) bool { 746 return ir.Any(n, func(n ir.Node) bool { 747 switch n.Op() { 748 case ir.OAPPEND, 749 ir.OCALL, 750 ir.OCALLFUNC, 751 ir.OCALLINTER, 752 ir.OCALLMETH, 753 ir.OCAP, 754 ir.OCLOSE, 755 ir.OCOMPLEX, 756 ir.OCOPY, 757 ir.ODELETE, 758 ir.OIMAG, 759 ir.OLEN, 760 ir.OMAKE, 761 ir.ONEW, 762 ir.OPANIC, 763 ir.OPRINT, 764 ir.OPRINTN, 765 ir.OREAL, 766 ir.ORECOVER, 767 ir.ORECV, 768 ir.OUNSAFEADD, 769 ir.OUNSAFESLICE: 770 return true 771 } 772 return false 773 }) 774} 775 776// A constSet represents a set of Go constant expressions. 777type constSet struct { 778 m map[constSetKey]src.XPos 779} 780 781type constSetKey struct { 782 typ *types.Type 783 val interface{} 784} 785 786// add adds constant expression n to s. If a constant expression of 787// equal value and identical type has already been added, then add 788// reports an error about the duplicate value. 789// 790// pos provides position information for where expression n occurred 791// (in case n does not have its own position information). what and 792// where are used in the error message. 793// 794// n must not be an untyped constant. 795func (s *constSet) add(pos src.XPos, n ir.Node, what, where string) { 796 if conv := n; conv.Op() == ir.OCONVIFACE { 797 conv := conv.(*ir.ConvExpr) 798 if conv.Implicit() { 799 n = conv.X 800 } 801 } 802 803 if !ir.IsConstNode(n) || n.Type() == nil { 804 return 805 } 806 if n.Type().IsUntyped() { 807 base.Fatalf("%v is untyped", n) 808 } 809 810 // Consts are only duplicates if they have the same value and 811 // identical types. 812 // 813 // In general, we have to use types.Identical to test type 814 // identity, because == gives false negatives for anonymous 815 // types and the byte/uint8 and rune/int32 builtin type 816 // aliases. However, this is not a problem here, because 817 // constant expressions are always untyped or have a named 818 // type, and we explicitly handle the builtin type aliases 819 // below. 820 // 821 // This approach may need to be revisited though if we fix 822 // #21866 by treating all type aliases like byte/uint8 and 823 // rune/int32. 824 825 typ := n.Type() 826 switch typ { 827 case types.ByteType: 828 typ = types.Types[types.TUINT8] 829 case types.RuneType: 830 typ = types.Types[types.TINT32] 831 } 832 k := constSetKey{typ, ir.ConstValue(n)} 833 834 if ir.HasUniquePos(n) { 835 pos = n.Pos() 836 } 837 838 if s.m == nil { 839 s.m = make(map[constSetKey]src.XPos) 840 } 841 842 if prevPos, isDup := s.m[k]; isDup { 843 base.ErrorfAt(pos, "duplicate %s %s in %s\n\tprevious %s at %v", 844 what, nodeAndVal(n), where, 845 what, base.FmtPos(prevPos)) 846 } else { 847 s.m[k] = pos 848 } 849} 850 851// nodeAndVal reports both an expression and its constant value, if 852// the latter is non-obvious. 853// 854// TODO(mdempsky): This could probably be a fmt.go flag. 855func nodeAndVal(n ir.Node) string { 856 show := fmt.Sprint(n) 857 val := ir.ConstValue(n) 858 if s := fmt.Sprintf("%#v", val); show != s { 859 show += " (value " + s + ")" 860 } 861 return show 862} 863 864// evalunsafe evaluates a package unsafe operation and returns the result. 865func evalunsafe(n ir.Node) int64 { 866 switch n.Op() { 867 case ir.OALIGNOF, ir.OSIZEOF: 868 n := n.(*ir.UnaryExpr) 869 n.X = Expr(n.X) 870 n.X = DefaultLit(n.X, nil) 871 tr := n.X.Type() 872 if tr == nil { 873 return 0 874 } 875 types.CalcSize(tr) 876 if n.Op() == ir.OALIGNOF { 877 return tr.Alignment() 878 } 879 return tr.Size() 880 881 case ir.OOFFSETOF: 882 // must be a selector. 883 n := n.(*ir.UnaryExpr) 884 // ODOT and ODOTPTR are allowed in case the OXDOT transformation has 885 // already happened (e.g. during -G=3 stenciling). 886 if n.X.Op() != ir.OXDOT && n.X.Op() != ir.ODOT && n.X.Op() != ir.ODOTPTR { 887 base.Errorf("invalid expression %v", n) 888 return 0 889 } 890 sel := n.X.(*ir.SelectorExpr) 891 892 // Remember base of selector to find it back after dot insertion. 893 // Since r->left may be mutated by typechecking, check it explicitly 894 // first to track it correctly. 895 sel.X = Expr(sel.X) 896 sbase := sel.X 897 898 tsel := Expr(sel) 899 n.X = tsel 900 if tsel.Type() == nil { 901 return 0 902 } 903 switch tsel.Op() { 904 case ir.ODOT, ir.ODOTPTR: 905 break 906 case ir.OMETHVALUE: 907 base.Errorf("invalid expression %v: argument is a method value", n) 908 return 0 909 default: 910 base.Errorf("invalid expression %v", n) 911 return 0 912 } 913 914 // Sum offsets for dots until we reach sbase. 915 var v int64 916 var next ir.Node 917 for r := tsel; r != sbase; r = next { 918 switch r.Op() { 919 case ir.ODOTPTR: 920 // For Offsetof(s.f), s may itself be a pointer, 921 // but accessing f must not otherwise involve 922 // indirection via embedded pointer types. 923 r := r.(*ir.SelectorExpr) 924 if r.X != sbase { 925 base.Errorf("invalid expression %v: selector implies indirection of embedded %v", n, r.X) 926 return 0 927 } 928 fallthrough 929 case ir.ODOT: 930 r := r.(*ir.SelectorExpr) 931 v += r.Offset() 932 next = r.X 933 default: 934 ir.Dump("unsafenmagic", tsel) 935 base.Fatalf("impossible %v node after dot insertion", r.Op()) 936 } 937 } 938 return v 939 } 940 941 base.Fatalf("unexpected op %v", n.Op()) 942 return 0 943} 944