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