private bool bindImplicitConversionFromAgg(AggregateType aggTypeSrc) { // GENERICS: The case for constructed types is very similar to types with // no parameters. The parameters are irrelevant for most of the conversions // below. They could be relevant if we had user-defined conversions on // generic types. AggregateSymbol aggSrc = aggTypeSrc.getAggregate(); if (aggSrc.IsEnum()) { return(bindImplicitConversionFromEnum(aggTypeSrc)); } if (_typeDest.isEnumType()) { if (bindImplicitConversionToEnum(aggTypeSrc)) { return(true); } // Even though enum is sealed, a class can derive from enum in LAF scenarios -- // continue testing for derived to base conversions below. } else if (aggSrc.getThisType().isSimpleType() && _typeDest.isSimpleType()) { if (bindImplicitConversionBetweenSimpleTypes(aggTypeSrc)) { return(true); } // No simple conversion -- continue testing for derived to base conversions below. } return(bindImplicitConversionToBase(aggTypeSrc)); }
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); }