@@ -207,7 +207,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
207
207
return
208
208
}
209
209
210
- // Convert or check untyped arguments.
210
+ // convert or check untyped arguments
211
211
d := 0
212
212
if isUntyped (x .typ ) {
213
213
d |= 1
@@ -231,7 +231,8 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
231
231
// 2) if one of them is not constant (possible because
232
232
// it contains a shift that is yet untyped), convert
233
233
// both of them to float64 since they must have the
234
- // same type to succeed
234
+ // same type to succeed (this will result in an error
235
+ // because shifts of floats are not permitted)
235
236
if x .mode == constant_ && y .mode == constant_ {
236
237
toFloat := func (x * operand ) {
237
238
if isNumeric (x .typ ) && constant .Sign (constant .Imag (x .val )) == 0 {
@@ -243,6 +244,8 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
243
244
} else {
244
245
check .convertUntyped (x , Typ [Float64 ])
245
246
check .convertUntyped (& y , Typ [Float64 ])
247
+ // x and y should be invalid now, but be conservative
248
+ // and check below
246
249
}
247
250
}
248
251
if x .mode == invalid || y .mode == invalid {
@@ -261,7 +264,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
261
264
return
262
265
}
263
266
264
- // if both arguments are constant , the result is a constant
267
+ // if both arguments are constants , the result is a constant
265
268
if x .mode == constant_ && y .mode == constant_ {
266
269
x .val = constant .BinaryOp (x .val , token .ADD , constant .MakeImag (y .val ))
267
270
} else {
@@ -351,10 +354,35 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
351
354
case _Imag , _Real :
352
355
// imag(complexT) floatT
353
356
// real(complexT) floatT
357
+
358
+ // convert or check untyped argument
359
+ if isUntyped (x .typ ) {
360
+ if x .mode == constant_ {
361
+ // an untyped constant number can alway be considered
362
+ // as a complex constant
363
+ if isNumeric (x .typ ) {
364
+ x .typ = Typ [UntypedComplex ]
365
+ }
366
+ } else {
367
+ // an untyped non-constant argument may appear if
368
+ // it contains a (yet untyped non-constant) shift
369
+ // epression: convert it to complex128 which will
370
+ // result in an error (shift of complex value)
371
+ check .convertUntyped (x , Typ [Complex128 ])
372
+ // x should be invalid now, but be conservative and check
373
+ if x .mode == invalid {
374
+ return
375
+ }
376
+ }
377
+ }
378
+
379
+ // the argument must be of complex type
354
380
if ! isComplex (x .typ ) {
355
- check .invalidArg (x .pos (), "%s must be a complex number " , x )
381
+ check .invalidArg (x .pos (), "argument has type %s, expected complex type " , x . typ )
356
382
return
357
383
}
384
+
385
+ // if the argument is a constant, the result is a constant
358
386
if x .mode == constant_ {
359
387
if id == _Real {
360
388
x .val = constant .Real (x .val )
@@ -364,22 +392,26 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
364
392
} else {
365
393
x .mode = value
366
394
}
367
- var k BasicKind
395
+
396
+ // determine result type
397
+ var res BasicKind
368
398
switch x .typ .Underlying ().(* Basic ).kind {
369
399
case Complex64 :
370
- k = Float32
400
+ res = Float32
371
401
case Complex128 :
372
- k = Float64
402
+ res = Float64
373
403
case UntypedComplex :
374
- k = UntypedFloat
404
+ res = UntypedFloat
375
405
default :
376
406
unreachable ()
377
407
}
408
+ resTyp := Typ [res ]
378
409
379
410
if check .Types != nil && x .mode != constant_ {
380
- check .recordBuiltinType (call .Fun , makeSig (Typ [ k ] , x .typ ))
411
+ check .recordBuiltinType (call .Fun , makeSig (resTyp , x .typ ))
381
412
}
382
- x .typ = Typ [k ]
413
+
414
+ x .typ = resTyp
383
415
384
416
case _Make :
385
417
// make(T, n)
0 commit comments