1// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT. 2// Source: ../../cmd/compile/internal/types2/const.go 3 4// Copyright 2023 The Go Authors. All rights reserved. 5// Use of this source code is governed by a BSD-style 6// license that can be found in the LICENSE file. 7 8// This file implements functions for untyped constant operands. 9 10package types 11 12import ( 13 "go/constant" 14 "go/token" 15 . "internal/types/errors" 16 "math" 17) 18 19// overflow checks that the constant x is representable by its type. 20// For untyped constants, it checks that the value doesn't become 21// arbitrarily large. 22func (check *Checker) overflow(x *operand, opPos token.Pos) { 23 assert(x.mode == constant_) 24 25 if x.val.Kind() == constant.Unknown { 26 // TODO(gri) We should report exactly what went wrong. At the 27 // moment we don't have the (go/constant) API for that. 28 // See also TODO in go/constant/value.go. 29 check.error(atPos(opPos), InvalidConstVal, "constant result is not representable") 30 return 31 } 32 33 // Typed constants must be representable in 34 // their type after each constant operation. 35 // x.typ cannot be a type parameter (type 36 // parameters cannot be constant types). 37 if isTyped(x.typ) { 38 check.representable(x, under(x.typ).(*Basic)) 39 return 40 } 41 42 // Untyped integer values must not grow arbitrarily. 43 const prec = 512 // 512 is the constant precision 44 if x.val.Kind() == constant.Int && constant.BitLen(x.val) > prec { 45 op := opName(x.expr) 46 if op != "" { 47 op += " " 48 } 49 check.errorf(atPos(opPos), InvalidConstVal, "constant %soverflow", op) 50 x.val = constant.MakeUnknown() 51 } 52} 53 54// representableConst reports whether x can be represented as 55// value of the given basic type and for the configuration 56// provided (only needed for int/uint sizes). 57// 58// If rounded != nil, *rounded is set to the rounded value of x for 59// representable floating-point and complex values, and to an Int 60// value for integer values; it is left alone otherwise. 61// It is ok to provide the addressof the first argument for rounded. 62// 63// The check parameter may be nil if representableConst is invoked 64// (indirectly) through an exported API call (AssignableTo, ConvertibleTo) 65// because we don't need the Checker's config for those calls. 66func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *constant.Value) bool { 67 if x.Kind() == constant.Unknown { 68 return true // avoid follow-up errors 69 } 70 71 var conf *Config 72 if check != nil { 73 conf = check.conf 74 } 75 76 sizeof := func(T Type) int64 { 77 s := conf.sizeof(T) 78 return s 79 } 80 81 switch { 82 case isInteger(typ): 83 x := constant.ToInt(x) 84 if x.Kind() != constant.Int { 85 return false 86 } 87 if rounded != nil { 88 *rounded = x 89 } 90 if x, ok := constant.Int64Val(x); ok { 91 switch typ.kind { 92 case Int: 93 var s = uint(sizeof(typ)) * 8 94 return int64(-1)<<(s-1) <= x && x <= int64(1)<<(s-1)-1 95 case Int8: 96 const s = 8 97 return -1<<(s-1) <= x && x <= 1<<(s-1)-1 98 case Int16: 99 const s = 16 100 return -1<<(s-1) <= x && x <= 1<<(s-1)-1 101 case Int32: 102 const s = 32 103 return -1<<(s-1) <= x && x <= 1<<(s-1)-1 104 case Int64, UntypedInt: 105 return true 106 case Uint, Uintptr: 107 if s := uint(sizeof(typ)) * 8; s < 64 { 108 return 0 <= x && x <= int64(1)<<s-1 109 } 110 return 0 <= x 111 case Uint8: 112 const s = 8 113 return 0 <= x && x <= 1<<s-1 114 case Uint16: 115 const s = 16 116 return 0 <= x && x <= 1<<s-1 117 case Uint32: 118 const s = 32 119 return 0 <= x && x <= 1<<s-1 120 case Uint64: 121 return 0 <= x 122 default: 123 panic("unreachable") 124 } 125 } 126 // x does not fit into int64 127 switch n := constant.BitLen(x); typ.kind { 128 case Uint, Uintptr: 129 var s = uint(sizeof(typ)) * 8 130 return constant.Sign(x) >= 0 && n <= int(s) 131 case Uint64: 132 return constant.Sign(x) >= 0 && n <= 64 133 case UntypedInt: 134 return true 135 } 136 137 case isFloat(typ): 138 x := constant.ToFloat(x) 139 if x.Kind() != constant.Float { 140 return false 141 } 142 switch typ.kind { 143 case Float32: 144 if rounded == nil { 145 return fitsFloat32(x) 146 } 147 r := roundFloat32(x) 148 if r != nil { 149 *rounded = r 150 return true 151 } 152 case Float64: 153 if rounded == nil { 154 return fitsFloat64(x) 155 } 156 r := roundFloat64(x) 157 if r != nil { 158 *rounded = r 159 return true 160 } 161 case UntypedFloat: 162 return true 163 default: 164 panic("unreachable") 165 } 166 167 case isComplex(typ): 168 x := constant.ToComplex(x) 169 if x.Kind() != constant.Complex { 170 return false 171 } 172 switch typ.kind { 173 case Complex64: 174 if rounded == nil { 175 return fitsFloat32(constant.Real(x)) && fitsFloat32(constant.Imag(x)) 176 } 177 re := roundFloat32(constant.Real(x)) 178 im := roundFloat32(constant.Imag(x)) 179 if re != nil && im != nil { 180 *rounded = constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) 181 return true 182 } 183 case Complex128: 184 if rounded == nil { 185 return fitsFloat64(constant.Real(x)) && fitsFloat64(constant.Imag(x)) 186 } 187 re := roundFloat64(constant.Real(x)) 188 im := roundFloat64(constant.Imag(x)) 189 if re != nil && im != nil { 190 *rounded = constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) 191 return true 192 } 193 case UntypedComplex: 194 return true 195 default: 196 panic("unreachable") 197 } 198 199 case isString(typ): 200 return x.Kind() == constant.String 201 202 case isBoolean(typ): 203 return x.Kind() == constant.Bool 204 } 205 206 return false 207} 208 209func fitsFloat32(x constant.Value) bool { 210 f32, _ := constant.Float32Val(x) 211 f := float64(f32) 212 return !math.IsInf(f, 0) 213} 214 215func roundFloat32(x constant.Value) constant.Value { 216 f32, _ := constant.Float32Val(x) 217 f := float64(f32) 218 if !math.IsInf(f, 0) { 219 return constant.MakeFloat64(f) 220 } 221 return nil 222} 223 224func fitsFloat64(x constant.Value) bool { 225 f, _ := constant.Float64Val(x) 226 return !math.IsInf(f, 0) 227} 228 229func roundFloat64(x constant.Value) constant.Value { 230 f, _ := constant.Float64Val(x) 231 if !math.IsInf(f, 0) { 232 return constant.MakeFloat64(f) 233 } 234 return nil 235} 236 237// representable checks that a constant operand is representable in the given 238// basic type. 239func (check *Checker) representable(x *operand, typ *Basic) { 240 v, code := check.representation(x, typ) 241 if code != 0 { 242 check.invalidConversion(code, x, typ) 243 x.mode = invalid 244 return 245 } 246 assert(v != nil) 247 x.val = v 248} 249 250// representation returns the representation of the constant operand x as the 251// basic type typ. 252// 253// If no such representation is possible, it returns a non-zero error code. 254func (check *Checker) representation(x *operand, typ *Basic) (constant.Value, Code) { 255 assert(x.mode == constant_) 256 v := x.val 257 if !representableConst(x.val, check, typ, &v) { 258 if isNumeric(x.typ) && isNumeric(typ) { 259 // numeric conversion : error msg 260 // 261 // integer -> integer : overflows 262 // integer -> float : overflows (actually not possible) 263 // float -> integer : truncated 264 // float -> float : overflows 265 // 266 if !isInteger(x.typ) && isInteger(typ) { 267 return nil, TruncatedFloat 268 } else { 269 return nil, NumericOverflow 270 } 271 } 272 return nil, InvalidConstVal 273 } 274 return v, 0 275} 276 277func (check *Checker) invalidConversion(code Code, x *operand, target Type) { 278 msg := "cannot convert %s to type %s" 279 switch code { 280 case TruncatedFloat: 281 msg = "%s truncated to %s" 282 case NumericOverflow: 283 msg = "%s overflows %s" 284 } 285 check.errorf(x, code, msg, x, target) 286} 287 288// convertUntyped attempts to set the type of an untyped value to the target type. 289func (check *Checker) convertUntyped(x *operand, target Type) { 290 newType, val, code := check.implicitTypeAndValue(x, target) 291 if code != 0 { 292 t := target 293 if !isTypeParam(target) { 294 t = safeUnderlying(target) 295 } 296 check.invalidConversion(code, x, t) 297 x.mode = invalid 298 return 299 } 300 if val != nil { 301 x.val = val 302 check.updateExprVal(x.expr, val) 303 } 304 if newType != x.typ { 305 x.typ = newType 306 check.updateExprType(x.expr, newType, false) 307 } 308} 309