Fix the monotouch build
[mono.git] / mcs / mcs / convert.cs
index 009716e8aead6b550227ab2073431f069f7056fa..5a1ebe831644b3503fed44d4b0f3eacdf4a1a14e 100644 (file)
@@ -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<MethodSpec> candidates)
+               static void FindApplicableUserDefinedConversionOperators (IList<MemberSpec> operators, Expression source, TypeSpec target, bool implicitOnly, ref List<MethodSpec> 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);
 
                        //