2005-01-19 Sureshkumar T <tsureshkumar@novell.com>
[mono.git] / mcs / gmcs / convert.cs
index d95cefc32f4bda960092fad117432a5644a454c4..e6bdf4674c0c7a0c35c58e5000ac1e8785e4e066 100644 (file)
@@ -29,7 +29,7 @@ namespace Mono.CSharp {
                //
                public static EmitContext ConstantEC = null;
                
-               static void Error_CannotConvertType (Location loc, Type source, Type target)
+               static public void Error_CannotConvertType (Location loc, Type source, Type target)
                {
                        Report.Error (30, loc, "Cannot convert type '" +
                                      TypeManager.CSharpName (source) + "' to '" +
@@ -52,12 +52,16 @@ namespace Mono.CSharp {
 
                static bool TypeParameter_to_Null (Type target_type)
                {
-                       if ((target_type.BaseType == null) ||
-                           (target_type.BaseType == TypeManager.value_type) ||
-                           target_type.BaseType.IsValueType)
+                       GenericConstraints gc = TypeManager.GetTypeParameterConstraints (target_type);
+                       if (gc == null)
                                return false;
 
-                       return true;
+                       if (gc.HasReferenceTypeConstraint)
+                               return true;
+                       if (gc.HasClassConstraint && !TypeManager.IsValueType (gc.ClassConstraint))
+                               return true;
+
+                       return false;
                }
 
                static Type TypeParam_EffectiveBaseType (EmitContext ec, Type t)
@@ -164,7 +168,7 @@ namespace Mono.CSharp {
                                if (TypeManager.IsValueType (expr_type))
                                        return new BoxedCast (expr);
                                if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type){
-                                       if (target_type == TypeManager.anonymous_method_type)
+                                       if (expr_type == TypeManager.anonymous_method_type)
                                                return null;
                                        return new EmptyCast (expr, target_type);
                                }
@@ -197,7 +201,7 @@ namespace Mono.CSharp {
                        // from the null type to any reference-type.
                        if (expr_type == TypeManager.null_type){
                                if (target_type.IsPointer)
-                                       return NullPointer.Null;
+                                       return new EmptyCast (expr, target_type);
                                        
                                if (!target_type.IsValueType)
                                        return new NullCast (expr, target_type);
@@ -301,6 +305,16 @@ namespace Mono.CSharp {
                                
                        // from any class-type S to any interface-type T.
                        if (target_type.IsInterface) {
+                               if (target_type != TypeManager.iconvertible_type &&
+                                   expr_type.IsValueType && (expr is Constant) &&
+                                   !(expr is IntLiteral || expr is BoolLiteral ||
+                                     expr is FloatLiteral || expr is DoubleLiteral ||
+                                     expr is LongLiteral || expr is CharLiteral ||
+                                     expr is StringLiteral || expr is DecimalLiteral ||
+                                     expr is UIntLiteral || expr is ULongLiteral)) {
+                                       return false;
+                               }
+                               
                                if (TypeManager.ImplementsInterface (expr_type, target_type))
                                        return true;
                        }
@@ -346,8 +360,13 @@ namespace Mono.CSharp {
                                        return true;
                                
                        // from the null type to any reference-type.
-                       if (expr_type == TypeManager.null_type && !target_type.IsValueType && !TypeManager.IsEnumType (target_type))
-                               return true;
+                       if (expr_type == TypeManager.null_type){
+                               if (target_type.IsPointer)
+                                       return true;
+                       
+                               if (!target_type.IsValueType)
+                                       return true;
+                       }
 
                        // from a generic type definition to a generic instance.
                        if (TypeManager.IsEqual (expr_type, target_type))
@@ -1312,7 +1331,7 @@ namespace Mono.CSharp {
                                //
                                // Possibly, we need to create a different 0 literal before passing
                                // to EnumConstant
-                               //n
+                               //
                                if (underlying == TypeManager.int64_type)
                                        e = new LongLiteral (0);
                                else if (underlying == TypeManager.uint64_type)
@@ -1325,6 +1344,13 @@ namespace Mono.CSharp {
 
                static public void Error_CannotImplicitConversion (Location loc, Type source, Type target)
                {
+                       if (source.Name == target.Name){
+                               Report.ExtraInformation (loc,
+                                        String.Format (
+                                               "The type {0} has two conflicting definitons, one comes from {0} and the other from {1}",
+                                               source.Assembly.FullName, target.Assembly.FullName));
+                                                        
+                       }
                        Report.Error (29, loc, "Cannot convert implicitly from {0} to `{1}'",
                                      source == TypeManager.anonymous_method_type ?
                                      "anonymous method" : "`" + TypeManager.CSharpName (source) + "'",
@@ -1348,10 +1374,15 @@ namespace Mono.CSharp {
                        if (e != null)
                                return e;
 
-                       if (source is DoubleLiteral && target_type == TypeManager.float_type){
-                               Report.Error (664, loc,
-                                             "Double literal cannot be implicitly converted to " +
-                                             "float type, use F suffix to create a float literal");
+                       if (source is DoubleLiteral) {
+                               if (target_type == TypeManager.float_type) {
+                                       Error_664 (loc, "float", "f");
+                                       return null;
+                               }
+                               if (target_type == TypeManager.decimal_type) {
+                                       Error_664 (loc, "decimal", "m");
+                                       return null;
+                               }
                        }
 
                        if (source is Constant){
@@ -1366,6 +1397,12 @@ namespace Mono.CSharp {
                        return null;
                }
 
+               static void Error_664 (Location loc, string type, string suffix) {
+                       Report.Error (664, loc,
+                               "Literal of type double cannot be implicitly converted to type '{0}'. Add suffix '{1}' to create a literal of this type",
+                               type, suffix);
+               }
+
                /// <summary>
                ///   Performs the explicit numeric conversions
                /// </summary>