private AggCastResult bindExplicitConversionToEnum(AggregateType aggTypeDest) { Debug.Assert(_typeSrc != null); Debug.Assert(aggTypeDest != null); AggregateSymbol aggDest = aggTypeDest.getAggregate(); if (!aggDest.IsEnum()) { return(AggCastResult.Failure); } if (_typeSrc.isPredefType(PredefinedType.PT_DECIMAL)) { return(bindExplicitConversionFromDecimalToEnum(aggTypeDest)); } if (_typeSrc.isNumericType() || (_typeSrc.isPredefined() && _typeSrc.getPredefType() == PredefinedType.PT_CHAR)) { // Transform constant to constant. if (_exprSrc.GetConst() != null) { ConstCastResult result = _binder.bindConstantCast(_exprSrc, _exprTypeDest, _needsExprDest, out _exprDest, true); if (result == ConstCastResult.Success) { return(AggCastResult.Success); } if (result == ConstCastResult.CheckFailure) { return(AggCastResult.Abort); } } if (_needsExprDest) { _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest); } return(AggCastResult.Success); } else if (_typeSrc.isPredefined() && (_typeSrc.isPredefType(PredefinedType.PT_OBJECT) || _typeSrc.isPredefType(PredefinedType.PT_VALUE) || _typeSrc.isPredefType(PredefinedType.PT_ENUM))) { if (_needsExprDest) { _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_UNBOX); } return(AggCastResult.Success); } return(AggCastResult.Failure); }
private bool bindImplicitConversionBetweenSimpleTypes(AggregateType aggTypeSrc) { AggregateSymbol aggSrc = aggTypeSrc.getAggregate(); Debug.Assert(aggSrc.getThisType().isSimpleType()); Debug.Assert(_typeDest.isSimpleType()); Debug.Assert(aggSrc.IsPredefined() && _typeDest.isPredefined()); PredefinedType ptSrc = aggSrc.GetPredefType(); PredefinedType ptDest = _typeDest.getPredefType(); ConvKind convertKind; bool fConstShrinkCast = false; Debug.Assert((int)ptSrc < NUM_SIMPLE_TYPES && (int)ptDest < NUM_SIMPLE_TYPES); // 13.1.7 Implicit constant expression conversions // // An implicit constant expression conversion permits the following conversions: // * A constant-expression (14.16) of type int can be converted to type sbyte, byte, short, // ushort, uint, or ulong, provided the value of the constant-expression is within the range // of the destination type. // * A constant-expression of type long can be converted to type ulong, provided the value of // the constant-expression is not negative. // Note: Don't use GetConst here since the conversion only applies to bona-fide compile time constants. if (_exprSrc is ExprConstant constant && _exprSrc.IsOK && ((ptSrc == PredefinedType.PT_INT && ptDest != PredefinedType.PT_BOOL && ptDest != PredefinedType.PT_CHAR) || (ptSrc == PredefinedType.PT_LONG && ptDest == PredefinedType.PT_ULONG)) && isConstantInRange(constant, _typeDest)) { // Special case (CLR 6.1.6): if integral constant is in range, the conversion is a legal implicit conversion. convertKind = ConvKind.Implicit; fConstShrinkCast = _needsExprDest && (GetConvKind(ptSrc, ptDest) != ConvKind.Implicit); }
private bool bindImplicitConversionBetweenSimpleTypes(AggregateType aggTypeSrc) { AggregateSymbol aggSrc = aggTypeSrc.getAggregate(); Debug.Assert(aggSrc.getThisType().isSimpleType()); Debug.Assert(typeDest.isSimpleType()); Debug.Assert(aggSrc.IsPredefined() && typeDest.isPredefined()); PredefinedType ptSrc = aggSrc.GetPredefType(); PredefinedType ptDest = typeDest.getPredefType(); ConvKind convertKind; bool fConstShrinkCast = false; Debug.Assert((int)ptSrc < NUM_SIMPLE_TYPES && (int)ptDest < NUM_SIMPLE_TYPES); // 13.1.7 Implicit constant expression conversions // // An implicit constant expression conversion permits the following conversions: // * A constant-expression (14.16) of type int can be converted to type sbyte, byte, short, // ushort, uint, or ulong, provided the value of the constant-expression is within the range // of the destination type. // * A constant-expression of type long can be converted to type ulong, provided the value of // the constant-expression is not negative. // Note: Don't use GetConst here since the conversion only applies to bona-fide compile time constants. if (exprSrc != null && exprSrc.isCONSTANT_OK() && ((ptSrc == PredefinedType.PT_INT && ptDest != PredefinedType.PT_BOOL && ptDest != PredefinedType.PT_CHAR) || (ptSrc == PredefinedType.PT_LONG && ptDest == PredefinedType.PT_ULONG)) && isConstantInRange(exprSrc.asCONSTANT(), typeDest)) { // Special case (CLR 6.1.6): if integral constant is in range, the conversion is a legal implicit conversion. convertKind = ConvKind.Implicit; fConstShrinkCast = needsExprDest && (GetConvKind(ptSrc, ptDest) != ConvKind.Implicit); } else if (ptSrc == ptDest) { // Special case: precision limiting casts to float or double Debug.Assert(ptSrc == PredefinedType.PT_FLOAT || ptSrc == PredefinedType.PT_DOUBLE); Debug.Assert(0 != (flags & CONVERTTYPE.ISEXPLICIT)); convertKind = ConvKind.Implicit; } else { convertKind = GetConvKind(ptSrc, ptDest); Debug.Assert(convertKind != ConvKind.Identity); // identity conversion should have been handled at first. } if (convertKind != ConvKind.Implicit) { return(false); } // An implicit conversion exists. Do the conversion. if (exprSrc.GetConst() != null) { // Fold the constant cast if possible. ConstCastResult result = binder.bindConstantCast(exprSrc, exprTypeDest, needsExprDest, out exprDest, false); if (result == ConstCastResult.Success) { return(true); // else, don't fold and use a regular cast, below. } // REVIEW: I don't think this can ever be hit. If exprSrc is a constant then // it's either a floating point number (which always succeeds), it's a numeric implicit // conversion (which always succeeds), or it's a constant numeric conversion (which // has already been checked by isConstantInRange, so should always succeed) } if (isUserDefinedConversion(ptSrc, ptDest)) { if (!needsExprDest) { return(true); } // According the language, this is a standard conversion, but it is implemented // through a user-defined conversion. Because it's a standard conversion, we don't // test the NOUDC flag here. return(binder.bindUserDefinedConversion(exprSrc, aggTypeSrc, typeDest, needsExprDest, out exprDest, true)); } if (needsExprDest) { binder.bindSimpleCast(exprSrc, exprTypeDest, out exprDest); } return(true); }
private BetterType WhichConversionIsBetter(CType argType, CType p1, CType p2) { Debug.Assert(argType != null); Debug.Assert(p1 != null); Debug.Assert(p2 != null); // 7.4.2.3 Better Conversion From Expression // // Given an implicit conversion C1 that converts from an expression E to a type T1 // and an implicit conversion C2 that converts from an expression E to a type T2, the // better conversion of the two conversions is determined as follows: //* if T1 and T2 are the same type, neither conversion is better. //* If E has a type S and the conversion from S to T1 is better than the conversion from // S to T2 then C1 is the better conversion. //* If E has a type S and the conversion from S to T2 is better than the conversion from // S to T1 then C2 is the better conversion. //* If E is a lambda expression or anonymous method for which an inferred return type X // exists and T1 is a delegate type and T2 is a delegate type and T1 and T2 have identical // parameter lists: // * If T1 is a delegate of return type Y1 and T2 is a delegate of return type Y2 and the // conversion from X to Y1 is better than the conversion from X to Y2, then C1 is the // better return type. // * If T1 is a delegate of return type Y1 and T2 is a delegate of return type Y2 and the // conversion from X to Y2 is better than the conversion from X to Y1, then C2 is the // better return type. if (p1 == p2) { return(BetterType.Same); } // 7.4.2.4 Better conversion from type // // Given a conversion C1 that converts from a type S to a type T1 and a conversion C2 // that converts from a type S to a type T2, the better conversion of the two conversions // is determined as follows: //* If T1 and T2 are the same type, neither conversion is better //* If S is T1, C1 is the better conversion. //* If S is T2, C2 is the better conversion. //* If an implicit conversion from T1 to T2 exists and no implicit conversion from T2 to // T1 exists, C1 is the better conversion. //* If an implicit conversion from T2 to T1 exists and no implicit conversion from T1 to // T2 exists, C2 is the better conversion. // // [Otherwise, see table above for better integral type conversions.] if (argType == p1) { return(BetterType.Left); } if (argType == p2) { return(BetterType.Right); } bool a2b = canConvert(p1, p2); bool b2a = canConvert(p2, p1); if (a2b != b2a) { return(a2b ? BetterType.Left : BetterType.Right); } if (p1.isPredefined() && p2.isPredefined()) { PredefinedType pt1 = p1.getPredefType(); if (pt1 <= PredefinedType.PT_OBJECT) { PredefinedType pt2 = p2.getPredefType(); if (pt2 <= PredefinedType.PT_OBJECT) { return((BetterType)s_betterConversionTable[(int)pt1][(int)pt2]); } } } return(BetterType.Neither); }
private BetterType WhichConversionIsBetter(CType argType, CType p1, CType p2) { // 7.4.2.4 Better conversion from type // // Given a conversion C1 that converts from a type S to a type T1 and a conversion C2 // that converts from a type S to a type T2, the better conversion of the two conversions // is determined as follows: //* If T1 and T2 are the same type, neither conversion is better //* If S is T1, C1 is the better conversion. //* If S is T2, C2 is the better conversion. //* If an implicit conversion from T1 to T2 exists and no implicit conversion from T2 to // T1 exists, C1 is the better conversion. //* If an implicit conversion from T2 to T1 exists and no implicit conversion from T1 to // T2 exists, C2 is the better conversion. // // [Otherwise, see table above for better integral type conversions.] if (p1 == p2) { return(BetterType.Same); } if (argType == p1) { return(BetterType.Left); } if (argType == p2) { return(BetterType.Right); } bool a2b = canConvert(p1, p2); bool b2a = canConvert(p2, p1); if (a2b && !b2a) { return(BetterType.Left); } if (b2a && !a2b) { return(BetterType.Right); } Debug.Assert(b2a == a2b); if (p1.isPredefined() && p2.isPredefined() && p1.getPredefType() <= PredefinedType.PT_OBJECT && p2.getPredefType() <= PredefinedType.PT_OBJECT) { int c = s_betterConversionTable[(int)p1.getPredefType()][(int)p2.getPredefType()]; if (c == 1) { return(BetterType.Left); } else if (c == 2) { return(BetterType.Right); } } return(BetterType.Neither); }
public BetterType WhichConversionIsBetter(CType argType, CType p1, CType p2) { // 7.4.2.4 Better conversion from type // // Given a conversion C1 that converts from a type S to a type T1 and a conversion C2 // that converts from a type S to a type T2, the better conversion of the two conversions // is determined as follows: //* If T1 and T2 are the same type, neither conversion is better //* If S is T1, C1 is the better conversion. //* If S is T2, C2 is the better conversion. //* If an implicit conversion from T1 to T2 exists and no implicit conversion from T2 to // T1 exists, C1 is the better conversion. //* If an implicit conversion from T2 to T1 exists and no implicit conversion from T1 to // T2 exists, C2 is the better conversion. // // [Otherwise, see table above for better integral type conversions.] if (p1 == p2) { return BetterType.Same; } if (argType == p1) { return BetterType.Left; } if (argType == p2) { return BetterType.Right; } bool a2b = canConvert(p1, p2); bool b2a = canConvert(p2, p1); if (a2b && !b2a) { return BetterType.Left; } if (b2a && !a2b) { return BetterType.Right; } Debug.Assert(b2a == a2b); if (p1.isPredefined() && p2.isPredefined() && p1.getPredefType() <= PredefinedType.PT_OBJECT && p2.getPredefType() <= PredefinedType.PT_OBJECT) { int c = s_betterConversionTable[(int)p1.getPredefType()][(int)p2.getPredefType()]; if (c == 1) { return BetterType.Left; } else if (c == 2) { return BetterType.Right; } } return BetterType.Neither; }