// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
// Source: ../../cmd/compile/internal/types2/const.go

// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements functions for untyped constant operands.

package types

import (
	
	
	. 
	
)

// overflow checks that the constant x is representable by its type.
// For untyped constants, it checks that the value doesn't become
// arbitrarily large.
func ( *Checker) ( *operand,  token.Pos) {
	assert(.mode == constant_)

	if .val.Kind() == constant.Unknown {
		// TODO(gri) We should report exactly what went wrong. At the
		//           moment we don't have the (go/constant) API for that.
		//           See also TODO in go/constant/value.go.
		.error(atPos(), InvalidConstVal, "constant result is not representable")
		return
	}

	// Typed constants must be representable in
	// their type after each constant operation.
	// x.typ cannot be a type parameter (type
	// parameters cannot be constant types).
	if isTyped(.typ) {
		.representable(, under(.typ).(*Basic))
		return
	}

	// Untyped integer values must not grow arbitrarily.
	const  = 512 // 512 is the constant precision
	if .val.Kind() == constant.Int && constant.BitLen(.val) >  {
		 := opName(.expr)
		if  != "" {
			 += " "
		}
		.errorf(atPos(), InvalidConstVal, "constant %soverflow", )
		.val = constant.MakeUnknown()
	}
}

// representableConst reports whether x can be represented as
// value of the given basic type and for the configuration
// provided (only needed for int/uint sizes).
//
// If rounded != nil, *rounded is set to the rounded value of x for
// representable floating-point and complex values, and to an Int
// value for integer values; it is left alone otherwise.
// It is ok to provide the addressof the first argument for rounded.
//
// The check parameter may be nil if representableConst is invoked
// (indirectly) through an exported API call (AssignableTo, ConvertibleTo)
// because we don't need the Checker's config for those calls.
func representableConst( constant.Value,  *Checker,  *Basic,  *constant.Value) bool {
	if .Kind() == constant.Unknown {
		return true // avoid follow-up errors
	}

	var  *Config
	if  != nil {
		 = .conf
	}

	 := func( Type) int64 {
		 := .sizeof()
		return 
	}

	switch {
	case isInteger():
		 := constant.ToInt()
		if .Kind() != constant.Int {
			return false
		}
		if  != nil {
			* = 
		}
		if ,  := constant.Int64Val();  {
			switch .kind {
			case Int:
				var  = uint(()) * 8
				return int64(-1)<<(-1) <=  &&  <= int64(1)<<(-1)-1
			case Int8:
				const  = 8
				return -1<<(-1) <=  &&  <= 1<<(-1)-1
			case Int16:
				const  = 16
				return -1<<(-1) <=  &&  <= 1<<(-1)-1
			case Int32:
				const  = 32
				return -1<<(-1) <=  &&  <= 1<<(-1)-1
			case Int64, UntypedInt:
				return true
			case Uint, Uintptr:
				if  := uint(()) * 8;  < 64 {
					return 0 <=  &&  <= int64(1)<<-1
				}
				return 0 <= 
			case Uint8:
				const  = 8
				return 0 <=  &&  <= 1<<-1
			case Uint16:
				const  = 16
				return 0 <=  &&  <= 1<<-1
			case Uint32:
				const  = 32
				return 0 <=  &&  <= 1<<-1
			case Uint64:
				return 0 <= 
			default:
				panic("unreachable")
			}
		}
		// x does not fit into int64
		switch  := constant.BitLen(); .kind {
		case Uint, Uintptr:
			var  = uint(()) * 8
			return constant.Sign() >= 0 &&  <= int()
		case Uint64:
			return constant.Sign() >= 0 &&  <= 64
		case UntypedInt:
			return true
		}

	case isFloat():
		 := constant.ToFloat()
		if .Kind() != constant.Float {
			return false
		}
		switch .kind {
		case Float32:
			if  == nil {
				return fitsFloat32()
			}
			 := roundFloat32()
			if  != nil {
				* = 
				return true
			}
		case Float64:
			if  == nil {
				return fitsFloat64()
			}
			 := roundFloat64()
			if  != nil {
				* = 
				return true
			}
		case UntypedFloat:
			return true
		default:
			panic("unreachable")
		}

	case isComplex():
		 := constant.ToComplex()
		if .Kind() != constant.Complex {
			return false
		}
		switch .kind {
		case Complex64:
			if  == nil {
				return fitsFloat32(constant.Real()) && fitsFloat32(constant.Imag())
			}
			 := roundFloat32(constant.Real())
			 := roundFloat32(constant.Imag())
			if  != nil &&  != nil {
				* = constant.BinaryOp(, token.ADD, constant.MakeImag())
				return true
			}
		case Complex128:
			if  == nil {
				return fitsFloat64(constant.Real()) && fitsFloat64(constant.Imag())
			}
			 := roundFloat64(constant.Real())
			 := roundFloat64(constant.Imag())
			if  != nil &&  != nil {
				* = constant.BinaryOp(, token.ADD, constant.MakeImag())
				return true
			}
		case UntypedComplex:
			return true
		default:
			panic("unreachable")
		}

	case isString():
		return .Kind() == constant.String

	case isBoolean():
		return .Kind() == constant.Bool
	}

	return false
}

