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); }
public static string GetNiceName(AggregateSymbol type) { if (type.IsPredefined()) { return(GetNiceName(type.GetPredefType())); } else { return(null); } }
// 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); }
//////////////////////////////////////////////////////////////////////////////// // Given a symbol, determine its fundamental type. This is the type that // indicate how the item is stored and what instructions are used to reference // if. The fundamental types are: // one of the integral/float types (includes enums with that underlying type) // reference type // struct/value type public FUNDTYPE fundType() { switch (GetTypeKind()) { case TypeKind.TK_AggregateType: { AggregateSymbol sym = ((AggregateType)this).getAggregate(); // Treat enums like their underlying types. if (sym.IsEnum()) { sym = sym.GetUnderlyingType().getAggregate(); } if (sym.IsStruct()) { // Struct type could be predefined (int, long, etc.) or some other struct. if (sym.IsPredefined()) { return(PredefinedTypeFacts.GetFundType(sym.GetPredefType())); } return(FUNDTYPE.FT_STRUCT); } return(FUNDTYPE.FT_REF); // Interfaces, classes, delegates are reference types. } case TypeKind.TK_TypeParameterType: return(FUNDTYPE.FT_VAR); case TypeKind.TK_ArrayType: case TypeKind.TK_NullType: return(FUNDTYPE.FT_REF); case TypeKind.TK_PointerType: return(FUNDTYPE.FT_PTR); case TypeKind.TK_NullableType: return(FUNDTYPE.FT_STRUCT); default: return(FUNDTYPE.FT_NONE); } }
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); }
public static string GetNiceName(AggregateSymbol type) { if (type.IsPredefined()) return GetNiceName(type.GetPredefType()); else return null; }
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); }
public override bool IsPredefType(PredefinedType pt) { AggregateSymbol agg = OwningAggregate; return(agg.IsPredefined() && agg.GetPredefType() == pt); }
public static string GetNiceName(AggregateSymbol type) => type.IsPredefined() ? GetNiceName(type.GetPredefType()) : null;