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