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