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	"unicode"
14
15	"cmd/compile/internal/base"
16	"cmd/compile/internal/ir"
17	"cmd/compile/internal/types"
18)
19
20func roundFloat(v constant.Value, sz int64) constant.Value {
21	switch sz {
22	case 4:
23		f, _ := constant.Float32Val(v)
24		return makeFloat64(float64(f))
25	case 8:
26		f, _ := constant.Float64Val(v)
27		return makeFloat64(f)
28	}
29	base.Fatalf("unexpected size: %v", sz)
30	panic("unreachable")
31}
32
33// truncate float literal fv to 32-bit or 64-bit precision
34// according to type; return truncated value.
35func truncfltlit(v constant.Value, t *types.Type) constant.Value {
36	if t.IsUntyped() {
37		return v
38	}
39
40	return roundFloat(v, t.Size())
41}
42
43// truncate Real and Imag parts of Mpcplx to 32-bit or 64-bit
44// precision, according to type; return truncated value. In case of
45// overflow, calls Errorf but does not truncate the input value.
46func trunccmplxlit(v constant.Value, t *types.Type) constant.Value {
47	if t.IsUntyped() {
48		return v
49	}
50
51	fsz := t.Size() / 2
52	return makeComplex(roundFloat(constant.Real(v), fsz), roundFloat(constant.Imag(v), fsz))
53}
54
55// TODO(mdempsky): Replace these with better APIs.
56func convlit(n ir.Node, t *types.Type) ir.Node    { return convlit1(n, t, false, nil) }
57func DefaultLit(n ir.Node, t *types.Type) ir.Node { return convlit1(n, t, false, nil) }
58
59// convlit1 converts an untyped expression n to type t. If n already
60// has a type, convlit1 has no effect.
61//
62// For explicit conversions, t must be non-nil, and integer-to-string
63// conversions are allowed.
64//
65// For implicit conversions (e.g., assignments), t may be nil; if so,
66// n is converted to its default type.
67//
68// If there's an error converting n to t, context is used in the error
69// message.
70func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir.Node {
71	if explicit && t == nil {
72		base.Fatalf("explicit conversion missing type")
73	}
74	if t != nil && t.IsUntyped() {
75		base.Fatalf("bad conversion to untyped: %v", t)
76	}
77
78	if n == nil || n.Type() == nil {
79		// Allow sloppy callers.
80		return n
81	}
82	if !n.Type().IsUntyped() {
83		// Already typed; nothing to do.
84		return n
85	}
86
87	// Nil is technically not a constant, so handle it specially.
88	if n.Type().Kind() == types.TNIL {
89		if n.Op() != ir.ONIL {
90			base.Fatalf("unexpected op: %v (%v)", n, n.Op())
91		}
92		n = ir.Copy(n)
93		if t == nil {
94			base.Fatalf("use of untyped nil")
95		}
96
97		if !t.HasNil() {
98			// Leave for caller to handle.
99			return n
100		}
101
102		n.SetType(t)
103		return n
104	}
105
106	if t == nil || !ir.OKForConst[t.Kind()] {
107		t = defaultType(n.Type())
108	}
109
110	switch n.Op() {
111	default:
112		base.Fatalf("unexpected untyped expression: %v", n)
113
114	case ir.OLITERAL:
115		v := ConvertVal(n.Val(), t, explicit)
116		if v.Kind() == constant.Unknown {
117			n = ir.NewConstExpr(n.Val(), n)
118			break
119		}
120		n = ir.NewConstExpr(v, n)
121		n.SetType(t)
122		return n
123
124	case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.OREAL, ir.OIMAG:
125		ot := operandType(n.Op(), t)
126		if ot == nil {
127			n = DefaultLit(n, nil)
128			break
129		}
130
131		n := n.(*ir.UnaryExpr)
132		n.X = convlit(n.X, ot)
133		if n.X.Type() == nil {
134			n.SetType(nil)
135			return n
136		}
137		n.SetType(t)
138		return n
139
140	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:
141		ot := operandType(n.Op(), t)
142		if ot == nil {
143			n = DefaultLit(n, nil)
144			break
145		}
146
147		var l, r ir.Node
148		switch n := n.(type) {
149		case *ir.BinaryExpr:
150			n.X = convlit(n.X, ot)
151			n.Y = convlit(n.Y, ot)
152			l, r = n.X, n.Y
153		case *ir.LogicalExpr:
154			n.X = convlit(n.X, ot)
155			n.Y = convlit(n.Y, ot)
156			l, r = n.X, n.Y
157		}
158
159		if l.Type() == nil || r.Type() == nil {
160			n.SetType(nil)
161			return n
162		}
163		if !types.Identical(l.Type(), r.Type()) {
164			base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type())
165			n.SetType(nil)
166			return n
167		}
168
169		n.SetType(t)
170		return n
171
172	case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
173		n := n.(*ir.BinaryExpr)
174		if !t.IsBoolean() {
175			break
176		}
177		n.SetType(t)
178		return n
179
180	case ir.OLSH, ir.ORSH:
181		n := n.(*ir.BinaryExpr)
182		n.X = convlit1(n.X, t, explicit, nil)
183		n.SetType(n.X.Type())
184		if n.Type() != nil && !n.Type().IsInteger() {
185			base.Errorf("invalid operation: %v (shift of type %v)", n, n.Type())
186			n.SetType(nil)
187		}
188		return n
189	}
190
191	if explicit {
192		base.Fatalf("cannot convert %L to type %v", n, t)
193	} else if context != nil {
194		base.Fatalf("cannot use %L as type %v in %s", n, t, context())
195	} else {
196		base.Fatalf("cannot use %L as type %v", n, t)
197	}
198
199	n.SetType(nil)
200	return n
201}
202
203func operandType(op ir.Op, t *types.Type) *types.Type {
204	switch op {
205	case ir.OCOMPLEX:
206		if t.IsComplex() {
207			return types.FloatForComplex(t)
208		}
209	case ir.OREAL, ir.OIMAG:
210		if t.IsFloat() {
211			return types.ComplexForFloat(t)
212		}
213	default:
214		if okfor[op][t.Kind()] {
215			return t
216		}
217	}
218	return nil
219}
220
221// ConvertVal converts v into a representation appropriate for t. If
222// no such representation exists, it returns constant.MakeUnknown()
223// instead.
224//
225// If explicit is true, then conversions from integer to string are
226// also allowed.
227func ConvertVal(v constant.Value, t *types.Type, explicit bool) constant.Value {
228	switch ct := v.Kind(); ct {
229	case constant.Bool:
230		if t.IsBoolean() {
231			return v
232		}
233
234	case constant.String:
235		if t.IsString() {
236			return v
237		}
238
239	case constant.Int:
240		if explicit && t.IsString() {
241			return tostr(v)
242		}
243		fallthrough
244	case constant.Float, constant.Complex:
245		switch {
246		case t.IsInteger():
247			v = toint(v)
248			return v
249		case t.IsFloat():
250			v = toflt(v)
251			v = truncfltlit(v, t)
252			return v
253		case t.IsComplex():
254			v = tocplx(v)
255			v = trunccmplxlit(v, t)
256			return v
257		}
258	}
259
260	return constant.MakeUnknown()
261}
262
263func tocplx(v constant.Value) constant.Value {
264	return constant.ToComplex(v)
265}
266
267func toflt(v constant.Value) constant.Value {
268	if v.Kind() == constant.Complex {
269		v = constant.Real(v)
270	}
271
272	return constant.ToFloat(v)
273}
274
275func toint(v constant.Value) constant.Value {
276	if v.Kind() == constant.Complex {
277		v = constant.Real(v)
278	}
279
280	if v := constant.ToInt(v); v.Kind() == constant.Int {
281		return v
282	}
283
284	// The value of v cannot be represented as an integer;
285	// so we need to print an error message.
286	// Unfortunately some float values cannot be
287	// reasonably formatted for inclusion in an error
288	// message (example: 1 + 1e-100), so first we try to
289	// format the float; if the truncation resulted in
290	// something that looks like an integer we omit the
291	// value from the error message.
292	// (See issue #11371).
293	f := ir.BigFloat(v)
294	if f.MantExp(nil) > 2*ir.ConstPrec {
295		base.Errorf("integer too large")
296	} else {
297		var t big.Float
298		t.Parse(fmt.Sprint(v), 0)
299		if t.IsInt() {
300			base.Errorf("constant truncated to integer")
301		} else {
302			base.Errorf("constant %v truncated to integer", v)
303		}
304	}
305
306	// Prevent follow-on errors.
307	return constant.MakeUnknown()
308}
309
310func tostr(v constant.Value) constant.Value {
311	if v.Kind() == constant.Int {
312		r := unicode.ReplacementChar
313		if x, ok := constant.Uint64Val(v); ok && x <= unicode.MaxRune {
314			r = rune(x)
315		}
316		v = constant.MakeString(string(r))
317	}
318	return v
319}
320
321func makeFloat64(f float64) constant.Value {
322	if math.IsInf(f, 0) {
323		base.Fatalf("infinity is not a valid constant")
324	}
325	return constant.MakeFloat64(f)
326}
327
328func makeComplex(real, imag constant.Value) constant.Value {
329	return constant.BinaryOp(constant.ToFloat(real), token.ADD, constant.MakeImag(constant.ToFloat(imag)))
330}
331
332// DefaultLit on both nodes simultaneously;
333// if they're both ideal going in they better
334// get the same type going out.
335// force means must assign concrete (non-ideal) type.
336// The results of defaultlit2 MUST be assigned back to l and r, e.g.
337//
338//	n.Left, n.Right = defaultlit2(n.Left, n.Right, force)
339func defaultlit2(l ir.Node, r ir.Node, force bool) (ir.Node, ir.Node) {
340	if l.Type() == nil || r.Type() == nil {
341		return l, r
342	}
343
344	if !l.Type().IsInterface() && !r.Type().IsInterface() {
345		// Can't mix bool with non-bool, string with non-string.
346		if l.Type().IsBoolean() != r.Type().IsBoolean() {
347			return l, r
348		}
349		if l.Type().IsString() != r.Type().IsString() {
350			return l, r
351		}
352	}
353
354	if !l.Type().IsUntyped() {
355		r = convlit(r, l.Type())
356		return l, r
357	}
358
359	if !r.Type().IsUntyped() {
360		l = convlit(l, r.Type())
361		return l, r
362	}
363
364	if !force {
365		return l, r
366	}
367
368	// Can't mix nil with anything untyped.
369	if ir.IsNil(l) || ir.IsNil(r) {
370		return l, r
371	}
372	t := defaultType(mixUntyped(l.Type(), r.Type()))
373	l = convlit(l, t)
374	r = convlit(r, t)
375	return l, r
376}
377
378func mixUntyped(t1, t2 *types.Type) *types.Type {
379	if t1 == t2 {
380		return t1
381	}
382
383	rank := func(t *types.Type) int {
384		switch t {
385		case types.UntypedInt:
386			return 0
387		case types.UntypedRune:
388			return 1
389		case types.UntypedFloat:
390			return 2
391		case types.UntypedComplex:
392			return 3
393		}
394		base.Fatalf("bad type %v", t)
395		panic("unreachable")
396	}
397
398	if rank(t2) > rank(t1) {
399		return t2
400	}
401	return t1
402}
403
404func defaultType(t *types.Type) *types.Type {
405	if !t.IsUntyped() || t.Kind() == types.TNIL {
406		return t
407	}
408
409	switch t {
410	case types.UntypedBool:
411		return types.Types[types.TBOOL]
412	case types.UntypedString:
413		return types.Types[types.TSTRING]
414	case types.UntypedInt:
415		return types.Types[types.TINT]
416	case types.UntypedRune:
417		return types.RuneType
418	case types.UntypedFloat:
419		return types.Types[types.TFLOAT64]
420	case types.UntypedComplex:
421		return types.Types[types.TCOMPLEX128]
422	}
423
424	base.Fatalf("bad type %v", t)
425	return nil
426}
427
428// IndexConst checks if Node n contains a constant expression
429// representable as a non-negative int and returns its value.
430// If n is not a constant expression, not representable as an
431// integer, or negative, it returns -1. If n is too large, it
432// returns -2.
433func IndexConst(n ir.Node) int64 {
434	if n.Op() != ir.OLITERAL {
435		return -1
436	}
437	if !n.Type().IsInteger() && n.Type().Kind() != types.TIDEAL {
438		return -1
439	}
440
441	v := toint(n.Val())
442	if v.Kind() != constant.Int || constant.Sign(v) < 0 {
443		return -1
444	}
445	if ir.ConstOverflow(v, types.Types[types.TINT]) {
446		return -2
447	}
448	return ir.IntVal(types.Types[types.TINT], v)
449}
450
451// callOrChan reports whether n is a call or channel operation.
452func callOrChan(n ir.Node) bool {
453	switch n.Op() {
454	case ir.OAPPEND,
455		ir.OCALL,
456		ir.OCALLFUNC,
457		ir.OCALLINTER,
458		ir.OCALLMETH,
459		ir.OCAP,
460		ir.OCLEAR,
461		ir.OCLOSE,
462		ir.OCOMPLEX,
463		ir.OCOPY,
464		ir.ODELETE,
465		ir.OIMAG,
466		ir.OLEN,
467		ir.OMAKE,
468		ir.OMAX,
469		ir.OMIN,
470		ir.ONEW,
471		ir.OPANIC,
472		ir.OPRINT,
473		ir.OPRINTLN,
474		ir.OREAL,
475		ir.ORECOVER,
476		ir.ORECOVERFP,
477		ir.ORECV,
478		ir.OUNSAFEADD,
479		ir.OUNSAFESLICE,
480		ir.OUNSAFESLICEDATA,
481		ir.OUNSAFESTRING,
482		ir.OUNSAFESTRINGDATA:
483		return true
484	}
485	return false
486}
487