func fitsFloat32( constant.Value) bool {
	,  := constant.Float32Val()
	 := float64()
	return !math.IsInf(, 0)
}

func roundFloat32( constant.Value) constant.Value {
	,  := constant.Float32Val()
	 := float64()
	if !math.IsInf(, 0) {
		return constant.MakeFloat64()
	}
	return nil
}

func fitsFloat64( constant.Value) bool {
	,  := constant.Float64Val()
	return !math.IsInf(, 0)
}

func roundFloat64( constant.Value) constant.Value {
	,  := constant.Float64Val()
	if !math.IsInf(, 0) {
		return constant.MakeFloat64()
	}
	return nil
}

// representable checks that a constant operand is representable in the given
// basic type.
func ( *Checker) ( *operand,  *Basic) {
	,  := .representation(, )
	if  != 0 {
		.invalidConversion(, , )
		.mode = invalid
		return
	}
	assert( != nil)
	.val = 
}

// representation returns the representation of the constant operand x as the
// basic type typ.
//
// If no such representation is possible, it returns a non-zero error code.
func ( *Checker) ( *operand,  *Basic) (constant.Value, Code) {
	assert(.mode == constant_)
	 := .val
	if !representableConst(.val, , , &) {
		if isNumeric(.typ) && isNumeric() {
			// numeric conversion : error msg
			//
			// integer -> integer : overflows
			// integer -> float   : overflows (actually not possible)
			// float   -> integer : truncated
			// float   -> float   : overflows
			//
			if !isInteger(.typ) && isInteger() {
				return nil, TruncatedFloat
			} else {
				return nil, NumericOverflow
			}
		}
		return nil, InvalidConstVal
	}
	return , 0
}

func ( *Checker) ( Code,  *operand,  Type) {
	 := "cannot convert %s to type %s"
	switch  {
	case TruncatedFloat:
		 = "%s truncated to %s"
	case NumericOverflow:
		 = "%s overflows %s"
	}
	.errorf(, , , , )
}

// convertUntyped attempts to set the type of an untyped value to the target type.
func ( *Checker) ( *operand,  Type) {
	, ,  := .implicitTypeAndValue(, )
	if  != 0 {
		 := 
		if !isTypeParam() {
			 = safeUnderlying()
		}
		.invalidConversion(, , )
		.mode = invalid
		return
	}
	if  != nil {
		.val = 
		.updateExprVal(.expr, )
	}
	if  != .typ {
		.typ = 
		.updateExprType(.expr, , false)
	}
}