Ejemplo n.º 1
0
            private AggCastResult bindExplicitConversionFromEnumToDecimal(AggregateType aggTypeDest)
            {
                Debug.Assert(_typeSrc != null);
                Debug.Assert(aggTypeDest != null);
                Debug.Assert(aggTypeDest.isPredefType(PredefinedType.PT_DECIMAL));

                AggregateType underlyingType = _typeSrc.underlyingType() as AggregateType;

                // Need to first cast the source expr to its underlying type.

                Expr exprCast;

                if (_exprSrc == null)
                {
                    exprCast = null;
                }
                else
                {
                    ExprClass underlyingExpr = GetExprFactory().CreateClass(underlyingType);
                    _binder.bindSimpleCast(_exprSrc, underlyingExpr, out exprCast);
                }

                // There is always an implicit conversion from any integral type to decimal.

                if (exprCast.GetConst() != null)
                {
                    // Fold the constant cast if possible.
                    ConstCastResult result = _binder.bindConstantCast(exprCast, _exprTypeDest, _needsExprDest, out _exprDest, true);
                    if (result == ConstCastResult.Success)
                    {
                        return(AggCastResult.Success);  // else, don't fold and use a regular cast, below.
                    }
                    if (result == ConstCastResult.CheckFailure && 0 == (_flags & CONVERTTYPE.CHECKOVERFLOW))
                    {
                        return(AggCastResult.Abort);
                    }
                }

                // Conversions from integral types to decimal are always bound as a user-defined conversion.

                if (_needsExprDest)
                {
                    // 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 CONVERTTYPE.NOUDC flag here.

                    bool ok = _binder.bindUserDefinedConversion(exprCast, underlyingType, aggTypeDest, _needsExprDest, out _exprDest, false);
                    Debug.Assert(ok);
                }

                return(AggCastResult.Success);
            }
Ejemplo n.º 2
0
            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);
            }
Ejemplo n.º 3
0
            // 13.2.2 Explicit enumeration conversions
            //
            // The explicit enumeration conversions are:
            //
            // * From sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, or
            //   decimal to any enum-type.
            //
            // * From any enum-type to sbyte, byte, short, ushort, int, uint, long, ulong, char,
            //   float, double, or decimal.
            //
            // * From any enum-type to any other enum-type.
            //
            // * An explicit enumeration conversion between two types is processed by treating any
            //   participating enum-type as the underlying type of that enum-type, and then performing
            //   an implicit or explicit numeric conversion between the resulting types.

            private AggCastResult bindExplicitConversionFromEnumToAggregate(AggregateType aggTypeDest)
            {
                Debug.Assert(_typeSrc != null);
                Debug.Assert(aggTypeDest != null);

                if (!_typeSrc.isEnumType())
                {
                    return(AggCastResult.Failure);
                }

                AggregateSymbol aggDest = aggTypeDest.getAggregate();

                if (aggDest.isPredefAgg(PredefinedType.PT_DECIMAL))
                {
                    return(bindExplicitConversionFromEnumToDecimal(aggTypeDest));
                }


                if (!aggDest.getThisType().isNumericType() &&
                    !aggDest.IsEnum() &&
                    !(aggDest.IsPredefined() && aggDest.GetPredefType() == PredefinedType.PT_CHAR))
                {
                    return(AggCastResult.Failure);
                }

                if (_exprSrc.GetConst() != null)
                {
                    ConstCastResult result = _binder.bindConstantCast(_exprSrc, _exprTypeDest, _needsExprDest, out _exprDest, true);
                    if (result == ConstCastResult.Success)
                    {
                        return(AggCastResult.Success);
                    }
                    else if (result == ConstCastResult.CheckFailure)
                    {
                        return(AggCastResult.Abort);
                    }
                }

                if (_needsExprDest)
                {
                    _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest);
                }
                return(AggCastResult.Success);
            }
