X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fconvert.cs;h=5a1ebe831644b3503fed44d4b0f3eacdf4a1a14e;hb=21dd2b0200d091c43fce9e1941e8ab5e111f3651;hp=009716e8aead6b550227ab2073431f069f7056fa;hpb=64a55b9a1ce8d432f47b58901568c68e1b2e2d55;p=mono.git diff --git a/mcs/mcs/convert.cs b/mcs/mcs/convert.cs index 009716e8aea..5a1ebe83164 100644 --- a/mcs/mcs/convert.cs +++ b/mcs/mcs/convert.cs @@ -92,15 +92,35 @@ namespace Mono.CSharp { static Expression ImplicitTypeParameterConversion (Expression expr, TypeSpec target_type) { var expr_type = (TypeParameterSpec) expr.Type; + // - // From T to a type parameter U + // From T to a type parameter U, provided T depends on U // var ttype = target_type as TypeParameterSpec; if (ttype != null) { - if (expr_type.IsReferenceType && !ttype.IsReferenceType) - return new BoxedCast (expr, target_type); + if (expr_type.TypeArguments != null) { + foreach (var targ in expr_type.TypeArguments) { + if (!TypeSpecComparer.Override.IsEqual (ttype, targ)) + continue; + + if (expr_type.IsReferenceType && !ttype.IsReferenceType) + return new BoxedCast (expr, target_type); + + return new ClassCast (expr, target_type); + } + } + + return null; + } - return new ClassCast (expr, target_type); + // + // LAMESPEC: From T to dynamic type + // + if (target_type == InternalType.Dynamic) { + if (expr_type.IsReferenceType) + return new ClassCast (expr, target_type); + + return new BoxedCast (expr, target_type); } // @@ -130,6 +150,15 @@ namespace Mono.CSharp { { var target_tp = target_type as TypeParameterSpec; if (target_tp != null) { + if (target_tp.TypeArguments != null) { + foreach (var targ in target_tp.TypeArguments) { + if (!TypeSpecComparer.Override.IsEqual (source_type, targ)) + continue; + + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + } + } + if (target_tp.Interfaces != null) { foreach (TypeSpec iface in target_tp.Interfaces) { if (!TypeManager.IsGenericParameter (iface)) @@ -229,7 +258,7 @@ namespace Mono.CSharp { if (TypeManager.IsValueType (expr_type)) return false; - if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type || expr_type.IsDelegate) { + if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type || expr_type.IsDelegate || expr_type.Kind == MemberKind.ArrayType) { // No mcs internal types are convertible return true; // expr_type.MetaInfo.Module != typeof (Convert).Module; } @@ -706,9 +735,6 @@ namespace Mono.CSharp { if (value >= 0) return true; } - - if (value == 0 && target_type.IsEnum) - return true; } if (expr is LongConstant && target_type == TypeManager.uint64_type){ @@ -722,6 +748,18 @@ namespace Mono.CSharp { return true; } + if (expr is IntegralConstant && TypeManager.IsEnumType (target_type)) { + var i = (IntegralConstant) expr; + // + // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0 + // + // An implicit enumeration conversion permits the decimal-integer-literal 0 + // to be converted to any enum-type and to any nullable-type whose underlying + // type is an enum-type + // + return i.IsZeroInteger; + } + // // If `expr_type' implements `target_type' (which is an iface) // see TryImplicitIntConversion @@ -928,7 +966,7 @@ namespace Mono.CSharp { return UserDefinedConversion (ec, source, target, false, loc); } - static void FindApplicableUserDefinedConversionOperators (MethodSpec[] operators, Expression source, TypeSpec target, bool implicitOnly, ref List candidates) + static void FindApplicableUserDefinedConversionOperators (IList operators, Expression source, TypeSpec target, bool implicitOnly, ref List candidates) { // // LAMESPEC: Undocumented IntPtr/UIntPtr conversions @@ -951,7 +989,12 @@ namespace Mono.CSharp { Expression texpr = null; - foreach (var op in operators) { + foreach (MethodSpec op in operators) { + + // Can be null because MemberCache.GetUserOperator does not resize the array + if (op == null) + continue; + var t = op.Parameters.Types[0]; if (source.Type != t && !ImplicitStandardConversionExists (source, t)) { if (implicitOnly) @@ -1214,17 +1257,19 @@ namespace Mono.CSharp { if (e != null) return e; - if (expr is IntConstant && TypeManager.IsEnumType (target_type)){ - Constant i = (Constant) expr; + if (expr is IntegralConstant && TypeManager.IsEnumType (target_type)){ + var i = (IntegralConstant) expr; // - // LAMESPEC: Conversion from any 0 constant is allowed + // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0 // // An implicit enumeration conversion permits the decimal-integer-literal 0 // to be converted to any enum-type and to any nullable-type whose underlying // type is an enum-type // - if (i.IsDefaultValue) - return new EnumConstant (i, target_type).Resolve (ec); + if (i.IsZeroInteger) { + // Recreate 0 literal to remove any collected conversions + return new EnumConstant (new IntLiteral (0, i.Location), target_type).Resolve (ec); + } } if (ec.IsUnsafe) { @@ -1583,7 +1628,7 @@ namespace Mono.CSharp { // // Explicit type parameter conversion. // - if (TypeManager.IsGenericParameter (source_type)) + 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); @@ -1607,7 +1652,7 @@ namespace Mono.CSharp { // // From any class S to any class-type T, provided S is a base class of T // - if (TypeManager.IsSubclassOf (target_type, source_type)) + if (source_type.Kind == MemberKind.Class && TypeManager.IsSubclassOf (target_type, source_type)) return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); //