representableConst reports whether x can be represented as value of the given basic type and for the configuration provided (only needed for int/uint sizes). If rounded != nil, *rounded is set to the rounded value of x for representable floating-point and complex values, and to an Int value for int
(x constant.Value, check *Checker, typ *Basic, rounded *constant.Value)
| 284 | // (indirectly) through an exported API call (AssignableTo, ConvertibleTo) |
| 285 | // because we don't need the Checker's config for those calls. |
| 286 | func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *constant.Value) bool { |
| 287 | if x.Kind() == constant.Unknown { |
| 288 | return true // avoid follow-up errors |
| 289 | } |
| 290 | |
| 291 | var conf *Config |
| 292 | if check != nil { |
| 293 | conf = check.conf |
| 294 | } |
| 295 | |
| 296 | switch { |
| 297 | case isInteger(typ): |
| 298 | x := constant.ToInt(x) |
| 299 | if x.Kind() != constant.Int { |
| 300 | return false |
| 301 | } |
| 302 | if rounded != nil { |
| 303 | *rounded = x |
| 304 | } |
| 305 | if x, ok := constant.Int64Val(x); ok { |
| 306 | switch typ.kind { |
| 307 | case Int: |
| 308 | var s = uint(conf.sizeof(typ)) * 8 |
| 309 | return int64(-1)<<(s-1) <= x && x <= int64(1)<<(s-1)-1 |
| 310 | case Int8: |
| 311 | const s = 8 |
| 312 | return -1<<(s-1) <= x && x <= 1<<(s-1)-1 |
| 313 | case Int16: |
| 314 | const s = 16 |
| 315 | return -1<<(s-1) <= x && x <= 1<<(s-1)-1 |
| 316 | case Int32: |
| 317 | const s = 32 |
| 318 | return -1<<(s-1) <= x && x <= 1<<(s-1)-1 |
| 319 | case Int64, UntypedInt: |
| 320 | return true |
| 321 | case Uint, Uintptr: |
| 322 | if s := uint(conf.sizeof(typ)) * 8; s < 64 { |
| 323 | return 0 <= x && x <= int64(1)<<s-1 |
| 324 | } |
| 325 | return 0 <= x |
| 326 | case Uint8: |
| 327 | const s = 8 |
| 328 | return 0 <= x && x <= 1<<s-1 |
| 329 | case Uint16: |
| 330 | const s = 16 |
| 331 | return 0 <= x && x <= 1<<s-1 |
| 332 | case Uint32: |
| 333 | const s = 32 |
| 334 | return 0 <= x && x <= 1<<s-1 |
| 335 | case Uint64: |
| 336 | return 0 <= x |
| 337 | default: |
| 338 | unreachable() |
| 339 | } |
| 340 | } |
| 341 | // x does not fit into int64 |
| 342 | switch n := constant.BitLen(x); typ.kind { |
| 343 | case Uint, Uintptr: |
no test coverage detected