X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fconvert.cs;h=f1dfc2d8bdd9a4c96764e1983cc9c3d24f464e08;hb=8e33e0d088c564d039dd791b7cc3e121ff87b3e4;hp=9fef120b13022398add8e709fd654b446689e0d5;hpb=420704e73341805e8660be1fac5a8a7407abcd6e;p=mono.git diff --git a/mcs/mcs/convert.cs b/mcs/mcs/convert.cs index 9fef120b130..f1dfc2d8bdd 100644 --- a/mcs/mcs/convert.cs +++ b/mcs/mcs/convert.cs @@ -8,31 +8,25 @@ // // Copyright 2001, 2002, 2003 Ximian, Inc. // Copyright 2003-2008 Novell, Inc. +// Copyright 2011 Xamarin Inc (http://www.xamarin.com) // using System; using System.Collections.Generic; + +#if STATIC +using IKVM.Reflection.Emit; +#else using System.Reflection.Emit; +#endif namespace Mono.CSharp { // // A container class for all the conversion operations // - static class Convert { - - static EmptyExpression MyEmptyExpr; - - static Convert () - { - Reset (); - } - - public static void Reset () - { - MyEmptyExpr = null; - } - + static class Convert + { // // From a one-dimensional array-type S[] to System.Collections.IList and base // interfaces of this interface, provided there is an implicit reference conversion @@ -40,68 +34,52 @@ namespace Mono.CSharp { // static bool ArrayToIList (ArrayContainer array, TypeSpec list, bool isExplicit) { - if (array.Rank != 1 || !list.IsGeneric) - return false; - - var open_version = list.GetDefinition (); - if ((open_version != TypeManager.generic_ilist_type) && - (open_version != TypeManager.generic_icollection_type) && - (open_version != TypeManager.generic_ienumerable_type)) + if (array.Rank != 1 || !list.IsGenericIterateInterface) return false; var arg_type = list.TypeArguments[0]; if (array.Element == arg_type) return true; + // + // Reject conversion from T[] to IList even if T has U dependency + // + if (arg_type.IsGenericParameter) + return false; + if (isExplicit) return ExplicitReferenceConversionExists (array.Element, arg_type); - if (MyEmptyExpr == null) - MyEmptyExpr = new EmptyExpression (array.Element); - else - MyEmptyExpr.SetType (array.Element); - - return ImplicitReferenceConversionExists (MyEmptyExpr, arg_type); + return ImplicitReferenceConversionExists (array.Element, arg_type); } static bool IList_To_Array(TypeSpec list, ArrayContainer array) { - if (array.Rank != 1 || !list.IsGeneric) - return false; - - var open_version = list.GetDefinition (); - if ((open_version != TypeManager.generic_ilist_type) && - (open_version != TypeManager.generic_icollection_type) && - (open_version != TypeManager.generic_ienumerable_type)) + if (array.Rank != 1 || !list.IsGenericIterateInterface) return false; var arg_type = list.TypeArguments[0]; if (array.Element == arg_type) return true; - if (MyEmptyExpr == null) - MyEmptyExpr = new EmptyExpression (array.Element); - else - MyEmptyExpr.SetType (array.Element); - - return ImplicitReferenceConversionExists (MyEmptyExpr, arg_type) || ExplicitReferenceConversionExists (array.Element, arg_type); + return ImplicitReferenceConversionExists (array.Element, arg_type) || ExplicitReferenceConversionExists (array.Element, arg_type); } - public static Expression ImplicitTypeParameterConversion (Expression expr, TypeSpec target_type) + public static Expression ImplicitTypeParameterConversion (Expression expr, TypeParameterSpec expr_type, TypeSpec target_type) { - var expr_type = (TypeParameterSpec) expr.Type; - // // From T to a type parameter U, provided T depends on U // - var ttype = target_type as TypeParameterSpec; - if (ttype != null) { + if (target_type.IsGenericParameter) { if (expr_type.TypeArguments != null) { foreach (var targ in expr_type.TypeArguments) { - if (!TypeSpecComparer.Override.IsEqual (ttype, targ)) + if (!TypeSpecComparer.Override.IsEqual (target_type, targ)) continue; - if (expr_type.IsReferenceType && !ttype.IsReferenceType) + if (expr == null) + return EmptyExpression.Null; + + if (expr_type.IsReferenceType && !((TypeParameterSpec)target_type).IsReferenceType) return new BoxedCast (expr, target_type); return new ClassCast (expr, target_type); @@ -114,7 +92,10 @@ namespace Mono.CSharp { // // LAMESPEC: From T to dynamic type because it's like T to object // - if (target_type == InternalType.Dynamic) { + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + if (expr == null) + return EmptyExpression.Null; + if (expr_type.IsReferenceType) return new ClassCast (expr, target_type); @@ -123,11 +104,14 @@ namespace Mono.CSharp { // // From T to its effective base class C - // From T to any base class of C (it cannot contain dynamic of be of dynamic type) + // From T to any base class of C (it cannot contain dynamic or be of dynamic type) // From T to any interface implemented by C // var base_type = expr_type.GetEffectiveBase (); if (base_type == target_type || TypeSpec.IsBaseClass (base_type, target_type, false) || base_type.ImplementsInterface (target_type, true)) { + if (expr == null) + return EmptyExpression.Null; + if (expr_type.IsReferenceType) return new ClassCast (expr, target_type); @@ -135,6 +119,9 @@ namespace Mono.CSharp { } if (target_type.IsInterface && expr_type.IsConvertibleToInterface (target_type)) { + if (expr == null) + return EmptyExpression.Null; + if (expr_type.IsReferenceType) return new ClassCast (expr, target_type); @@ -180,27 +167,18 @@ namespace Mono.CSharp { { TypeSpec expr_type = expr.Type; - if (expr_type == null && expr.eclass == ExprClass.MethodGroup){ - // if we are a method group, emit a warning - - expr.Emit (null); - } - - if (expr_type == TypeManager.void_type) - return null; - if (expr_type.Kind == MemberKind.TypeParameter) - return ImplicitTypeParameterConversion (expr, target_type); + return ImplicitTypeParameterConversion (expr, (TypeParameterSpec) expr.Type, target_type); // // from the null type to any reference-type. // NullLiteral nl = expr as NullLiteral; if (nl != null) { - return nl.ConvertImplicitly (null, target_type); + return nl.ConvertImplicitly (target_type); } - if (ImplicitReferenceConversionExists (expr, target_type)) { + if (ImplicitReferenceConversionExists (expr_type, target_type)) { // // Avoid wrapping implicitly convertible reference type // @@ -210,171 +188,200 @@ namespace Mono.CSharp { return EmptyCast.Create (expr, target_type); } - return ImplicitBoxingConversion (expr, expr_type, target_type); + return null; } // - // 6.1.6 Implicit reference conversions + // Implicit reference conversions // - public static bool ImplicitReferenceConversionExists (Expression expr, TypeSpec target_type) + public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type) { - if (TypeManager.IsStruct (target_type)) - return false; - - TypeSpec expr_type = expr.Type; + return ImplicitReferenceConversionExists (expr_type, target_type, true); + } - // from the null type to any reference-type. - if (expr_type == InternalType.Null) - return target_type != InternalType.AnonymousMethod; + public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type, bool refOnlyTypeParameter) + { + // It's here only to speed things up + if (target_type.IsStruct) + return false; - if (TypeManager.IsGenericParameter (expr_type)) - return ImplicitTypeParameterConversion (expr, target_type) != null; + switch (expr_type.Kind) { + case MemberKind.TypeParameter: + return ImplicitTypeParameterConversion (null, (TypeParameterSpec) expr_type, target_type) != null && + (!refOnlyTypeParameter || TypeSpec.IsReferenceType (expr_type)); - // This code is kind of mirrored inside ImplicitStandardConversionExists - // with the small distinction that we only probe there - // - // Always ensure that the code here and there is in sync + case MemberKind.Class: + // + // From any class-type to dynamic (+object to speed up common path) + // + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return true; - // from any class-type S to any interface-type T. - if (target_type.IsInterface) { - if (expr_type.ImplementsInterface (target_type, true)){ - return !TypeManager.IsValueType (expr_type); - } - } + if (target_type.IsClass) { + // + // Identity conversion, including dynamic erasure + // + if (TypeSpecComparer.IsEqual (expr_type, target_type)) + return true; - // - // Implicit reference conversions (no-boxing) to object or dynamic - // - if (target_type == TypeManager.object_type || target_type == InternalType.Dynamic) { - switch (expr_type.Kind) { - case MemberKind.Class: - case MemberKind.Interface: - case MemberKind.Delegate: - case MemberKind.ArrayType: - return true; + // + // From any class-type S to any class-type T, provided S is derived from T + // + return TypeSpec.IsBaseClass (expr_type, target_type, true); } - return expr_type == InternalType.Dynamic; - } - - if (target_type == TypeManager.value_type) { - return expr_type == TypeManager.enum_type; - } else if (expr_type == target_type || TypeSpec.IsBaseClass (expr_type, target_type, true)) { // - // Special case: enumeration to System.Enum. - // System.Enum is not a value type, it is a class, so we need - // a boxing conversion + // From any class-type S to any interface-type T, provided S implements T // - if (target_type == TypeManager.enum_type || TypeManager.IsGenericParameter (expr_type)) - return false; + if (target_type.IsInterface) + return expr_type.ImplementsInterface (target_type, true); - if (TypeManager.IsValueType (expr_type)) - return false; + return false; - // Array type variance conversion - //if (target_type.IsArray != expr_type.IsArray) - // return false; + case MemberKind.ArrayType: + // + // Identity array conversion + // + if (expr_type == target_type) + return true; - return true; - } + // + // From any array-type to System.Array + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Array: + case BuiltinTypeSpec.Type.Object: + case BuiltinTypeSpec.Type.Dynamic: + return true; + } - var expr_type_array = expr_type as ArrayContainer; - if (expr_type_array != null) { + var expr_type_array = (ArrayContainer) expr_type; var target_type_array = target_type as ArrayContainer; - // from an array-type S to an array-type of type T + + // + // From an array-type S to an array-type of type T + // if (target_type_array != null && expr_type_array.Rank == target_type_array.Rank) { // - // Both SE and TE are reference-types + // Both SE and TE are reference-types. TE check is defered + // to ImplicitReferenceConversionExists // TypeSpec expr_element_type = expr_type_array.Element; - if (!TypeManager.IsReferenceType (expr_element_type)) + if (!TypeSpec.IsReferenceType (expr_element_type)) return false; - TypeSpec target_element_type = target_type_array.Element; - if (!TypeManager.IsReferenceType (target_element_type)) - return false; + // + // An implicit reference conversion exists from SE to TE + // + return ImplicitReferenceConversionExists (expr_element_type, target_type_array.Element); + } - if (MyEmptyExpr == null) - MyEmptyExpr = new EmptyExpression (expr_element_type); - else - MyEmptyExpr.SetType (expr_element_type); + // + // From any array-type to the interfaces it implements + // + if (target_type.IsInterface) { + if (expr_type.ImplementsInterface (target_type, false)) + return true; - return ImplicitStandardConversionExists (MyEmptyExpr, target_element_type); + // from an array-type of type T to IList + if (ArrayToIList (expr_type_array, target_type, false)) + return true; } - // from an array-type to System.Array - if (target_type == TypeManager.array_type) + return false; + + case MemberKind.Delegate: + // + // From any delegate-type to System.Delegate (and its base types) + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Delegate: + case BuiltinTypeSpec.Type.MulticastDelegate: + case BuiltinTypeSpec.Type.Object: + case BuiltinTypeSpec.Type.Dynamic: return true; + } - // from an array-type of type T to IList - if (ArrayToIList (expr_type_array, target_type, false)) + // + // Identity conversion, including dynamic erasure + // + if (TypeSpecComparer.IsEqual (expr_type, target_type)) return true; - return false; - } + // + // From any delegate-type to the interfaces it implements + // From any reference-type to an delegate type if is variance-convertible + // + return expr_type.ImplementsInterface (target_type, false) || TypeSpecComparer.Variant.IsEqual (expr_type, target_type); - if (TypeSpecComparer.IsEqual (expr_type, target_type)) - return true; + case MemberKind.Interface: + // + // Identity conversion, including dynamic erasure + // + if (TypeSpecComparer.IsEqual (expr_type, target_type)) + return true; - if (TypeSpecComparer.Variant.IsEqual (expr_type, target_type)) - return true; + // + // From any interface type S to interface-type T + // From any reference-type to an interface if is variance-convertible + // + if (target_type.IsInterface) + return TypeSpecComparer.Variant.IsEqual (expr_type, target_type) || expr_type.ImplementsInterface (target_type, true); - // from any interface type S to interface-type T. - if (expr_type.IsInterface && target_type.IsInterface) { - return expr_type.ImplementsInterface (target_type, true); + return target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic; } - // from any delegate type to System.Delegate - if (target_type == TypeManager.delegate_type && - (expr_type == TypeManager.delegate_type || expr_type.IsDelegate)) - return true; + // + // from the null literal to any reference-type. + // + if (expr_type == InternalType.NullLiteral) { + // Exlude internal compiler types + if (target_type.Kind == MemberKind.InternalCompilerType) + return target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + + return TypeSpec.IsReferenceType (target_type); + } return false; } public static Expression ImplicitBoxingConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type) { + switch (target_type.BuiltinType) { // - // From any value-type to the type object. + // From any non-nullable-value-type to the type object and dynamic // - if (target_type == TypeManager.object_type || target_type == InternalType.Dynamic) { - // - // A pointer type cannot be converted to object - // - if (expr_type.IsPointer) - return null; - - if (!TypeManager.IsValueType (expr_type)) - return null; - - return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type); - } - + case BuiltinTypeSpec.Type.Object: + case BuiltinTypeSpec.Type.Dynamic: // - // From any value-type to the type System.ValueType. + // From any non-nullable-value-type to the type System.ValueType // - if (target_type == TypeManager.value_type) { - if (!TypeManager.IsValueType (expr_type)) + case BuiltinTypeSpec.Type.ValueType: + // + // No ned to check for nullable type as underlying type is always convertible + // + if (!TypeSpec.IsValueType (expr_type)) return null; return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type); - } - if (target_type == TypeManager.enum_type) { + case BuiltinTypeSpec.Type.Enum: // // From any enum-type to the type System.Enum. // - if (TypeManager.IsEnumType (expr_type)) + if (expr_type.IsEnum) return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type); + + break; } // // From a nullable-type to a reference type, if a boxing conversion exists from // the underlying type to the reference type // - if (TypeManager.IsNullableType (expr_type)) { - if (!TypeManager.IsReferenceType (target_type)) + if (expr_type.IsNullableType) { + if (!TypeSpec.IsReferenceType (target_type)) return null; var res = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type); @@ -387,27 +394,12 @@ namespace Mono.CSharp { return res; } - if (TypeSpec.IsBaseClass (expr_type, target_type, false)) { - // - // Don't box same type arguments - // - if (TypeManager.IsGenericParameter (expr_type) && expr_type != target_type) - return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type); - - return null; - } - - // This code is kind of mirrored inside ImplicitStandardConversionExists - // with the small distinction that we only probe there // - // Always ensure that the code here and there is in sync - - // from any class-type S to any interface-type T. - if (target_type.IsInterface) { - if (expr_type.ImplementsInterface (target_type, true) && - (TypeManager.IsGenericParameter (expr_type) || TypeManager.IsValueType (expr_type))) { - return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type); - } + // A value type has a boxing conversion to an interface type I if it has a boxing conversion + // to an interface or delegate type I0 and I0 is variance-convertible to I + // + if (target_type.IsInterface && TypeSpec.IsValueType (expr_type) && expr_type.ImplementsInterface (target_type, true)) { + return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type); } return null; @@ -420,14 +412,14 @@ namespace Mono.CSharp { // // From null to any nullable type // - if (expr_type == InternalType.Null) + if (expr_type == InternalType.NullLiteral) return ec == null ? EmptyExpression.Null : Nullable.LiftedNull.Create (target_type, expr.Location); // S -> T? TypeSpec t_el = Nullable.NullableInfo.GetUnderlyingType (target_type); // S? -> T? - if (TypeManager.IsNullableType (expr_type)) + if (expr_type.IsNullableType) expr_type = Nullable.NullableInfo.GetUnderlyingType (expr_type); // @@ -441,7 +433,7 @@ namespace Mono.CSharp { return EmptyExpression.Null; if (expr is Constant) - return ((Constant) expr).ConvertImplicitly (ec, t_el); + return ((Constant) expr).ConvertImplicitly (t_el); return ImplicitNumericConversion (null, expr_type, t_el); } @@ -455,7 +447,7 @@ namespace Mono.CSharp { Expression conv = unwrap; if (!TypeSpecComparer.IsEqual (expr_type, t_el)) { if (conv is Constant) - conv = ((Constant)conv).ConvertImplicitly (ec, t_el); + conv = ((Constant)conv).ConvertImplicitly (t_el); else conv = ImplicitNumericConversion (conv, expr_type, t_el); @@ -482,159 +474,188 @@ namespace Mono.CSharp { static Expression ImplicitNumericConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type) { - if (expr_type == TypeManager.sbyte_type){ + switch (expr_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: // // From sbyte to short, int, long, float, double, decimal // - if (target_type == TypeManager.int32_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I4); - if (target_type == TypeManager.int64_type) + case BuiltinTypeSpec.Type.Long: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); - if (target_type == TypeManager.double_type) + case BuiltinTypeSpec.Type.Double: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); - if (target_type == TypeManager.float_type) + case BuiltinTypeSpec.Type.Float: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); - if (target_type == TypeManager.short_type) + case BuiltinTypeSpec.Type.Short: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I2); - if (target_type == TypeManager.decimal_type) - return expr == null ? EmptyExpression.Null : new CastToDecimal (expr); - } else if (expr_type == TypeManager.byte_type){ + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + + } + + break; + case BuiltinTypeSpec.Type.Byte: // // From byte to short, ushort, int, uint, long, ulong, float, double, decimal // - if (target_type == TypeManager.int32_type || target_type == TypeManager.uint32_type || - target_type == TypeManager.short_type || target_type == TypeManager.ushort_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type); - - if (target_type == TypeManager.uint64_type) + case BuiltinTypeSpec.Type.ULong: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); - if (target_type == TypeManager.int64_type) + case BuiltinTypeSpec.Type.Long: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); - if (target_type == TypeManager.float_type) + case BuiltinTypeSpec.Type.Float: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); - if (target_type == TypeManager.double_type) + case BuiltinTypeSpec.Type.Double: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); - if (target_type == TypeManager.decimal_type) - return expr == null ? EmptyExpression.Null : new CastToDecimal (expr); - - } else if (expr_type == TypeManager.short_type){ + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Short: // // From short to int, long, float, double, decimal // - if (target_type == TypeManager.int32_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type); - if (target_type == TypeManager.int64_type) + case BuiltinTypeSpec.Type.Long: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); - if (target_type == TypeManager.double_type) + case BuiltinTypeSpec.Type.Double: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); - if (target_type == TypeManager.float_type) + case BuiltinTypeSpec.Type.Float: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); - if (target_type == TypeManager.decimal_type) - return expr == null ? EmptyExpression.Null : new CastToDecimal (expr); - - } else if (expr_type == TypeManager.ushort_type){ + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.UShort: // // From ushort to int, uint, long, ulong, float, double, decimal // - if (target_type == TypeManager.int32_type || target_type == TypeManager.uint32_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type); - - if (target_type == TypeManager.uint64_type) + case BuiltinTypeSpec.Type.ULong: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); - if (target_type == TypeManager.int64_type) + case BuiltinTypeSpec.Type.Long: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); - if (target_type == TypeManager.double_type) + case BuiltinTypeSpec.Type.Double: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); - if (target_type == TypeManager.float_type) + case BuiltinTypeSpec.Type.Float: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); - if (target_type == TypeManager.decimal_type) - return expr == null ? EmptyExpression.Null : new CastToDecimal (expr); - } else if (expr_type == TypeManager.int32_type){ + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Int: // // From int to long, float, double, decimal // - if (target_type == TypeManager.int64_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Long: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); - if (target_type == TypeManager.double_type) + case BuiltinTypeSpec.Type.Double: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); - if (target_type == TypeManager.float_type) + case BuiltinTypeSpec.Type.Float: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); - if (target_type == TypeManager.decimal_type) - return expr == null ? EmptyExpression.Null : new CastToDecimal (expr); - } else if (expr_type == TypeManager.uint32_type){ + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.UInt: // // From uint to long, ulong, float, double, decimal // - if (target_type == TypeManager.int64_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Long: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); - if (target_type == TypeManager.uint64_type) + case BuiltinTypeSpec.Type.ULong: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); - if (target_type == TypeManager.double_type) + case BuiltinTypeSpec.Type.Double: return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8); - if (target_type == TypeManager.float_type) + case BuiltinTypeSpec.Type.Float: return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4); - if (target_type == TypeManager.decimal_type) - return expr == null ? EmptyExpression.Null : new CastToDecimal (expr); - } else if (expr_type == TypeManager.int64_type){ + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Long: // - // From long/ulong to float, double + // From long to float, double, decimal // - if (target_type == TypeManager.double_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Double: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); - if (target_type == TypeManager.float_type) + case BuiltinTypeSpec.Type.Float: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); - if (target_type == TypeManager.decimal_type) - return expr == null ? EmptyExpression.Null : new CastToDecimal (expr); - } else if (expr_type == TypeManager.uint64_type){ + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.ULong: // - // From ulong to float, double + // From ulong to float, double, decimal // - if (target_type == TypeManager.double_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Double: return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8); - if (target_type == TypeManager.float_type) + case BuiltinTypeSpec.Type.Float: return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4); - if (target_type == TypeManager.decimal_type) - return expr == null ? EmptyExpression.Null : new CastToDecimal (expr); - } else if (expr_type == TypeManager.char_type){ + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Char: // // From char to ushort, int, uint, long, ulong, float, double, decimal // - if ((target_type == TypeManager.ushort_type) || - (target_type == TypeManager.int32_type) || - (target_type == TypeManager.uint32_type)) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type); - if (target_type == TypeManager.uint64_type) + case BuiltinTypeSpec.Type.ULong: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); - if (target_type == TypeManager.int64_type) + case BuiltinTypeSpec.Type.Long: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); - if (target_type == TypeManager.float_type) + case BuiltinTypeSpec.Type.Float: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); - if (target_type == TypeManager.double_type) + case BuiltinTypeSpec.Type.Double: return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); - if (target_type == TypeManager.decimal_type) - return expr == null ? EmptyExpression.Null : new CastToDecimal (expr); - } else if (expr_type == TypeManager.float_type){ + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Float: // // float to double // - if (target_type == TypeManager.double_type) + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double) return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + break; } return null; } - /// - /// Same as ImplicitStandardConversionExists except that it also looks at - /// implicit user defined conversions - needed for overload resolution - /// + // + // Full version of implicit conversion + // public static bool ImplicitConversionExists (ResolveContext ec, Expression expr, TypeSpec target_type) { if (ImplicitStandardConversionExists (expr, target_type)) return true; if (expr.Type == InternalType.AnonymousMethod) { - if (!TypeManager.IsDelegateType (target_type) && target_type.GetDefinition () != TypeManager.expression_type) + if (!target_type.IsDelegate && !target_type.IsExpressionTreeType) return false; AnonymousMethodExpression ame = (AnonymousMethodExpression) expr; @@ -642,7 +663,7 @@ namespace Mono.CSharp { } if (expr.eclass == ExprClass.MethodGroup) { - if (target_type.IsDelegate && RootContext.Version != LanguageVersion.ISO_1) { + if (target_type.IsDelegate && ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1) { MethodGroupExpr mg = expr as MethodGroupExpr; if (mg != null) return DelegateCreation.ImplicitStandardConversionExists (ec, mg, target_type); @@ -651,57 +672,40 @@ namespace Mono.CSharp { return false; } + // Conversion from __arglist to System.ArgIterator + if (expr.Type == InternalType.Arglist) + return target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec; + return ImplicitUserConversion (ec, expr, target_type, Location.Null) != null; } - /// - /// Determines if a standard implicit conversion exists from - /// expr_type to target_type - /// - /// + // + // Implicit standard conversion (only core conversions are used here) + // public static bool ImplicitStandardConversionExists (Expression expr, TypeSpec target_type) { - TypeSpec expr_type = expr.Type; - - NullLiteral nl = expr as NullLiteral; - if (nl != null) - return nl.ConvertImplicitly (null, target_type) != null; + // + // Identity conversions + // Implicit numeric conversions + // Implicit nullable conversions + // Implicit reference conversions + // Boxing conversions + // Implicit constant expression conversions + // Implicit conversions involving type parameters + // - if (expr_type == TypeManager.void_type) - return false; + TypeSpec expr_type = expr.Type; if (expr_type == target_type) return true; - // Implicit dynamic conversion - if (expr_type == InternalType.Dynamic) { - switch (target_type.Kind) { - case MemberKind.ArrayType: - case MemberKind.Class: - case MemberKind.Struct: - case MemberKind.Delegate: - case MemberKind.Enum: - case MemberKind.Interface: - case MemberKind.TypeParameter: - return true; - } - - // dynamic to __arglist - if (target_type == InternalType.Arglist) - return true; - - return false; - } - - if (TypeManager.IsNullableType (target_type)) { + if (target_type.IsNullableType) return ImplicitNulableConversion (null, expr, target_type) != null; - } - // First numeric conversions if (ImplicitNumericConversion (null, expr_type, target_type) != null) return true; - if (ImplicitReferenceConversionExists (expr, target_type)) + if (ImplicitReferenceConversionExists (expr_type, target_type, false)) return true; if (ImplicitBoxingConversion (null, expr_type, target_type) != null) @@ -712,23 +716,28 @@ namespace Mono.CSharp { // if (expr is IntConstant){ int value = ((IntConstant) expr).Value; - - if (target_type == TypeManager.sbyte_type){ + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: if (value >= SByte.MinValue && value <= SByte.MaxValue) return true; - } else if (target_type == TypeManager.byte_type){ + break; + case BuiltinTypeSpec.Type.Byte: if (value >= 0 && value <= Byte.MaxValue) return true; - } else if (target_type == TypeManager.short_type){ + break; + case BuiltinTypeSpec.Type.Short: if (value >= Int16.MinValue && value <= Int16.MaxValue) return true; - } else if (target_type == TypeManager.ushort_type){ + break; + case BuiltinTypeSpec.Type.UShort: if (value >= UInt16.MinValue && value <= UInt16.MaxValue) return true; - } else if (target_type == TypeManager.uint32_type){ + break; + case BuiltinTypeSpec.Type.UInt: if (value >= 0) return true; - } else if (target_type == TypeManager.uint64_type){ + break; + case BuiltinTypeSpec.Type.ULong: // // we can optimize this case: a positive int32 // always fits on a uint64. But we need an opcode @@ -736,10 +745,12 @@ namespace Mono.CSharp { // if (value >= 0) return true; + + break; } } - if (expr is LongConstant && target_type == TypeManager.uint64_type){ + if (expr is LongConstant && target_type.BuiltinType == BuiltinTypeSpec.Type.ULong){ // // Try the implicit constant expression conversion // from long to ulong, instead of a nice routine, @@ -750,7 +761,7 @@ namespace Mono.CSharp { return true; } - if (expr is IntegralConstant && TypeManager.IsEnumType (target_type)) { + if (expr is IntegralConstant && target_type.IsEnum) { var i = (IntegralConstant) expr; // // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0 @@ -762,21 +773,42 @@ namespace Mono.CSharp { return i.IsZeroInteger; } + // Implicit dynamic conversion + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + switch (target_type.Kind) { + case MemberKind.ArrayType: + case MemberKind.Class: + case MemberKind.Struct: + case MemberKind.Delegate: + case MemberKind.Enum: + case MemberKind.Interface: + case MemberKind.TypeParameter: + return true; + } + + // dynamic to __arglist + if (target_type == InternalType.Arglist) + return true; + + return false; + } + // - // If `expr_type' implements `target_type' (which is an iface) - // see TryImplicitIntConversion + // In an unsafe context implicit conversions is extended to include // - if (target_type.IsInterface && expr_type.ImplementsInterface (target_type, true)) - return true; - - if (target_type.IsPointer && expr_type.IsPointer && ((PointerContainer) target_type).Element.BuildinType == BuildinTypeSpec.Type.Void) + // From any pointer-type to the type void* + // From the null literal to any pointer-type. + // + // LAMESPEC: The specification claims this conversion is allowed in implicit conversion but + // in reality implicit standard conversion uses it + // + if (target_type.IsPointer && expr.Type.IsPointer && ((PointerContainer) target_type).Element.Kind == MemberKind.Void) return true; - // Conversion from __arglist to System.ArgIterator - if (expr_type == InternalType.Arglist) - return target_type == TypeManager.arg_iterator_type; - - if (TypeSpecComparer.IsEqual (expr_type, target_type)) + // + // Struct identity conversion, including dynamic erasure + // + if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type)) return true; return false; @@ -786,10 +818,10 @@ namespace Mono.CSharp { /// Finds "most encompassed type" according to the spec (13.4.2) /// amongst the methods in the MethodGroupExpr /// - public static TypeSpec FindMostEncompassedType (IEnumerable types) + public static TypeSpec FindMostEncompassedType (IList types) { TypeSpec best = null; - EmptyExpression expr = EmptyExpression.Grab (); + EmptyExpression expr; foreach (TypeSpec t in types) { if (best == null) { @@ -797,12 +829,12 @@ namespace Mono.CSharp { continue; } - expr.SetType (t); + expr = new EmptyExpression (t); if (ImplicitStandardConversionExists (expr, best)) best = t; } - expr.SetType (best); + expr = new EmptyExpression (best); foreach (TypeSpec t in types) { if (best == t) continue; @@ -812,49 +844,46 @@ namespace Mono.CSharp { } } - EmptyExpression.Release (expr); - return best; } - /// - /// Finds "most encompassing type" according to the spec (13.4.2) - /// amongst the types in the given set - /// + // + // Finds the most encompassing type (type into which all other + // types can convert to) amongst the types in the given set + // static TypeSpec FindMostEncompassingType (IList types) { - TypeSpec best = null; - if (types.Count == 0) return null; if (types.Count == 1) return types [0]; - EmptyExpression expr = EmptyExpression.Grab (); + TypeSpec best = null; + for (int i = 0; i < types.Count; ++i) { + int ii = 0; + for (; ii < types.Count; ++ii) { + if (ii == i) + continue; - foreach (TypeSpec t in types) { - if (best == null) { - best = t; - continue; + var expr = new EmptyExpression (types[ii]); + if (!ImplicitStandardConversionExists (expr, types [i])) { + ii = 0; + break; + } } - expr.SetType (best); - if (ImplicitStandardConversionExists (expr, t)) - best = t; - } + if (ii == 0) + continue; - foreach (TypeSpec t in types) { - if (best == t) + if (best == null) { + best = types[i]; continue; - expr.SetType (t); - if (!ImplicitStandardConversionExists (expr, best)) { - best = null; - break; } - } - EmptyExpression.Release (expr); + // Indicates multiple best types + return InternalType.FakeInternalType; + } return best; } @@ -929,17 +958,13 @@ namespace Mono.CSharp { if (apply_explicit_conv_rules) { var candidate_set = new List (); - EmptyExpression expr = EmptyExpression.Grab (); - - foreach (TypeSpec ret_type in tgt_types_set){ - expr.SetType (ret_type); + foreach (TypeSpec ret_type in tgt_types_set) { + var expr = new EmptyExpression (ret_type); if (ImplicitStandardConversionExists (expr, target)) candidate_set.Add (ret_type); } - EmptyExpression.Release (expr); - if (candidate_set.Count != 0) return FindMostEncompassingType (candidate_set); } @@ -971,22 +996,10 @@ namespace Mono.CSharp { static void FindApplicableUserDefinedConversionOperators (IList operators, Expression source, TypeSpec target, bool implicitOnly, ref List candidates) { - // - // LAMESPEC: Undocumented IntPtr/UIntPtr conversions - // IntPtr -> uint uses int - // UIntPtr -> long uses ulong - // - if (source.Type == TypeManager.intptr_type) { - if (target == TypeManager.uint32_type) - target = TypeManager.int32_type; - } else if (source.Type == TypeManager.uintptr_type) { - if (target == TypeManager.int64_type) - target = TypeManager.uint64_type; - } - - // Neither A nor B are interface-types - if (source.Type.IsInterface) + if (source.Type.IsInterface) { + // Neither A nor B are interface-types return; + } // For a conversion operator to be applicable, it must be possible // to perform a standard conversion from the source type to @@ -1013,15 +1026,11 @@ namespace Mono.CSharp { t = op.ReturnType; - // LAMESPEC: Exclude UIntPtr -> int conversion - if (t == TypeManager.uint32_type && source.Type == TypeManager.uintptr_type) - continue; - if (t.IsInterface) continue; if (target != t) { - if (TypeManager.IsNullableType (t)) + if (t.IsNullableType) t = Nullable.NullableInfo.GetUnderlyingType (t); if (!ImplicitStandardConversionExists (new EmptyExpression (t), target)) { @@ -1058,9 +1067,9 @@ namespace Mono.CSharp { TypeSpec target_type = target; Expression source_type_expr; - if (TypeManager.IsNullableType (source_type)) { + if (source_type.IsNullableType) { // No implicit conversion S? -> T for non-reference types - if (implicitOnly && !TypeManager.IsReferenceType (target_type) && !TypeManager.IsNullableType (target_type)) + if (implicitOnly && !TypeSpec.IsReferenceType (target_type) && !target_type.IsNullableType) return null; source_type_expr = Nullable.Unwrap.Create (source); @@ -1069,13 +1078,13 @@ namespace Mono.CSharp { source_type_expr = source; } - if (TypeManager.IsNullableType (target_type)) + if (target_type.IsNullableType) target_type = Nullable.NullableInfo.GetUnderlyingType (target_type); // Only these containers can contain a user defined implicit or explicit operators const MemberKind user_conversion_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.TypeParameter; - if ((source_type.Kind & user_conversion_kinds) != 0 && source_type != TypeManager.decimal_type) { + if ((source_type.Kind & user_conversion_kinds) != 0 && source_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) { bool declared_only = source_type.IsStruct; var operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Implicit, declared_only); @@ -1091,7 +1100,7 @@ namespace Mono.CSharp { } } - if ((target.Kind & user_conversion_kinds) != 0 && target_type != TypeManager.decimal_type) { + if ((target.Kind & user_conversion_kinds) != 0 && target_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) { bool declared_only = target.IsStruct || implicitOnly; var operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Implicit, declared_only); @@ -1153,17 +1162,24 @@ namespace Mono.CSharp { "Ambiguous user defined operators `{0}' and `{1}' when converting from `{2}' to `{3}'", ambig_arg.GetSignatureForError (), most_specific_operator.GetSignatureForError (), source.Type.GetSignatureForError (), target.GetSignatureForError ()); + + return ErrorExpression.Instance; } } // // Convert input type when it's different to best operator argument // - if (s_x != source_type) - source = implicitOnly ? - ImplicitConversionStandard (ec, source_type_expr, s_x, loc) : - ExplicitConversionStandard (ec, source_type_expr, s_x, loc); - else { + if (s_x != source_type) { + var c = source as Constant; + if (c != null) { + source = c.TryReduce (ec, s_x, loc); + } else { + source = implicitOnly ? + ImplicitConversionStandard (ec, source_type_expr, s_x, loc) : + ExplicitConversionStandard (ec, source_type_expr, s_x, loc); + } + } else { source = source_type_expr; } @@ -1176,7 +1192,7 @@ namespace Mono.CSharp { // // User operator is of T?, no need to lift it // - if (TypeManager.IsNullableType (t_x) && t_x == target) + if (t_x == target && t_x.IsNullableType) return source; source = implicitOnly ? @@ -1191,7 +1207,7 @@ namespace Mono.CSharp { // Source expression is of nullable type, lift the result in the case it's null and // not nullable/lifted user operator is used // - if (source_type_expr is Nullable.Unwrap && !TypeManager.IsNullableType (s_x) && (TypeManager.IsReferenceType (target) || target_type != target)) + if (source_type_expr is Nullable.Unwrap && !s_x.IsNullableType && (TypeSpec.IsReferenceType (target) || target_type != target)) source = new Nullable.Lifted (source, source_type_expr, target).Resolve (ec); else if (target_type != target) source = Nullable.Wrap.Create (source, target); @@ -1243,14 +1259,14 @@ namespace Mono.CSharp { static Expression ImplicitConversionStandard (ResolveContext ec, Expression expr, TypeSpec target_type, Location loc, bool explicit_cast) { if (expr.eclass == ExprClass.MethodGroup){ - if (!TypeManager.IsDelegateType (target_type)){ + if (!target_type.IsDelegate){ return null; } // // Only allow anonymous method conversions on post ISO_1 // - if (RootContext.Version != LanguageVersion.ISO_1){ + if (ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1){ MethodGroupExpr mg = expr as MethodGroupExpr; if (mg != null) return ImplicitDelegateCreation.Create ( @@ -1262,25 +1278,20 @@ namespace Mono.CSharp { Expression e; if (expr_type == target_type) { - if (expr_type != InternalType.Null && expr_type != InternalType.AnonymousMethod) + if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod) return expr; return null; } - if (expr_type == InternalType.Dynamic) { + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { switch (target_type.Kind) { case MemberKind.ArrayType: case MemberKind.Class: - if (target_type == TypeManager.object_type) + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object) return EmptyCast.Create (expr, target_type); goto case MemberKind.Struct; case MemberKind.Struct: - // TODO: Should really introduce MemberKind.Void - if (target_type == TypeManager.void_type) - return null; - - goto case MemberKind.Enum; case MemberKind.Delegate: case MemberKind.Enum: case MemberKind.Interface: @@ -1293,7 +1304,7 @@ namespace Mono.CSharp { return null; } - if (TypeManager.IsNullableType (target_type)) + if (target_type.IsNullableType) return ImplicitNulableConversion (ec, expr, target_type); // @@ -1302,7 +1313,7 @@ namespace Mono.CSharp { Constant c = expr as Constant; if (c != null) { try { - c = c.ConvertImplicitly (ec, target_type); + c = c.ConvertImplicitly (target_type); } catch { Console.WriteLine ("Conversion error happened in line {0}", loc); throw; @@ -1319,7 +1330,11 @@ namespace Mono.CSharp { if (e != null) return e; - if (expr is IntegralConstant && TypeManager.IsEnumType (target_type)){ + e = ImplicitBoxingConversion (expr, expr_type, target_type); + if (e != null) + return e; + + if (expr is IntegralConstant && target_type.IsEnum){ var i = (IntegralConstant) expr; // // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0 @@ -1330,7 +1345,7 @@ namespace Mono.CSharp { // if (i.IsZeroInteger) { // Recreate 0 literal to remove any collected conversions - return new EnumConstant (new IntLiteral (0, i.Location), target_type).Resolve (ec); + return new EnumConstant (new IntLiteral (ec.BuiltinTypes, 0, i.Location), target_type); } } @@ -1344,14 +1359,14 @@ namespace Mono.CSharp { if (expr_type == target_pc) return expr; - if (target_pc.Element.BuildinType == BuildinTypeSpec.Type.Void) + if (target_pc.Element.Kind == MemberKind.Void) return EmptyCast.Create (expr, target_type); //return null; } - if (expr_type == InternalType.Null) - return EmptyCast.Create (new NullPointer (loc), target_type); + if (expr_type == InternalType.NullLiteral) + return new NullPointer (target_type, loc); } } @@ -1362,11 +1377,14 @@ namespace Mono.CSharp { return am.Resolve (ec); } - if (expr_type == InternalType.Arglist && target_type == TypeManager.arg_iterator_type) + if (expr_type == InternalType.Arglist && target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec) return expr; - if (TypeSpecComparer.IsEqual (expr_type, target_type)) - return expr; + // + // dynamic erasure conversion on value types + // + if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type)) + return expr_type == target_type ? expr : EmptyCast.Create (expr, target_type); return null; } @@ -1408,252 +1426,304 @@ namespace Mono.CSharp { /// Int16->UIntPtr /// /// - public static Expression ExplicitNumericConversion (Expression expr, TypeSpec target_type) + public static Expression ExplicitNumericConversion (ResolveContext rc, Expression expr, TypeSpec target_type) { - TypeSpec expr_type = expr.Type; - TypeSpec real_target_type = target_type; + // Not all predefined explicit numeric conversion are + // defined here, for some of them (mostly IntPtr/UIntPtr) we + // defer to user-operator handling which is now perfect but + // works for now + // + // LAMESPEC: Undocumented IntPtr/UIntPtr conversions + // IntPtr -> uint uses int + // UIntPtr -> long uses ulong + // - if (expr_type == TypeManager.sbyte_type){ + switch (expr.Type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: // // From sbyte to byte, ushort, uint, ulong, char, uintptr // - if (real_target_type == TypeManager.byte_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1); - if (real_target_type == TypeManager.ushort_type) + case BuiltinTypeSpec.Type.UShort: return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2); - if (real_target_type == TypeManager.uint32_type) + case BuiltinTypeSpec.Type.UInt: return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4); - if (real_target_type == TypeManager.uint64_type) + case BuiltinTypeSpec.Type.ULong: return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8); - if (real_target_type == TypeManager.char_type) + case BuiltinTypeSpec.Type.Char: return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH); // One of the built-in conversions that belonged in the class library - if (real_target_type == TypeManager.uintptr_type){ - Expression u8e = new ConvCast (expr, TypeManager.uint64_type, ConvCast.Mode.I1_U8); - - return new OperatorCast (u8e, TypeManager.uintptr_type, true); + case BuiltinTypeSpec.Type.UIntPtr: + return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I1_U8), target_type, target_type, true); } - } else if (expr_type == TypeManager.byte_type){ + break; + case BuiltinTypeSpec.Type.Byte: // // From byte to sbyte and char // - if (real_target_type == TypeManager.sbyte_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1); - if (real_target_type == TypeManager.char_type) + case BuiltinTypeSpec.Type.Char: return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH); - } else if (expr_type == TypeManager.short_type){ + } + break; + case BuiltinTypeSpec.Type.Short: // // From short to sbyte, byte, ushort, uint, ulong, char, uintptr // - if (real_target_type == TypeManager.sbyte_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1); - if (real_target_type == TypeManager.byte_type) + case BuiltinTypeSpec.Type.Byte: return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1); - if (real_target_type == TypeManager.ushort_type) + case BuiltinTypeSpec.Type.UShort: return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2); - if (real_target_type == TypeManager.uint32_type) + case BuiltinTypeSpec.Type.UInt: return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4); - if (real_target_type == TypeManager.uint64_type) + case BuiltinTypeSpec.Type.ULong: return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8); - if (real_target_type == TypeManager.char_type) + case BuiltinTypeSpec.Type.Char: return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH); // One of the built-in conversions that belonged in the class library - if (real_target_type == TypeManager.uintptr_type){ - Expression u8e = new ConvCast (expr, TypeManager.uint64_type, ConvCast.Mode.I2_U8); - - return new OperatorCast (u8e, TypeManager.uintptr_type, true); + case BuiltinTypeSpec.Type.UIntPtr: + return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true); } - } else if (expr_type == TypeManager.ushort_type){ + break; + case BuiltinTypeSpec.Type.UShort: // // From ushort to sbyte, byte, short, char // - if (real_target_type == TypeManager.sbyte_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1); - if (real_target_type == TypeManager.byte_type) + case BuiltinTypeSpec.Type.Byte: return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1); - if (real_target_type == TypeManager.short_type) + case BuiltinTypeSpec.Type.Short: return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2); - if (real_target_type == TypeManager.char_type) + case BuiltinTypeSpec.Type.Char: return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH); - } else if (expr_type == TypeManager.int32_type){ + } + break; + case BuiltinTypeSpec.Type.Int: // // From int to sbyte, byte, short, ushort, uint, ulong, char, uintptr // - if (real_target_type == TypeManager.sbyte_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1); - if (real_target_type == TypeManager.byte_type) + case BuiltinTypeSpec.Type.Byte: return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1); - if (real_target_type == TypeManager.short_type) + case BuiltinTypeSpec.Type.Short: return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2); - if (real_target_type == TypeManager.ushort_type) + case BuiltinTypeSpec.Type.UShort: return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2); - if (real_target_type == TypeManager.uint32_type) + case BuiltinTypeSpec.Type.UInt: return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4); - if (real_target_type == TypeManager.uint64_type) + case BuiltinTypeSpec.Type.ULong: return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8); - if (real_target_type == TypeManager.char_type) + case BuiltinTypeSpec.Type.Char: return new ConvCast (expr, target_type, ConvCast.Mode.I4_CH); // One of the built-in conversions that belonged in the class library - if (real_target_type == TypeManager.uintptr_type){ - Expression u8e = new ConvCast (expr, TypeManager.uint64_type, ConvCast.Mode.I2_U8); - - return new OperatorCast (u8e, TypeManager.uintptr_type, true); + case BuiltinTypeSpec.Type.UIntPtr: + return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true); } - } else if (expr_type == TypeManager.uint32_type){ + break; + case BuiltinTypeSpec.Type.UInt: // // From uint to sbyte, byte, short, ushort, int, char // - if (real_target_type == TypeManager.sbyte_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1); - if (real_target_type == TypeManager.byte_type) + case BuiltinTypeSpec.Type.Byte: return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1); - if (real_target_type == TypeManager.short_type) + case BuiltinTypeSpec.Type.Short: return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2); - if (real_target_type == TypeManager.ushort_type) + case BuiltinTypeSpec.Type.UShort: return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2); - if (real_target_type == TypeManager.int32_type) + case BuiltinTypeSpec.Type.Int: return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4); - if (real_target_type == TypeManager.char_type) + case BuiltinTypeSpec.Type.Char: return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH); - } else if (expr_type == TypeManager.int64_type){ + } + break; + case BuiltinTypeSpec.Type.Long: // // From long to sbyte, byte, short, ushort, int, uint, ulong, char // - if (real_target_type == TypeManager.sbyte_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1); - if (real_target_type == TypeManager.byte_type) + case BuiltinTypeSpec.Type.Byte: return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1); - if (real_target_type == TypeManager.short_type) + case BuiltinTypeSpec.Type.Short: return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2); - if (real_target_type == TypeManager.ushort_type) + case BuiltinTypeSpec.Type.UShort: return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2); - if (real_target_type == TypeManager.int32_type) + case BuiltinTypeSpec.Type.Int: return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4); - if (real_target_type == TypeManager.uint32_type) + case BuiltinTypeSpec.Type.UInt: return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4); - if (real_target_type == TypeManager.uint64_type) + case BuiltinTypeSpec.Type.ULong: return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8); - if (real_target_type == TypeManager.char_type) + case BuiltinTypeSpec.Type.Char: return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH); - } else if (expr_type == TypeManager.uint64_type){ + } + break; + case BuiltinTypeSpec.Type.ULong: // // From ulong to sbyte, byte, short, ushort, int, uint, long, char // - if (real_target_type == TypeManager.sbyte_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1); - if (real_target_type == TypeManager.byte_type) + case BuiltinTypeSpec.Type.Byte: return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1); - if (real_target_type == TypeManager.short_type) + case BuiltinTypeSpec.Type.Short: return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2); - if (real_target_type == TypeManager.ushort_type) + case BuiltinTypeSpec.Type.UShort: return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2); - if (real_target_type == TypeManager.int32_type) + case BuiltinTypeSpec.Type.Int: return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4); - if (real_target_type == TypeManager.uint32_type) + case BuiltinTypeSpec.Type.UInt: return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4); - if (real_target_type == TypeManager.int64_type) + case BuiltinTypeSpec.Type.Long: return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8); - if (real_target_type == TypeManager.char_type) + case BuiltinTypeSpec.Type.Char: return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH); // One of the built-in conversions that belonged in the class library - if (real_target_type == TypeManager.intptr_type){ - return new OperatorCast (EmptyCast.Create (expr, TypeManager.int64_type), - TypeManager.intptr_type, true); + case BuiltinTypeSpec.Type.IntPtr: + return new OperatorCast (EmptyCast.Create (expr, rc.BuiltinTypes.Long), target_type, true); } - } else if (expr_type == TypeManager.char_type){ + break; + case BuiltinTypeSpec.Type.Char: // // From char to sbyte, byte, short // - if (real_target_type == TypeManager.sbyte_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1); - if (real_target_type == TypeManager.byte_type) + case BuiltinTypeSpec.Type.Byte: return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1); - if (real_target_type == TypeManager.short_type) + case BuiltinTypeSpec.Type.Short: return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2); - } else if (expr_type == TypeManager.float_type){ + } + break; + case BuiltinTypeSpec.Type.Float: // // From float to sbyte, byte, short, // ushort, int, uint, long, ulong, char // or decimal // - if (real_target_type == TypeManager.sbyte_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1); - if (real_target_type == TypeManager.byte_type) + case BuiltinTypeSpec.Type.Byte: return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1); - if (real_target_type == TypeManager.short_type) + case BuiltinTypeSpec.Type.Short: return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2); - if (real_target_type == TypeManager.ushort_type) + case BuiltinTypeSpec.Type.UShort: return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2); - if (real_target_type == TypeManager.int32_type) + case BuiltinTypeSpec.Type.Int: return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4); - if (real_target_type == TypeManager.uint32_type) + case BuiltinTypeSpec.Type.UInt: return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4); - if (real_target_type == TypeManager.int64_type) + case BuiltinTypeSpec.Type.Long: return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8); - if (real_target_type == TypeManager.uint64_type) + case BuiltinTypeSpec.Type.ULong: return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8); - if (real_target_type == TypeManager.char_type) + case BuiltinTypeSpec.Type.Char: return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH); - if (real_target_type == TypeManager.decimal_type) - return new CastToDecimal (expr, true); - } else if (expr_type == TypeManager.double_type){ + case BuiltinTypeSpec.Type.Decimal: + return new OperatorCast (expr, target_type, true); + } + break; + case BuiltinTypeSpec.Type.Double: // // From double to sbyte, byte, short, // ushort, int, uint, long, ulong, // char, float or decimal // - if (real_target_type == TypeManager.sbyte_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1); - if (real_target_type == TypeManager.byte_type) + case BuiltinTypeSpec.Type.Byte: return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1); - if (real_target_type == TypeManager.short_type) + case BuiltinTypeSpec.Type.Short: return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2); - if (real_target_type == TypeManager.ushort_type) + case BuiltinTypeSpec.Type.UShort: return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2); - if (real_target_type == TypeManager.int32_type) + case BuiltinTypeSpec.Type.Int: return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4); - if (real_target_type == TypeManager.uint32_type) + case BuiltinTypeSpec.Type.UInt: return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4); - if (real_target_type == TypeManager.int64_type) + case BuiltinTypeSpec.Type.Long: return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8); - if (real_target_type == TypeManager.uint64_type) + case BuiltinTypeSpec.Type.ULong: return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8); - if (real_target_type == TypeManager.char_type) + case BuiltinTypeSpec.Type.Char: return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH); - if (real_target_type == TypeManager.float_type) + case BuiltinTypeSpec.Type.Float: return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4); - if (real_target_type == TypeManager.decimal_type) - return new CastToDecimal (expr, true); - } else if (expr_type == TypeManager.uintptr_type){ + case BuiltinTypeSpec.Type.Decimal: + return new OperatorCast (expr, target_type, true); + } + break; + case BuiltinTypeSpec.Type.UIntPtr: // // Various built-in conversions that belonged in the class library // // from uintptr to sbyte, short, int32 // - if (real_target_type == TypeManager.sbyte_type){ - Expression uint32e = new OperatorCast (expr, TypeManager.uint32_type, true); - return new ConvCast (uint32e, TypeManager.sbyte_type, ConvCast.Mode.U4_I1); + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I2); + case BuiltinTypeSpec.Type.Int: + return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type); + case BuiltinTypeSpec.Type.UInt: + return new OperatorCast (expr, expr.Type, target_type, true); + case BuiltinTypeSpec.Type.Long: + return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.ULong, true), target_type); } - if (real_target_type == TypeManager.short_type){ - Expression uint32e = new OperatorCast (expr, TypeManager.uint32_type, true); - return new ConvCast (uint32e, TypeManager.sbyte_type, ConvCast.Mode.U4_I2); - } - if (real_target_type == TypeManager.int32_type){ - return EmptyCast.Create (new OperatorCast (expr, TypeManager.uint32_type, true), - TypeManager.int32_type); - } - } else if (expr_type == TypeManager.intptr_type){ - if (real_target_type == TypeManager.uint64_type){ - return EmptyCast.Create (new OperatorCast (expr, TypeManager.int64_type, true), - TypeManager.uint64_type); + break; + case BuiltinTypeSpec.Type.IntPtr: + if (target_type.BuiltinType == BuiltinTypeSpec.Type.UInt) + return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Int, true), target_type); + if (target_type.BuiltinType == BuiltinTypeSpec.Type.ULong) + return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Long, true), target_type); + + break; + case BuiltinTypeSpec.Type.Decimal: + // From decimal to sbyte, byte, short, + // ushort, int, uint, long, ulong, char, + // float, or double + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.Double: + return new OperatorCast (expr, expr.Type, target_type, true); } - } else if (expr_type == TypeManager.decimal_type) { - return new CastFromDecimal (expr, target_type).Resolve (); + + break; } + return null; } @@ -1681,7 +1751,7 @@ namespace Mono.CSharp { // // From object to a generic parameter // - if (source_type == TypeManager.object_type && TypeManager.IsGenericParameter (target_type)) + if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object && TypeManager.IsGenericParameter (target_type)) return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type); // @@ -1690,18 +1760,18 @@ namespace Mono.CSharp { if (source_type.Kind == MemberKind.TypeParameter) return ExplicitTypeParameterConversion (source, source_type, target_type); - bool target_is_value_type = TypeManager.IsStruct (target_type) || TypeManager.IsEnumType (target_type); + bool target_is_value_type = target_type.Kind == MemberKind.Struct || target_type.Kind == MemberKind.Enum; // // Unboxing conversion from System.ValueType to any non-nullable-value-type // - if (source_type == TypeManager.value_type && target_is_value_type) + if (source_type.BuiltinType == BuiltinTypeSpec.Type.ValueType && target_is_value_type) return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type); // // From object or dynamic to any reference type or value type (unboxing) // - if (source_type == TypeManager.object_type || source_type == InternalType.Dynamic) { + if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object || source_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { if (target_type.IsPointer) return null; @@ -1722,7 +1792,7 @@ namespace Mono.CSharp { // From any interface-type S to to any class type T, provided T is not // sealed, or provided T implements S. // - if (source_type.IsInterface) { + if (source_type.Kind == MemberKind.Interface) { if (!target_type.IsSealed || target_type.ImplementsInterface (source_type, true)) { if (source == null) return EmptyExpression.Null; @@ -1752,7 +1822,7 @@ namespace Mono.CSharp { // // From System.Array to any array-type // - if (source_type == TypeManager.array_type) + if (source_type.BuiltinType == BuiltinTypeSpec.Type.Array) return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); // @@ -1766,11 +1836,11 @@ namespace Mono.CSharp { if (source_array.Rank == target_array.Rank) { source_type = source_array.Element; - if (!TypeManager.IsReferenceType (source_type)) + if (!TypeSpec.IsReferenceType (source_type)) return null; var target_element = target_array.Element; - if (!TypeManager.IsReferenceType (target_element)) + if (!TypeSpec.IsReferenceType (target_element)) return null; if (ExplicitReferenceConversionExists (source_type, target_element)) @@ -1801,7 +1871,7 @@ namespace Mono.CSharp { // // From System delegate to any delegate-type // - if (source_type == TypeManager.delegate_type && TypeManager.IsDelegateType (target_type)) + if (source_type.BuiltinType == BuiltinTypeSpec.Type.Delegate && target_type.IsDelegate) return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); // @@ -1823,7 +1893,7 @@ namespace Mono.CSharp { // //If TP is covariant, an implicit or explicit identity or reference conversion is required // - if (ImplicitReferenceConversionExists (new EmptyExpression (targs_src[i]), targs_dst[i])) + if (ImplicitReferenceConversionExists (targs_src[i], targs_dst[i])) continue; if (ExplicitReferenceConversionExists (targs_src[i], targs_dst[i])) @@ -1833,7 +1903,7 @@ namespace Mono.CSharp { // //If TP is contravariant, both are either identical or reference types // - if (TypeManager.IsReferenceType (targs_src[i]) && TypeManager.IsReferenceType (targs_dst[i])) + if (TypeSpec.IsReferenceType (targs_src[i]) && TypeSpec.IsReferenceType (targs_dst[i])) continue; } @@ -1861,8 +1931,8 @@ namespace Mono.CSharp { if (ne != null) return ne; - if (TypeManager.IsEnumType (expr_type)) { - TypeSpec real_target = TypeManager.IsEnumType (target_type) ? EnumSpec.GetUnderlyingType (target_type) : target_type; + if (expr_type.IsEnum) { + TypeSpec real_target = target_type.IsEnum ? EnumSpec.GetUnderlyingType (target_type) : target_type; Expression underlying = EmptyCast.Create (expr, EnumSpec.GetUnderlyingType (expr_type)); if (underlying.Type == real_target) ne = underlying; @@ -1871,25 +1941,25 @@ namespace Mono.CSharp { ne = ImplicitNumericConversion (underlying, real_target); if (ne == null) - ne = ExplicitNumericConversion (underlying, real_target); + ne = ExplicitNumericConversion (ec, underlying, real_target); // // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed // - if (ne == null && (real_target == TypeManager.intptr_type || real_target == TypeManager.uintptr_type)) + if (ne == null && (real_target.BuiltinType == BuiltinTypeSpec.Type.IntPtr || real_target.BuiltinType == BuiltinTypeSpec.Type.UIntPtr)) ne = ExplicitUserConversion (ec, underlying, real_target, loc); return ne != null ? EmptyCast.Create (ne, target_type) : null; } - if (TypeManager.IsEnumType (target_type)) { + if (target_type.IsEnum) { // // System.Enum can be unboxed to any enum-type // - if (expr_type == TypeManager.enum_type) + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Enum) return new UnboxCast (expr, target_type); - TypeSpec real_target = TypeManager.IsEnumType (target_type) ? EnumSpec.GetUnderlyingType (target_type) : target_type; + TypeSpec real_target = target_type.IsEnum ? EnumSpec.GetUnderlyingType (target_type) : target_type; if (expr_type == real_target) return EmptyCast.Create (expr, target_type); @@ -1898,20 +1968,20 @@ namespace Mono.CSharp { if (ne != null) return EmptyCast.Create (ne, target_type); - ne = ExplicitNumericConversion (expr, real_target); + ne = ExplicitNumericConversion (ec, expr, real_target); if (ne != null) return EmptyCast.Create (ne, target_type); // // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed // - if (expr_type == TypeManager.intptr_type || expr_type == TypeManager.uintptr_type) { + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.IntPtr || expr_type.BuiltinType == BuiltinTypeSpec.Type.UIntPtr) { ne = ExplicitUserConversion (ec, expr, real_target, loc); if (ne != null) return ExplicitConversionCore (ec, ne, target_type, loc); } } else { - ne = ExplicitNumericConversion (expr, target_type); + ne = ExplicitNumericConversion (ec, expr, target_type); if (ne != null) return ne; } @@ -1921,7 +1991,7 @@ namespace Mono.CSharp { // from Null to a ValueType, and ExplicitReference wont check against // null literal explicitly // - if (expr_type != InternalType.Null) { + if (expr_type != InternalType.NullLiteral) { ne = ExplicitReferenceConversion (expr, expr_type, target_type); if (ne != null) return ne; @@ -1944,40 +2014,44 @@ namespace Mono.CSharp { if (expr_type.IsPointer) return EmptyCast.Create (expr, target_type); - if (expr_type == TypeManager.sbyte_type || - expr_type == TypeManager.short_type || - expr_type == TypeManager.int32_type) + switch (expr_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.Int: return new OpcodeCast (expr, target_type, OpCodes.Conv_I); - if (expr_type == TypeManager.ushort_type || - expr_type == TypeManager.uint32_type || - expr_type == TypeManager.byte_type) + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Byte: return new OpcodeCast (expr, target_type, OpCodes.Conv_U); - if (expr_type == TypeManager.int64_type) + case BuiltinTypeSpec.Type.Long: return new ConvCast (expr, target_type, ConvCast.Mode.I8_I); - if (expr_type == TypeManager.uint64_type) + case BuiltinTypeSpec.Type.ULong: return new ConvCast (expr, target_type, ConvCast.Mode.U8_I); + } } if (expr_type.IsPointer){ - if (target_type == TypeManager.sbyte_type) + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: return new OpcodeCast (expr, target_type, OpCodes.Conv_I1); - if (target_type == TypeManager.byte_type) + case BuiltinTypeSpec.Type.Byte: return new OpcodeCast (expr, target_type, OpCodes.Conv_U1); - if (target_type == TypeManager.short_type) + case BuiltinTypeSpec.Type.Short: return new OpcodeCast (expr, target_type, OpCodes.Conv_I2); - if (target_type == TypeManager.ushort_type) + case BuiltinTypeSpec.Type.UShort: return new OpcodeCast (expr, target_type, OpCodes.Conv_U2); - if (target_type == TypeManager.int32_type) + case BuiltinTypeSpec.Type.Int: return new OpcodeCast (expr, target_type, OpCodes.Conv_I4); - if (target_type == TypeManager.uint32_type) + case BuiltinTypeSpec.Type.UInt: return new OpcodeCast (expr, target_type, OpCodes.Conv_U4); - if (target_type == TypeManager.int64_type) + case BuiltinTypeSpec.Type.Long: return new ConvCast (expr, target_type, ConvCast.Mode.I_I8); - if (target_type == TypeManager.uint64_type) + case BuiltinTypeSpec.Type.ULong: return new OpcodeCast (expr, target_type, OpCodes.Conv_U8); + } } return null; } @@ -1996,7 +2070,7 @@ namespace Mono.CSharp { if (ne != null) return ne; - ne = ExplicitNumericConversion (expr, target_type); + ne = ExplicitNumericConversion (ec, expr, target_type); if (ne != null) return ne; @@ -2004,7 +2078,7 @@ namespace Mono.CSharp { if (ne != null) return ne; - if (ec.IsUnsafe && expr.Type.IsPointer && target_type.IsPointer && ((PointerContainer)expr.Type).Element.BuildinType == BuildinTypeSpec.Type.Void) + if (ec.IsUnsafe && expr.Type.IsPointer && target_type.IsPointer && ((PointerContainer)expr.Type).Element.Kind == MemberKind.Void) return EmptyCast.Create (expr, target_type); expr.Error_ValueCannotBeConverted (ec, l, target_type, true); @@ -2024,10 +2098,10 @@ namespace Mono.CSharp { // Don't eliminate explicit precission casts // if (e == expr) { - if (target_type == TypeManager.float_type) + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Float) return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); - if (target_type == TypeManager.double_type) + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double) return new OpcodeCast (expr, target_type, OpCodes.Conv_R8); } @@ -2035,25 +2109,27 @@ namespace Mono.CSharp { } TypeSpec expr_type = expr.Type; - if (TypeManager.IsNullableType (target_type)) { - if (TypeManager.IsNullableType (expr_type)) { - TypeSpec target = Nullable.NullableInfo.GetUnderlyingType (target_type); + if (target_type.IsNullableType) { + TypeSpec target; + + if (expr_type.IsNullableType) { + target = Nullable.NullableInfo.GetUnderlyingType (target_type); Expression unwrap = Nullable.Unwrap.Create (expr); e = ExplicitConversion (ec, unwrap, target, expr.Location); if (e == null) return null; return new Nullable.Lifted (e, unwrap, target_type).Resolve (ec); - } else if (expr_type == TypeManager.object_type) { + } + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Object) { return new UnboxCast (expr, target_type); - } else { - TypeSpec target = TypeManager.GetTypeArguments (target_type) [0]; - - e = ExplicitConversionCore (ec, expr, target, loc); - if (e != null) - return Nullable.Wrap.Create (e, target_type); } - } else if (TypeManager.IsNullableType (expr_type)) { + + target = TypeManager.GetTypeArguments (target_type) [0]; + e = ExplicitConversionCore (ec, expr, target, loc); + if (e != null) + return Nullable.Wrap.Create (e, target_type); + } else if (expr_type.IsNullableType) { e = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type); if (e != null) return e;