Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/compile/internal/typecheck/const.go

Documentation: cmd/compile/internal/typecheck

     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  
     5  package typecheck
     6  
     7  import (
     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  
    22  func 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.
    37  func 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.
    51  func 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.
    64  func convlit(n ir.Node, t *types.Type) ir.Node    { return convlit1(n, t, false, nil) }
    65  func 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.
    78  func 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  
   218  func 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.
   241  func 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  
   278  func tocplx(v constant.Value) constant.Value {
   279  	return constant.ToComplex(v)
   280  }
   281  
   282  func 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  
   293  func 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.
   334  func 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  
   351  func 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  
   362  var 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.
   395  func 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  
   567  func 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  
   574  func makeComplex(real, imag constant.Value) constant.Value {
   575  	return constant.BinaryOp(constant.ToFloat(real), token.ADD, constant.MakeImag(constant.ToFloat(imag)))
   576  }
   577  
   578  func 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.
   584  var 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.
   594  func 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  
   618  func OrigBool(n ir.Node, v bool) ir.Node {
   619  	return OrigConst(n, constant.MakeBool(v))
   620  }
   621  
   622  func 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)
   632  func 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  
   671  func 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  
   697  func 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.
   726  func 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.
   745  func 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.
   777  type constSet struct {
   778  	m map[constSetKey]src.XPos
   779  }
   780  
   781  type 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.
   795  func (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.
   855  func 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.
   865  func 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 int64(tr.Align)
   878  		}
   879  		return tr.Width
   880  
   881  	case ir.OOFFSETOF:
   882  		// must be a selector.
   883  		n := n.(*ir.UnaryExpr)
   884  		if n.X.Op() != ir.OXDOT {
   885  			base.Errorf("invalid expression %v", n)
   886  			return 0
   887  		}
   888  		sel := n.X.(*ir.SelectorExpr)
   889  
   890  		// Remember base of selector to find it back after dot insertion.
   891  		// Since r->left may be mutated by typechecking, check it explicitly
   892  		// first to track it correctly.
   893  		sel.X = Expr(sel.X)
   894  		sbase := sel.X
   895  
   896  		tsel := Expr(sel)
   897  		n.X = tsel
   898  		if tsel.Type() == nil {
   899  			return 0
   900  		}
   901  		switch tsel.Op() {
   902  		case ir.ODOT, ir.ODOTPTR:
   903  			break
   904  		case ir.OCALLPART:
   905  			base.Errorf("invalid expression %v: argument is a method value", n)
   906  			return 0
   907  		default:
   908  			base.Errorf("invalid expression %v", n)
   909  			return 0
   910  		}
   911  
   912  		// Sum offsets for dots until we reach sbase.
   913  		var v int64
   914  		var next ir.Node
   915  		for r := tsel; r != sbase; r = next {
   916  			switch r.Op() {
   917  			case ir.ODOTPTR:
   918  				// For Offsetof(s.f), s may itself be a pointer,
   919  				// but accessing f must not otherwise involve
   920  				// indirection via embedded pointer types.
   921  				r := r.(*ir.SelectorExpr)
   922  				if r.X != sbase {
   923  					base.Errorf("invalid expression %v: selector implies indirection of embedded %v", n, r.X)
   924  					return 0
   925  				}
   926  				fallthrough
   927  			case ir.ODOT:
   928  				r := r.(*ir.SelectorExpr)
   929  				v += r.Offset()
   930  				next = r.X
   931  			default:
   932  				ir.Dump("unsafenmagic", tsel)
   933  				base.Fatalf("impossible %v node after dot insertion", r.Op())
   934  			}
   935  		}
   936  		return v
   937  	}
   938  
   939  	base.Fatalf("unexpected op %v", n.Op())
   940  	return 0
   941  }
   942  

View as plain text