Source file
src/go/types/const.go
1
2
3
4
5
6
7
8
9 package types
10
11 import (
12 "go/constant"
13 "go/token"
14 . "internal/types/errors"
15 "math"
16 )
17
18
19
20
21 func (check *Checker) overflow(x *operand, opPos token.Pos) {
22 assert(x.mode == constant_)
23
24 if x.val.Kind() == constant.Unknown {
25
26
27
28 check.error(atPos(opPos), InvalidConstVal, "constant result is not representable")
29 return
30 }
31
32
33
34
35
36 if isTyped(x.typ) {
37 check.representable(x, under(x.typ).(*Basic))
38 return
39 }
40
41
42 const prec = 512
43 if x.val.Kind() == constant.Int && constant.BitLen(x.val) > prec {
44 op := opName(x.expr)
45 if op != "" {
46 op += " "
47 }
48 check.errorf(atPos(opPos), InvalidConstVal, "constant %soverflow", op)
49 x.val = constant.MakeUnknown()
50 }
51 }
52
53
54
55
56
57
58
59
60
61
62
63
64
65 func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *constant.Value) bool {
66 if x.Kind() == constant.Unknown {
67 return true
68 }
69
70 var conf *Config
71 if check != nil {
72 conf = check.conf
73 }
74
75 sizeof := func(T Type) int64 {
76 s := conf.sizeof(T)
77 return s
78 }
79
80 switch {
81 case isInteger(typ):
82 x := constant.ToInt(x)
83 if x.Kind() != constant.Int {
84 return false
85 }
86 if rounded != nil {
87 *rounded = x
88 }
89 if x, ok := constant.Int64Val(x); ok {
90 switch typ.kind {
91 case Int:
92 var s = uint(sizeof(typ)) * 8
93 return int64(-1)<<(s-1) <= x && x <= int64(1)<<(s-1)-1
94 case Int8:
95 const s = 8
96 return -1<<(s-1) <= x && x <= 1<<(s-1)-1
97 case Int16:
98 const s = 16
99 return -1<<(s-1) <= x && x <= 1<<(s-1)-1
100 case Int32:
101 const s = 32
102 return -1<<(s-1) <= x && x <= 1<<(s-1)-1
103 case Int64, UntypedInt:
104 return true
105 case Uint, Uintptr:
106 if s := uint(sizeof(typ)) * 8; s < 64 {
107 return 0 <= x && x <= int64(1)<<s-1
108 }
109 return 0 <= x
110 case Uint8:
111 const s = 8
112 return 0 <= x && x <= 1<<s-1
113 case Uint16:
114 const s = 16
115 return 0 <= x && x <= 1<<s-1
116 case Uint32:
117 const s = 32
118 return 0 <= x && x <= 1<<s-1
119 case Uint64:
120 return 0 <= x
121 default:
122 unreachable()
123 }
124 }
125
126 switch n := constant.BitLen(x); typ.kind {
127 case Uint, Uintptr:
128 var s = uint(sizeof(typ)) * 8
129 return constant.Sign(x) >= 0 && n <= int(s)
130 case Uint64:
131 return constant.Sign(x) >= 0 && n <= 64
132 case UntypedInt:
133 return true
134 }
135
136 case isFloat(typ):
137 x := constant.ToFloat(x)
138 if x.Kind() != constant.Float {
139 return false
140 }
141 switch typ.kind {
142 case Float32:
143 if rounded == nil {
144 return fitsFloat32(x)
145 }
146 r := roundFloat32(x)
147 if r != nil {
148 *rounded = r
149 return true
150 }
151 case Float64:
152 if rounded == nil {
153 return fitsFloat64(x)
154 }
155 r := roundFloat64(x)
156 if r != nil {
157 *rounded = r
158 return true
159 }
160 case UntypedFloat:
161 return true
162 default:
163 unreachable()
164 }
165
166 case isComplex(typ):
167 x := constant.ToComplex(x)
168 if x.Kind() != constant.Complex {
169 return false
170 }
171 switch typ.kind {
172 case Complex64:
173 if rounded == nil {
174 return fitsFloat32(constant.Real(x)) && fitsFloat32(constant.Imag(x))
175 }
176 re := roundFloat32(constant.Real(x))
177 im := roundFloat32(constant.Imag(x))
178 if re != nil && im != nil {
179 *rounded = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
180 return true
181 }
182 case Complex128:
183 if rounded == nil {
184 return fitsFloat64(constant.Real(x)) && fitsFloat64(constant.Imag(x))
185 }
186 re := roundFloat64(constant.Real(x))
187 im := roundFloat64(constant.Imag(x))
188 if re != nil && im != nil {
189 *rounded = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
190 return true
191 }
192 case UntypedComplex:
193 return true
194 default:
195 unreachable()
196 }
197
198 case isString(typ):
199 return x.Kind() == constant.String
200
201 case isBoolean(typ):
202 return x.Kind() == constant.Bool
203 }
204
205 return false
206 }
207
208 func fitsFloat32(x constant.Value) bool {
209 f32, _ := constant.Float32Val(x)
210 f := float64(f32)
211 return !math.IsInf(f, 0)
212 }
213
214 func roundFloat32(x constant.Value) constant.Value {
215 f32, _ := constant.Float32Val(x)
216 f := float64(f32)
217 if !math.IsInf(f, 0) {
218 return constant.MakeFloat64(f)
219 }
220 return nil
221 }
222
223 func fitsFloat64(x constant.Value) bool {
224 f, _ := constant.Float64Val(x)
225 return !math.IsInf(f, 0)
226 }
227
228 func roundFloat64(x constant.Value) constant.Value {
229 f, _ := constant.Float64Val(x)
230 if !math.IsInf(f, 0) {
231 return constant.MakeFloat64(f)
232 }
233 return nil
234 }
235
236
237
238 func (check *Checker) representable(x *operand, typ *Basic) {
239 v, code := check.representation(x, typ)
240 if code != 0 {
241 check.invalidConversion(code, x, typ)
242 x.mode = invalid
243 return
244 }
245 assert(v != nil)
246 x.val = v
247 }
248
249
250
251
252
253 func (check *Checker) representation(x *operand, typ *Basic) (constant.Value, Code) {
254 assert(x.mode == constant_)
255 v := x.val
256 if !representableConst(x.val, check, typ, &v) {
257 if isNumeric(x.typ) && isNumeric(typ) {
258
259
260
261
262
263
264
265 if !isInteger(x.typ) && isInteger(typ) {
266 return nil, TruncatedFloat
267 } else {
268 return nil, NumericOverflow
269 }
270 }
271 return nil, InvalidConstVal
272 }
273 return v, 0
274 }
275
276 func (check *Checker) invalidConversion(code Code, x *operand, target Type) {
277 msg := "cannot convert %s to type %s"
278 switch code {
279 case TruncatedFloat:
280 msg = "%s truncated to %s"
281 case NumericOverflow:
282 msg = "%s overflows %s"
283 }
284 check.errorf(x, code, msg, x, target)
285 }
286
287
288 func (check *Checker) convertUntyped(x *operand, target Type) {
289 newType, val, code := check.implicitTypeAndValue(x, target)
290 if code != 0 {
291 t := target
292 if !isTypeParam(target) {
293 t = safeUnderlying(target)
294 }
295 check.invalidConversion(code, x, t)
296 x.mode = invalid
297 return
298 }
299 if val != nil {
300 x.val = val
301 check.updateExprVal(x.expr, val)
302 }
303 if newType != x.typ {
304 x.typ = newType
305 check.updateExprType(x.expr, newType, false)
306 }
307 }
308
View as plain text