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