Ejemplo n.º 4
0
            private AggCastResult bindExplicitConversionFromDecimalToEnum(AggregateType aggTypeDest)
            {
                Debug.Assert(_typeSrc != null);
                Debug.Assert(_typeSrc.IsPredefType(PredefinedType.PT_DECIMAL));
                Debug.Assert(aggTypeDest.IsEnumType);

                // There is an explicit conversion from decimal to all integral types.
                if (_exprSrc.GetConst() != null)
                {
                    // Fold the constant cast if possible.
                    ConstCastResult result = _binder.bindConstantCast(_exprSrc, _typeDest, _needsExprDest, out _exprDest, true);
                    if (result == ConstCastResult.Success)
                    {
                        return(AggCastResult.Success);  // else, don't fold and use a regular cast, below.
                    }
                    if (result == ConstCastResult.CheckFailure && 0 == (_flags & CONVERTTYPE.CHECKOVERFLOW))
                    {
                        return(AggCastResult.Abort);
                    }
                }

                // All casts from decimal to integer types are bound as user-defined conversions.

                bool bIsConversionOK = true;

                if (_needsExprDest)
                {
                    // 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 CONVERTTYPE.NOUDC flag here.
                    CType underlyingType = aggTypeDest.UnderlyingEnumType;
                    bIsConversionOK = _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, underlyingType, _needsExprDest, out _exprDest, false);

                    if (bIsConversionOK)
                    {
                        // upcast to the Enum type
                        _binder.bindSimpleCast(_exprDest, _typeDest, out _exprDest);
                    }
                }
                return(bIsConversionOK ? AggCastResult.Success : AggCastResult.Failure);
            }
Ejemplo n.º 5
0
            private AggCastResult bindExplicitConversionBetweenSimpleTypes(AggregateType aggTypeDest)
            {
                // 13.2.1
                //
                // Because the explicit conversions include all implicit and explicit numeric conversions,
                // it is always possible to convert from any numeric-type to any other numeric-type using
                // a cast expression (14.6.6).

                Debug.Assert(_typeSrc != null);
                Debug.Assert(aggTypeDest != null);

                if (!_typeSrc.isSimpleType() || !aggTypeDest.isSimpleType())
                {
                    return(AggCastResult.Failure);
                }

                AggregateSymbol aggDest = aggTypeDest.getAggregate();

                Debug.Assert(_typeSrc.isPredefined() && aggDest.IsPredefined());

                PredefinedType ptSrc  = _typeSrc.getPredefType();
                PredefinedType ptDest = aggDest.GetPredefType();

                Debug.Assert((int)ptSrc < NUM_SIMPLE_TYPES && (int)ptDest < NUM_SIMPLE_TYPES);

                ConvKind convertKind = GetConvKind(ptSrc, ptDest);

                // Identity and implicit conversions should already have been handled.
                Debug.Assert(convertKind != ConvKind.Implicit);
                Debug.Assert(convertKind != ConvKind.Identity);

                if (convertKind != ConvKind.Explicit)
                {
                    return(AggCastResult.Failure);
                }

                if (_exprSrc.GetConst() != null)
                {
                    // Fold the constant cast if possible.
                    ConstCastResult result = _binder.bindConstantCast(_exprSrc, _exprTypeDest, _needsExprDest, out _exprDest, true);
                    if (result == ConstCastResult.Success)
                    {
                        return(AggCastResult.Success);  // else, don't fold and use a regular cast, below.
                    }
                    if (result == ConstCastResult.CheckFailure && 0 == (_flags & CONVERTTYPE.CHECKOVERFLOW))
                    {
                        return(AggCastResult.Abort);
                    }
                }

                bool bConversionOk = true;

                if (_needsExprDest)
                {
                    // Explicit conversions involving decimals are bound as user-defined conversions.
                    if (isUserDefinedConversion(ptSrc, ptDest))
                    {
                        // 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 CONVERTTYPE.NOUDC flag here.
                        bConversionOk = _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, aggTypeDest, _needsExprDest, out _exprDest, false);
                    }
                    else
                    {
                        _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, (_flags & CONVERTTYPE.CHECKOVERFLOW) != 0 ? EXPRFLAG.EXF_CHECKOVERFLOW : 0);
                    }
                }
                return(bConversionOk ? AggCastResult.Success : AggCastResult.Failure);
            }
Ejemplo n.º 6
0
            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);
            }