//////////////////////////////////////////////////////////////////////////////// // // Precondition: // // type - Non-null // // This returns a null for reference types and an EXPRZEROINIT for all others. public Expr CreateZeroInit(CType type) { Debug.Assert(type != null); if (type.isEnumType()) { // For enum types, we create a constant that has the default value // as an object pointer. return(CreateConstant(type, ConstVal.Get(Activator.CreateInstance(type.AssociatedSystemType)))); } Debug.Assert(type.fundType() > FUNDTYPE.FT_NONE); Debug.Assert(type.fundType() < FUNDTYPE.FT_COUNT); switch (type.fundType()) { case FUNDTYPE.FT_PTR: { // Just allocate a new node and fill it in. return(CreateCast(0, type, CreateNull())); } case FUNDTYPE.FT_STRUCT: if (type.isPredefType(PredefinedType.PT_DECIMAL)) { goto default; } goto case FUNDTYPE.FT_VAR; case FUNDTYPE.FT_VAR: return(new ExprZeroInit(type)); default: return(CreateConstant(type, ConstVal.GetDefaultValue(type.constValKind()))); } }
private bool bindExplicitConversionToPointer() { // 27.4 Pointer conversions // // in an unsafe context, the set of available explicit conversions (13.2) is extended to // include the following explicit pointer conversions: // // * From any pointer-type to any other pointer-type. // * From sbyte, byte, short, ushort, int, uint, long, or ulong to any pointer-type. if (_typeSrc is PointerType || _typeSrc.fundType() <= FUNDTYPE.FT_LASTINTEGRAL && _typeSrc.isNumericType()) { if (_needsExprDest) { _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest); } return(true); } return(false); }
/* * BindImplicitConversion * * This is a complex routine with complex parameters. Generally, this should * be called through one of the helper methods that insulates you * from the complexity of the interface. This routine handles all the logic * associated with implicit conversions. * * exprSrc - the expression being converted. Can be null if only type conversion * info is being supplied. * typeSrc - type of the source * typeDest - type of the destination * exprDest - returns an expression of the src converted to the dest. If null, we * only care about whether the conversion can be attempted, not the * expression tree. * flags - flags possibly customizing the conversions allowed. E.g., can suppress * user-defined conversions. * * returns true if the conversion can be made, false if not. */ public bool Bind() { // 13.1 Implicit conversions // // The following conversions are classified as implicit conversions: // // * Identity conversions // * Implicit numeric conversions // * Implicit enumeration conversions // * Implicit reference conversions // * Boxing conversions // * Implicit type parameter conversions // * Implicit constant expression conversions // * User-defined implicit conversions // * Implicit conversions from an anonymous method expression to a compatible delegate type // * Implicit conversion from a method group to a compatible delegate type // * Conversions from the null type (11.2.7) to any nullable type // * Implicit nullable conversions // * Lifted user-defined implicit conversions // // Implicit conversions can occur in a variety of situations, including function member invocations // (14.4.3), cast expressions (14.6.6), and assignments (14.14). // Can't convert to or from the error type. if (_typeSrc == null || _typeDest == null || _typeDest.IsNeverSameType()) { return(false); } Debug.Assert(_typeSrc != null && _typeDest != null); // types must be supplied. Debug.Assert(_exprSrc == null || _typeSrc == _exprSrc.Type); // type of source should be correct if source supplied Debug.Assert(!_needsExprDest || _exprSrc != null); // need source expr to create dest expr switch (_typeDest.GetTypeKind()) { case TypeKind.TK_ErrorType: Debug.Assert(((ErrorType)_typeDest).HasParent); if (_typeSrc != _typeDest) { return(false); } if (_needsExprDest) { _exprDest = _exprSrc; } return(true); case TypeKind.TK_NullType: // Can only convert to the null type if src is null. if (!(_typeSrc is NullType)) { return(false); } if (_needsExprDest) { _exprDest = _exprSrc; } return(true); case TypeKind.TK_MethodGroupType: Debug.Fail("Something is wrong with Type.IsNeverSameType()"); return(false); case TypeKind.TK_ArgumentListType: return(_typeSrc == _typeDest); case TypeKind.TK_VoidType: return(false); default: break; } if (_typeSrc is ErrorType) { Debug.Assert(!(_typeDest is ErrorType)); return(false); } // 13.1.1 Identity conversion // // An identity conversion converts from any type to the same type. This conversion exists only // such that an entity that already has a required type can be said to be convertible to that type. if (_typeSrc == _typeDest && ((_flags & CONVERTTYPE.ISEXPLICIT) == 0 || (!_typeSrc.isPredefType(PredefinedType.PT_FLOAT) && !_typeSrc.isPredefType(PredefinedType.PT_DOUBLE)))) { if (_needsExprDest) { _exprDest = _exprSrc; } return(true); } if (_typeDest is NullableType nubDest) { return(BindNubConversion(nubDest)); } if (_typeSrc is NullableType nubSrc) { return(bindImplicitConversionFromNullable(nubSrc)); } if ((_flags & CONVERTTYPE.ISEXPLICIT) != 0) { _flags |= CONVERTTYPE.NOUDC; } // Get the fundamental types of destination. FUNDTYPE ftDest = _typeDest.fundType(); Debug.Assert(ftDest != FUNDTYPE.FT_NONE || _typeDest is ParameterModifierType); switch (_typeSrc.GetTypeKind()) { default: Debug.Fail($"Bad type symbol kind: {_typeSrc.GetTypeKind()}"); break; case TypeKind.TK_VoidType: case TypeKind.TK_ErrorType: case TypeKind.TK_ParameterModifierType: case TypeKind.TK_ArgumentListType: return(false); case TypeKind.TK_NullType: if (bindImplicitConversionFromNull()) { return(true); } // If not, try user defined implicit conversions. break; case TypeKind.TK_ArrayType: if (bindImplicitConversionFromArray()) { return(true); } // If not, try user defined implicit conversions. break; case TypeKind.TK_PointerType: if (bindImplicitConversionFromPointer()) { return(true); } // If not, try user defined implicit conversions. break; case TypeKind.TK_AggregateType: if (bindImplicitConversionFromAgg(_typeSrc as AggregateType)) { return(true); } // If not, try user defined implicit conversions. break; } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // RUNTIME BINDER ONLY CHANGE // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // // Every incoming dynamic operand should be implicitly convertible // to any type that it is an instance of. object srcRuntimeObject = _exprSrc?.RuntimeObject; if (srcRuntimeObject != null && _typeDest.AssociatedSystemType.IsInstanceOfType(srcRuntimeObject) && _binder.GetSemanticChecker().CheckTypeAccess(_typeDest, _binder.Context.ContextForMemberLookup)) { if (_needsExprDest) { _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, _exprSrc.Flags & EXPRFLAG.EXF_CANTBENULL); } return(true); } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // END RUNTIME BINDER ONLY CHANGE // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // 13.1.8 User-defined implicit conversions // // A user-defined implicit conversion consists of an optional standard implicit conversion, // followed by execution of a user-defined implicit conversion operator, followed by another // optional standard implicit conversion. The exact rules for evaluating user-defined // conversions are described in 13.4.3. if (0 == (_flags & CONVERTTYPE.NOUDC)) { return(_binder.bindUserDefinedConversion(_exprSrc, _typeSrc, _typeDest, _needsExprDest, out _exprDest, true)); } // No conversion was found. return(false); }
/* * BindImplicitConversion * * This is a complex routine with complex parameters. Generally, this should * be called through one of the helper methods that insulates you * from the complexity of the interface. This routine handles all the logic * associated with implicit conversions. * * exprSrc - the expression being converted. Can be null if only type conversion * info is being supplied. * typeSrc - type of the source * typeDest - type of the destination * exprDest - returns an expression of the src converted to the dest. If null, we * only care about whether the conversion can be attempted, not the * expression tree. * flags - flags possibly customizing the conversions allowed. E.g., can suppress * user-defined conversions. * * returns true if the conversion can be made, false if not. */ public bool Bind() { // 13.1 Implicit conversions // // The following conversions are classified as implicit conversions: // // * Identity conversions // * Implicit numeric conversions // * Implicit enumeration conversions // * Implicit reference conversions // * Boxing conversions // * Implicit type parameter conversions // * Implicit constant expression conversions // * User-defined implicit conversions // * Implicit conversions from an anonymous method expression to a compatible delegate type // * Implicit conversion from a method group to a compatible delegate type // * Conversions from the null type (11.2.7) to any nullable type // * Implicit nullable conversions // * Lifted user-defined implicit conversions // // Implicit conversions can occur in a variety of situations, including function member invocations // (14.4.3), cast expressions (14.6.6), and assignments (14.14). // Can't convert to or from the error type. if (typeSrc == null || typeDest == null || typeDest.IsNeverSameType()) { return(false); } Debug.Assert(typeSrc != null && typeDest != null); // types must be supplied. Debug.Assert(exprSrc == null || typeSrc == exprSrc.type); // type of source should be correct if source supplied Debug.Assert(!needsExprDest || exprSrc != null); // need source expr to create dest expr switch (typeDest.GetTypeKind()) { case TypeKind.TK_ErrorType: Debug.Assert(typeDest.AsErrorType().HasTypeParent() || typeDest.AsErrorType().HasNSParent()); if (typeSrc != typeDest) { return(false); } if (needsExprDest) { exprDest = exprSrc; } return(true); case TypeKind.TK_NullType: // Can only convert to the null type if src is null. if (!typeSrc.IsNullType()) { return(false); } if (needsExprDest) { exprDest = exprSrc; } return(true); case TypeKind.TK_MethodGroupType: VSFAIL("Something is wrong with Type.IsNeverSameType()"); return(false); case TypeKind.TK_NaturalIntegerType: case TypeKind.TK_ArgumentListType: return(typeSrc == typeDest); case TypeKind.TK_VoidType: return(false); default: break; } if (typeSrc.IsErrorType()) { Debug.Assert(!typeDest.IsErrorType()); return(false); } // 13.1.1 Identity conversion // // An identity conversion converts from any type to the same type. This conversion exists only // such that an entity that already has a required type can be said to be convertible to that type. if (typeSrc == typeDest && ((flags & CONVERTTYPE.ISEXPLICIT) == 0 || (!typeSrc.isPredefType(PredefinedType.PT_FLOAT) && !typeSrc.isPredefType(PredefinedType.PT_DOUBLE)))) { if (needsExprDest) { exprDest = exprSrc; } return(true); } if (typeDest.IsNullableType()) { return(BindNubConversion(typeDest.AsNullableType())); } if (typeSrc.IsNullableType()) { return(bindImplicitConversionFromNullable(typeSrc.AsNullableType())); } if ((flags & CONVERTTYPE.ISEXPLICIT) != 0) { flags |= CONVERTTYPE.NOUDC; } // Get the fundamental types of destination. FUNDTYPE ftDest = typeDest.fundType(); Debug.Assert(ftDest != FUNDTYPE.FT_NONE || typeDest.IsParameterModifierType()); switch (typeSrc.GetTypeKind()) { default: VSFAIL("Bad type symbol kind"); break; case TypeKind.TK_MethodGroupType: if (exprSrc.isMEMGRP()) { EXPRCALL outExpr; bool retVal = binder.BindGrpConversion(exprSrc.asMEMGRP(), typeDest, needsExprDest, out outExpr, false); exprDest = outExpr; return(retVal); } return(false); case TypeKind.TK_VoidType: case TypeKind.TK_ErrorType: case TypeKind.TK_ParameterModifierType: case TypeKind.TK_ArgumentListType: return(false); case TypeKind.TK_NullType: if (bindImplicitConversionFromNull()) { return(true); } // If not, try user defined implicit conversions. break; case TypeKind.TK_ArrayType: if (bindImplicitConversionFromArray()) { return(true); } // If not, try user defined implicit conversions. break; case TypeKind.TK_PointerType: if (bindImplicitConversionFromPointer()) { return(true); } // If not, try user defined implicit conversions. break; case TypeKind.TK_TypeParameterType: if (bindImplicitConversionFromTypeVar(typeSrc.AsTypeParameterType())) { return(true); } // If not, try user defined implicit conversions. break; case TypeKind.TK_AggregateType: // TypeReference and ArgIterator can't be boxed (or converted to anything else) if (typeSrc.isSpecialByRefType()) { return(false); } if (bindImplicitConversionFromAgg(typeSrc.AsAggregateType())) { return(true); } // If not, try user defined implicit conversions. break; } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // RUNTIME BINDER ONLY CHANGE // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // // Every incoming dynamic operand should be implicitly convertible // to any type that it is an instance of. if (exprSrc != null && exprSrc.RuntimeObject != null && typeDest.AssociatedSystemType.IsInstanceOfType(exprSrc.RuntimeObject) && binder.GetSemanticChecker().CheckTypeAccess(typeDest, binder.Context.ContextForMemberLookup())) { if (needsExprDest) { binder.bindSimpleCast(exprSrc, exprTypeDest, out exprDest, exprSrc.flags & EXPRFLAG.EXF_CANTBENULL); } return(true); } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // END RUNTIME BINDER ONLY CHANGE // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // 13.1.8 User-defined implicit conversions // // A user-defined implicit conversion consists of an optional standard implicit conversion, // followed by execution of a user-defined implicit conversion operator, followed by another // optional standard implicit conversion. The exact rules for evaluating user-defined // conversions are described in 13.4.3. if (0 == (flags & CONVERTTYPE.NOUDC)) { return(binder.bindUserDefinedConversion(exprSrc, typeSrc, typeDest, needsExprDest, out exprDest, true)); } // No conversion was found. return(false); }
private EXPR CreateZeroInit(EXPRTYPEORNAMESPACE pTypeExpr, EXPR pOptionalOriginalConstructorCall, bool isConstructor) { Debug.Assert(pTypeExpr != null); CType pType = pTypeExpr.TypeOrNamespace.AsType(); bool bIsError = false; if (pType.isEnumType()) { // For enum types, we create a constant that has the default value // as an object pointer. ConstValFactory factory = new ConstValFactory(); EXPRCONSTANT expr = CreateConstant(pType, factory.Create(Activator.CreateInstance(pType.AssociatedSystemType))); return(expr); } switch (pType.fundType()) { default: bIsError = true; break; case FUNDTYPE.FT_PTR: { CType nullType = GetTypes().GetNullType(); // UNDONE: I think this if is always false ... if (nullType.fundType() == pType.fundType()) { // Create a constant here. EXPRCONSTANT expr = CreateConstant(pType, ConstValFactory.GetDefaultValue(ConstValKind.IntPtr)); return(expr); } // Just allocate a new node and fill it in. EXPRCAST cast = CreateCast(0, pTypeExpr, CreateNull()); // UNDONE: should pTree be passed in here? return(cast); } case FUNDTYPE.FT_REF: case FUNDTYPE.FT_I1: case FUNDTYPE.FT_U1: case FUNDTYPE.FT_I2: case FUNDTYPE.FT_U2: case FUNDTYPE.FT_I4: case FUNDTYPE.FT_U4: case FUNDTYPE.FT_I8: case FUNDTYPE.FT_U8: case FUNDTYPE.FT_R4: case FUNDTYPE.FT_R8: { EXPRCONSTANT expr = CreateConstant(pType, ConstValFactory.GetDefaultValue(pType.constValKind())); EXPRCONSTANT exprInOriginal = CreateConstant(pType, ConstValFactory.GetDefaultValue(pType.constValKind())); exprInOriginal.SetOptionalConstructorCall(pOptionalOriginalConstructorCall); return(expr); // UNDONE: Check other bogus casts } case FUNDTYPE.FT_STRUCT: if (pType.isPredefType(PredefinedType.PT_DECIMAL)) { EXPRCONSTANT expr = CreateConstant(pType, ConstValFactory.GetDefaultValue(pType.constValKind())); EXPRCONSTANT exprOriginal = CreateConstant(pType, ConstValFactory.GetDefaultValue(pType.constValKind())); exprOriginal.SetOptionalConstructorCall(pOptionalOriginalConstructorCall); return(expr); } break; case FUNDTYPE.FT_VAR: break; } EXPRZEROINIT rval = new EXPRZEROINIT(); rval.kind = ExpressionKind.EK_ZEROINIT; rval.type = pType; rval.flags = 0; rval.OptionalConstructorCall = pOptionalOriginalConstructorCall; rval.IsConstructor = isConstructor; if (bIsError) { rval.SetError(); } Debug.Assert(rval != null); return(rval); }
private Expr CreateZeroInit(ExprClass typeExpr, Expr originalConstructorCall, bool isConstructor) { Debug.Assert(typeExpr != null); CType type = typeExpr.Type; bool isError = false; if (type.isEnumType()) { // For enum types, we create a constant that has the default value // as an object pointer. return(CreateConstant(type, ConstVal.Get(Activator.CreateInstance(type.AssociatedSystemType)))); } switch (type.fundType()) { case FUNDTYPE.FT_PTR: { CType nullType = Types.GetNullType(); // It looks like this if is always false ... if (nullType.fundType() == type.fundType()) { // Create a constant here. return(CreateConstant(type, ConstVal.GetDefaultValue(ConstValKind.IntPtr))); } // Just allocate a new node and fill it in. return(CreateCast(0, typeExpr, CreateNull())); } case FUNDTYPE.FT_REF: case FUNDTYPE.FT_I1: case FUNDTYPE.FT_U1: case FUNDTYPE.FT_I2: case FUNDTYPE.FT_U2: case FUNDTYPE.FT_I4: case FUNDTYPE.FT_U4: case FUNDTYPE.FT_I8: case FUNDTYPE.FT_U8: case FUNDTYPE.FT_R4: case FUNDTYPE.FT_R8: return(CreateConstant(type, ConstVal.GetDefaultValue(type.constValKind()))); case FUNDTYPE.FT_STRUCT: if (type.isPredefType(PredefinedType.PT_DECIMAL)) { goto case FUNDTYPE.FT_R8; } break; case FUNDTYPE.FT_VAR: break; default: isError = true; break; } return(new ExprZeroInit(type, originalConstructorCall, isConstructor, isError)); }
private Expr CreateZeroInit(ExprTypeOrNamespace pTypeExpr, Expr pOptionalOriginalConstructorCall, bool isConstructor) { Debug.Assert(pTypeExpr != null); CType pType = pTypeExpr.TypeOrNamespace.AsType(); bool bIsError = false; if (pType.isEnumType()) { // For enum types, we create a constant that has the default value // as an object pointer. ExprConstant expr = CreateConstant(pType, ConstVal.Get(Activator.CreateInstance(pType.AssociatedSystemType))); return(expr); } switch (pType.fundType()) { default: bIsError = true; break; case FUNDTYPE.FT_PTR: { CType nullType = GetTypes().GetNullType(); // It looks like this if is always false ... if (nullType.fundType() == pType.fundType()) { // Create a constant here. ExprConstant expr = CreateConstant(pType, ConstVal.GetDefaultValue(ConstValKind.IntPtr)); return(expr); } // Just allocate a new node and fill it in. ExprCast cast = CreateCast(0, pTypeExpr, CreateNull()); return(cast); } case FUNDTYPE.FT_REF: case FUNDTYPE.FT_I1: case FUNDTYPE.FT_U1: case FUNDTYPE.FT_I2: case FUNDTYPE.FT_U2: case FUNDTYPE.FT_I4: case FUNDTYPE.FT_U4: case FUNDTYPE.FT_I8: case FUNDTYPE.FT_U8: case FUNDTYPE.FT_R4: case FUNDTYPE.FT_R8: { ExprConstant expr = CreateConstant(pType, ConstVal.GetDefaultValue(pType.constValKind())); ExprConstant exprInOriginal = CreateConstant(pType, ConstVal.GetDefaultValue(pType.constValKind())); exprInOriginal.OptionalConstructorCall = pOptionalOriginalConstructorCall; return(expr); } case FUNDTYPE.FT_STRUCT: if (pType.isPredefType(PredefinedType.PT_DECIMAL)) { ExprConstant expr = CreateConstant(pType, ConstVal.GetDefaultValue(pType.constValKind())); ExprConstant exprOriginal = CreateConstant(pType, ConstVal.GetDefaultValue(pType.constValKind())); exprOriginal.OptionalConstructorCall = pOptionalOriginalConstructorCall; return(expr); } break; case FUNDTYPE.FT_VAR: break; } ExprZeroInit rval = new ExprZeroInit(); rval.Kind = ExpressionKind.EK_ZEROINIT; rval.Type = pType; rval.Flags = 0; rval.OptionalConstructorCall = pOptionalOriginalConstructorCall; rval.IsConstructor = isConstructor; if (bIsError) { rval.SetError(); } Debug.Assert(rval != null); return(rval); }
public static bool isConstantInRange(EXPRCONSTANT exprSrc, CType typeDest, bool realsOk) { FUNDTYPE ftSrc = exprSrc.type.fundType(); FUNDTYPE ftDest = typeDest.fundType(); if (ftSrc > FUNDTYPE.FT_LASTINTEGRAL || ftDest > FUNDTYPE.FT_LASTINTEGRAL) { if (!realsOk) { return false; } else if (ftSrc > FUNDTYPE.FT_LASTNUMERIC || ftDest > FUNDTYPE.FT_LASTNUMERIC) { return false; } } // if converting to a float type, this always succeeds... if (ftDest > FUNDTYPE.FT_LASTINTEGRAL) { return true; } // if converting from float to an integral type, we need to check whether it fits if (ftSrc > FUNDTYPE.FT_LASTINTEGRAL) { double dvalue = (exprSrc.asCONSTANT().getVal().doubleVal); switch (ftDest) { case FUNDTYPE.FT_I1: if (dvalue > -0x81 && dvalue < 0x80) return true; break; case FUNDTYPE.FT_I2: if (dvalue > -0x8001 && dvalue < 0x8000) return true; break; case FUNDTYPE.FT_I4: if (dvalue > I64(-0x80000001) && dvalue < I64(0x80000000)) return true; break; case FUNDTYPE.FT_I8: // 0x7FFFFFFFFFFFFFFFFFFF is rounded to 0x800000000000000000000 in 64 bit double precision // floating point representation. The conversion back to ulong is not possible. if (dvalue >= -9223372036854775808.0 && dvalue < 9223372036854775808.0) { return true; } break; case FUNDTYPE.FT_U1: if (dvalue > -1 && dvalue < 0x100) return true; break; case FUNDTYPE.FT_U2: if (dvalue > -1 && dvalue < 0x10000) return true; break; case FUNDTYPE.FT_U4: if (dvalue > -1 && dvalue < I64(0x100000000)) return true; break; case FUNDTYPE.FT_U8: // 0xFFFFFFFFFFFFFFFFFFFF is rounded to 0x100000000000000000000 in 64 bit double precision // floating point representation. The conversion back to ulong is not possible. if (dvalue > -1.0 && dvalue < 18446744073709551616.0) { return true; } break; default: break; } return false; } // U8 src is unsigned, so deal with values > MAX_LONG here. if (ftSrc == FUNDTYPE.FT_U8) { ulong value = exprSrc.asCONSTANT().getU64Value(); switch (ftDest) { case FUNDTYPE.FT_I1: if (value <= (ulong)SByte.MaxValue) return true; break; case FUNDTYPE.FT_I2: if (value <= (ulong)Int16.MaxValue) return true; break; case FUNDTYPE.FT_I4: if (value <= Int32.MaxValue) return true; break; case FUNDTYPE.FT_I8: if (value <= Int64.MaxValue) return true; break; case FUNDTYPE.FT_U1: if (value <= Byte.MaxValue) return true; break; case FUNDTYPE.FT_U2: if (value <= UInt16.MaxValue) return true; break; case FUNDTYPE.FT_U4: if (value <= UInt32.MaxValue) return true; break; case FUNDTYPE.FT_U8: return true; default: break; } } else { long value = exprSrc.asCONSTANT().getI64Value(); switch (ftDest) { case FUNDTYPE.FT_I1: if (value >= -128 && value <= 127) return true; break; case FUNDTYPE.FT_I2: if (value >= -0x8000 && value <= 0x7fff) return true; break; case FUNDTYPE.FT_I4: if (value >= I64(-0x80000000) && value <= I64(0x7fffffff)) return true; break; case FUNDTYPE.FT_I8: return true; case FUNDTYPE.FT_U1: if (value >= 0 && value <= 0xff) return true; break; case FUNDTYPE.FT_U2: if (value >= 0 && value <= 0xffff) return true; break; case FUNDTYPE.FT_U4: if (value >= 0 && value <= I64(0xffffffff)) return true; break; case FUNDTYPE.FT_U8: if (value >= 0) return true; break; default: break; } } return false; }
private EXPR BindIncOpCore(ExpressionKind ek, EXPRFLAG flags, EXPR exprVal, CType type) { Debug.Assert(ek == ExpressionKind.EK_ADD || ek == ExpressionKind.EK_SUB); CONSTVAL cv = new CONSTVAL(); EXPR pExprResult = null; if (type.isEnumType() && type.fundType() > FUNDTYPE.FT_LASTINTEGRAL) { // This is an error case when enum derives from an illegal type. Just treat it as an int. type = GetReqPDT(PredefinedType.PT_INT); } FUNDTYPE ft = type.fundType(); CType typeTmp = type; switch (ft) { default: { Debug.Assert(type.isPredefType(PredefinedType.PT_DECIMAL)); ek = ek == ExpressionKind.EK_ADD ? ExpressionKind.EK_DECIMALINC : ExpressionKind.EK_DECIMALDEC; PREDEFMETH predefMeth = ek == ExpressionKind.EK_DECIMALINC ? PREDEFMETH.PM_DECIMAL_OPINCREMENT : PREDEFMETH.PM_DECIMAL_OPDECREMENT; pExprResult = CreateUnaryOpForPredefMethodCall(ek, predefMeth, type, exprVal); } break; case FUNDTYPE.FT_PTR: cv.iVal = 1; pExprResult = BindPtrBinOp(ek, flags, exprVal, GetExprFactory().CreateConstant(GetReqPDT(PredefinedType.PT_INT), cv)); break; case FUNDTYPE.FT_I1: case FUNDTYPE.FT_I2: case FUNDTYPE.FT_U1: case FUNDTYPE.FT_U2: typeTmp = GetReqPDT(PredefinedType.PT_INT); cv.iVal = 1; pExprResult = LScalar(ek, flags, exprVal, type, cv, pExprResult, typeTmp); break; case FUNDTYPE.FT_I4: case FUNDTYPE.FT_U4: cv.iVal = 1; pExprResult = LScalar(ek, flags, exprVal, type, cv, pExprResult, typeTmp); break; case FUNDTYPE.FT_I8: case FUNDTYPE.FT_U8: cv = GetExprConstants().Create((long)1); pExprResult = LScalar(ek, flags, exprVal, type, cv, pExprResult, typeTmp); break; case FUNDTYPE.FT_R4: case FUNDTYPE.FT_R8: cv = GetExprConstants().Create(1.0); pExprResult = LScalar(ek, flags, exprVal, type, cv, pExprResult, typeTmp); break; } Debug.Assert(pExprResult != null); Debug.Assert(!pExprResult.type.IsNullableType()); return pExprResult; }