Revert r51122 since it's causing strange failures. Restore tree to bootstrap-land
authorRaja R Harinath <harinath@hurrynot.org>
Mon, 3 Oct 2005 18:20:57 +0000 (18:20 -0000)
committerRaja R Harinath <harinath@hurrynot.org>
Mon, 3 Oct 2005 18:20:57 +0000 (18:20 -0000)
svn path=/trunk/mcs/; revision=51131

mcs/mcs/ChangeLog
mcs/mcs/assign.cs
mcs/mcs/cfold.cs
mcs/mcs/const.cs
mcs/mcs/constant.cs
mcs/mcs/convert.cs
mcs/mcs/ecore.cs
mcs/mcs/enum.cs
mcs/mcs/expression.cs
mcs/mcs/literal.cs
mcs/mcs/statement.cs

index 2ed1b2a3f24302af11849511077fccbdaf4fbe48..c5e2f5eb3960796c5976f926b1d69fd58e90cd96 100644 (file)
@@ -1,36 +1,3 @@
-2005-10-03  Marek Safar  <marek.safar@seznam.cz>
-
-       * assign.cs (Assign.DoResolve): Implicit conversion is more
-       strict.
-
-       * cfold.cs (DoConstantNumericPromotions): Error method changed.
-       
-       * const.cs (ResolveValue): Reset in_transit immediately.
-       
-       * constant.cs: Error method changed.
-       
-       * convert.cs: Removed useless location parameter.
-       (ExplicitNumericConversion): Don't do double enum check.
-       (ExplicitConversionCore): Renamed from ExplicitConversion.
-       (ExplicitUnsafe): Extracted from ExplicitConversion.
-       (ExplicitConversion): Uses for error reporting.
-       
-       * ecore.cs (Error_ValueCannotBeConverted): More logic for more
-       error messages.
-       (ResolveBoolean): Uses common error method.
-       (CastToDecimal): Get rid of ec.
-       (CastFromDecimal): Optimized.
-       (ConvCast): Get rid of ec.
-       
-       * enum.cs (ResolveValue): Reset in_transit immediately.
-       (Emit): Return after first error.
-       
-       * expression.cs: Convert changes.
-       
-       * literal.cs: Error method changed.
-       
-       * statement.cs: Error method changed.
-
 2005-10-03  Raja R Harinath  <rharinath@novell.com>
 
        * support.cs (SeekableStreamReader.Position): Don't error out when
index 54c20d2ece313b6a5555d4cca2a6e0afcfd48e9b..f7e28fd7a2269e8984e915a571d5ea06a684ba79 100644 (file)
@@ -458,13 +458,16 @@ namespace Mono.CSharp {
                                Binary b = source as Binary;
                                if (b != null){
                                        //
-                                       // In the spec 2.4 they added: or if type of the target is int
-                                       // and the operator is a shift operator...
+                                       // 1. if the source is explicitly convertible to the
+                                       //    target_type
                                        //
-                                       if (source_type == TypeManager.int32_type &&
-                                               (b.Oper == Binary.Operator.LeftShift || b.Oper == Binary.Operator.RightShift))
-                                               return this;
-
+                                       
+                                       source = Convert.ExplicitConversion (ec, source, target_type, loc);
+                                       if (source == null){
+                                               Convert.Error_CannotImplicitConversion (loc, source_type, target_type);
+                                               return null;
+                                       }
+                               
                                        //
                                        // 2. and the original right side is implicitly convertible to
                                        // the type of target
@@ -472,7 +475,15 @@ namespace Mono.CSharp {
                                        if (Convert.ImplicitStandardConversionExists (ec, a.original_source, target_type))
                                                return this;
 
-                                       source.Error_ValueCannotBeConverted (loc, target_type, false);
+                                       //
+                                       // In the spec 2.4 they added: or if type of the target is int
+                                       // and the operator is a shift operator...
+                                       //
+                                       if (source_type == TypeManager.int32_type &&
+                                           (b.Oper == Binary.Operator.LeftShift || b.Oper == Binary.Operator.RightShift))
+                                               return this;
+
+                                       Convert.Error_CannotImplicitConversion (loc, a.original_source.Type, target_type);
                                        return null;
                                }
                        }
index 4b09e39b5e93f250a67a346de5ac9843f10081ff..f9cc1d2204e198a9e9baf72f954f89697740e9ac 100644 (file)
@@ -162,7 +162,7 @@ namespace Mono.CSharp {
 
                                if (need_check &&
                                    !Convert.ImplicitConversionExists (ec, match, other.Type)) {
-                                       match.Error_ValueCannotBeConverted (loc, other.Type, false);
+                                       Convert.Error_CannotImplicitConversion (loc, match.Type, other.Type);
                                        left = null;
                                        right = null;
                                        return;
index e639f9b559f294748c551dafe363257039ba2189..7d489c39cce29638828901ab6274442363f297fe 100644 (file)
@@ -138,8 +138,6 @@ namespace Mono.CSharp {
                        in_transit = true;
                        EmitContext ec = new EmitContext (Parent, Location, null, MemberType, ModFlags);
                        value = Expr.ResolveAsConstant (ec, this);
-                       in_transit = false;
-
                        if (value == null)
                                return false;
 
@@ -153,6 +151,7 @@ namespace Mono.CSharp {
                                return false;
                        }
 
+                       in_transit = false;
                        return true;
                }
 
index 0f0a580477a720c951b3b203f7d378e0f55f6cb8..3f72833379e6988688954440508d8b0174a77bdd 100644 (file)
@@ -57,6 +57,17 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               public override void Error_ValueCannotBeConverted (Location loc, Type t)
+               {
+                       // string is not real constant
+                       if (type == TypeManager.string_type)
+                               base.Error_ValueCannotBeConverted (loc, t);
+                       else
+                               Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
+                                       AsString (), TypeManager.CSharpName (t));
+               }
+
+
                //
                // The various ToXXXX conversion functions are used by the constant
                // folding evaluator.   A null value is returned if the conversion is
@@ -73,7 +84,7 @@ namespace Mono.CSharp {
                        DoubleConstant c = ConvertToDouble ();
 
                        if (c == null)
-                               Error_ValueCannotBeConverted (loc, TypeManager.double_type, false);
+                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.double_type);
 
                        return c;
                }
@@ -83,7 +94,7 @@ namespace Mono.CSharp {
                        FloatConstant c = ConvertToFloat ();
 
                        if (c == null)
-                               Error_ValueCannotBeConverted (loc, TypeManager.float_type, false);
+                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.float_type);
 
                        return c;
                }
@@ -93,7 +104,7 @@ namespace Mono.CSharp {
                        ULongConstant c = ConvertToULong ();
 
                        if (c == null)
-                               Error_ValueCannotBeConverted (loc, TypeManager.uint64_type, false);
+                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint64_type);
 
                        return c;
                }
@@ -103,7 +114,7 @@ namespace Mono.CSharp {
                        LongConstant c = ConvertToLong ();
 
                        if (c == null)
-                               Error_ValueCannotBeConverted (loc, TypeManager.int64_type, false);
+                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int64_type);
 
                        return c;
                }
@@ -113,7 +124,7 @@ namespace Mono.CSharp {
                        UIntConstant c = ConvertToUInt ();
 
                        if (c == null)
-                               Error_ValueCannotBeConverted (loc, TypeManager.uint32_type, false);
+                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint32_type);
 
                        return c;
                }
@@ -123,7 +134,7 @@ namespace Mono.CSharp {
                        IntConstant c = ConvertToInt ();
 
                        if (c == null)
-                               Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
+                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int32_type);
 
                        return c;
                }
@@ -133,7 +144,7 @@ namespace Mono.CSharp {
                        DecimalConstant c = ConvertToDecimal ();
 
                        if (c == null)
-                               Error_ValueCannotBeConverted (loc, TypeManager.decimal_type, false);
+                               Convert.Error_CannotConvertType (loc, Type, TypeManager.decimal_type);
 
                        return c;
                }
@@ -147,7 +158,7 @@ namespace Mono.CSharp {
                                return this;
 
                        if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, this, type)){
-                               Error_ValueCannotBeConverted (loc, type, false);
+                               Error_ValueCannotBeConverted (loc, type);
                                return null;
                        }
 
@@ -160,7 +171,7 @@ namespace Mono.CSharp {
                        bool fail;                      
                        object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
                        if (fail){
-                               Error_ValueCannotBeConverted (loc, type, false);
+                               Convert.Error_CannotImplicitConversion (loc, Type, type);
                                
                                //
                                // We should always catch the error before this is ever
index 7ea3b969f51aa83dc50ff31a5f5f7927b421acf4..c8380ae29384c9f386ff8e01d1630cda3f303c6f 100644 (file)
@@ -29,6 +29,13 @@ namespace Mono.CSharp {
                //
                public static EmitContext ConstantEC = null;
                
+               static public void Error_CannotConvertType (Location loc, Type source, Type target)
+               {
+                       Report.Error (30, loc, "Cannot convert type '" +
+                                     TypeManager.CSharpName (source) + "' to '" +
+                                     TypeManager.CSharpName (target) + "'");
+               }
+
                static EmptyExpression MyEmptyExpr;
                static public Expression ImplicitReferenceConversion (Expression expr, Type target_type)
                {
@@ -268,7 +275,7 @@ namespace Mono.CSharp {
                ///   target_type or null if an implicit conversion is not possible.
                /// </summary>
                static public Expression ImplicitNumericConversion (EmitContext ec, Expression expr,
-                                                                   Type target_type)
+                                                                   Type target_type, Location loc)
                {
                        Type expr_type = expr.Type;
 
@@ -312,7 +319,7 @@ namespace Mono.CSharp {
                                if (real_target_type == TypeManager.short_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
                                if (real_target_type == TypeManager.decimal_type)
-                                       return new CastToDecimal (expr);
+                                       return new CastToDecimal (ec, expr);
                        } else if (expr_type == TypeManager.byte_type){
                                //
                                // From byte to short, ushort, int, uint, long, ulong, float, double, decimal
@@ -332,7 +339,7 @@ namespace Mono.CSharp {
                                if (real_target_type == TypeManager.double_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
                                if (real_target_type == TypeManager.decimal_type)
-                                       return new CastToDecimal (expr);
+                                       return new CastToDecimal (ec, expr);
                                
                        } else if (expr_type == TypeManager.short_type){
                                //
@@ -347,7 +354,7 @@ namespace Mono.CSharp {
                                if (real_target_type == TypeManager.float_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
                                if (real_target_type == TypeManager.decimal_type)
-                                       return new CastToDecimal (expr);
+                                       return new CastToDecimal (ec, expr);
                                
                        } else if (expr_type == TypeManager.ushort_type){
                                //
@@ -367,7 +374,7 @@ namespace Mono.CSharp {
                                if (real_target_type == TypeManager.float_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
                                if (real_target_type == TypeManager.decimal_type)
-                                       return new CastToDecimal (expr);
+                                       return new CastToDecimal (ec, expr);
                        } else if (expr_type == TypeManager.int32_type){
                                //
                                // From int to long, float, double, decimal
@@ -379,7 +386,7 @@ namespace Mono.CSharp {
                                if (real_target_type == TypeManager.float_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
                                if (real_target_type == TypeManager.decimal_type)
-                                       return new CastToDecimal (expr);
+                                       return new CastToDecimal (ec, expr);
                        } else if (expr_type == TypeManager.uint32_type){
                                //
                                // From uint to long, ulong, float, double, decimal
@@ -395,7 +402,7 @@ namespace Mono.CSharp {
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
                                                               OpCodes.Conv_R4);
                                if (real_target_type == TypeManager.decimal_type)
-                                       return new CastToDecimal (expr);
+                                       return new CastToDecimal (ec, expr);
                        } else if (expr_type == TypeManager.int64_type){
                                //
                                // From long/ulong to float, double
@@ -405,7 +412,7 @@ namespace Mono.CSharp {
                                if (real_target_type == TypeManager.float_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
                                if (real_target_type == TypeManager.decimal_type)
-                                       return new CastToDecimal (expr);
+                                       return new CastToDecimal (ec, expr);
                        } else if (expr_type == TypeManager.uint64_type){
                                //
                                // From ulong to float, double
@@ -417,7 +424,7 @@ namespace Mono.CSharp {
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
                                                               OpCodes.Conv_R4);
                                if (real_target_type == TypeManager.decimal_type)
-                                       return new CastToDecimal (expr);
+                                       return new CastToDecimal (ec, expr);
                        } else if (expr_type == TypeManager.char_type){
                                //
                                // From char to ushort, int, uint, long, ulong, float, double, decimal
@@ -435,7 +442,7 @@ namespace Mono.CSharp {
                                if (real_target_type == TypeManager.double_type)
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
                                if (real_target_type == TypeManager.decimal_type)
-                                       return new CastToDecimal (expr);
+                                       return new CastToDecimal (ec, expr);
                        } else if (expr_type == TypeManager.float_type){
                                //
                                // float to double
@@ -447,6 +454,7 @@ namespace Mono.CSharp {
                        return null;
                }
 
+
                /// <summary>
                ///  Same as ImplicitStandardConversionExists except that it also looks at
                ///  implicit user defined conversions - needed for overload resolution
@@ -466,7 +474,9 @@ namespace Mono.CSharp {
 
                public static bool ImplicitUserConversionExists (EmitContext ec, Type source, Type target)
                {
-                       return ImplicitUserConversion (ec, new EmptyExpression (source), target, Location.Null) != null;
+                       Expression dummy = ImplicitUserConversion (
+                               ec, new EmptyExpression (source), target, Location.Null);
+                       return dummy != null;
                }
 
                /// <summary>
@@ -779,7 +789,8 @@ namespace Mono.CSharp {
                ///   for explicit and implicit conversion operators.
                /// </summary>
                static public Type FindMostSpecificSource (EmitContext ec, IList list,
-                                                          Expression source, bool apply_explicit_conv_rules)
+                                                          Expression source, bool apply_explicit_conv_rules,
+                                                          Location loc)
                {
                        ArrayList src_types_set = new ArrayList ();
                        
@@ -825,7 +836,8 @@ namespace Mono.CSharp {
                ///  Finds the most specific target Tx according to section 13.4.4
                /// </summary>
                static public Type FindMostSpecificTarget (EmitContext ec, IList list,
-                                                          Type target, bool apply_explicit_conv_rules)
+                                                          Type target, bool apply_explicit_conv_rules,
+                                                          Location loc)
                {
                        ArrayList tgt_types_set = new ArrayList ();
                        
@@ -1001,13 +1013,13 @@ namespace Mono.CSharp {
                                        goto skip;
                                }
                                        
-                               most_specific_source = FindMostSpecificSource (ec, ops, source, look_for_explicit);
+                               most_specific_source = FindMostSpecificSource (ec, ops, source, look_for_explicit, loc);
                                if (most_specific_source == null) {
                                        method = null;
                                        goto skip;
                                }
                                
-                               most_specific_target = FindMostSpecificTarget (ec, ops, target, look_for_explicit);
+                               most_specific_target = FindMostSpecificTarget (ec, ops, target, look_for_explicit, loc);
                                if (most_specific_target == null) {
                                        method = null;
                                        goto skip;
@@ -1121,7 +1133,7 @@ namespace Mono.CSharp {
                        if (expr_type == target_type && expr_type != TypeManager.null_type)
                                return expr;
 
-                       e = ImplicitNumericConversion (ec, expr, target_type);
+                       e = ImplicitNumericConversion (ec, expr, target_type, loc);
                        if (e != null)
                                return e;
 
@@ -1150,8 +1162,6 @@ namespace Mono.CSharp {
                                        if (target_type.IsPointer){
                                                if (TypeManager.GetElementType(target_type) == TypeManager.GetElementType(expr_type))
                                                        return expr;
-
-                                               //return null;
                                        }
                                }
                                
@@ -1254,6 +1264,31 @@ namespace Mono.CSharp {
                        return null;
                }
 
+               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 definitions, one comes from {1} and the other from {2}",
+                                               source.Name, source.Assembly.FullName, target.Assembly.FullName));
+                                                        
+                       }
+                       
+                       // TODO: Missing explicit numeric check
+                       //ExplicitNumericConversion
+
+                       if (ExplicitReferenceConversionExists (source, target)) {
+                               Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
+                                       TypeManager.CSharpName (source), TypeManager.CSharpName (target));
+                               return;
+                       }
+
+                       Report.Error (29, loc, "Cannot implicitly convert type {0} to `{1}'",
+                                     source == TypeManager.anonymous_method_type ?
+                                     "anonymous method" : "`" + TypeManager.CSharpName (source) + "'",
+                                     TypeManager.CSharpName (target));
+               }
+
                /// <summary>
                ///   Attempts to implicitly convert `source' into `target_type', using
                ///   ImplicitConversion.  If there is no implicit conversion, then
@@ -1279,7 +1314,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       source.Error_ValueCannotBeConverted (loc, target_type, false);
+                       source.Error_ValueCannotBeConverted (loc, target_type);
                        return null;
                }
 
@@ -1292,145 +1327,162 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Performs the explicit numeric conversions
                /// </summary>
-               public static Expression ExplicitNumericConversion (Expression expr, Type target_type)
+               static Expression ExplicitNumericConversion (EmitContext ec, Expression expr, Type target_type, Location loc)
                {
                        Type expr_type = expr.Type;
+
+                       //
+                       // If we have an enumeration, extract the underlying type,
+                       // use this during the comparison, but wrap around the original
+                       // target_type
+                       //
                        Type real_target_type = target_type;
 
+                       if (TypeManager.IsEnumType (real_target_type))
+                               real_target_type = TypeManager.EnumToUnderlying (real_target_type);
+
+                       if (ImplicitStandardConversionExists (ec, expr, real_target_type)){
+                               Expression ce = ImplicitConversionStandard (ec, expr, real_target_type, loc);
+
+                               if (real_target_type != target_type)
+                                       return new EmptyCast (ce, target_type);
+                               return ce;
+                       }
+                       
                        if (expr_type == TypeManager.sbyte_type){
                                //
                                // From sbyte to byte, ushort, uint, ulong, char
                                //
                                if (real_target_type == TypeManager.byte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U1);
                                if (real_target_type == TypeManager.ushort_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U2);
                                if (real_target_type == TypeManager.uint32_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U4);
                                if (real_target_type == TypeManager.uint64_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U8);
                                if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_CH);
                        } else if (expr_type == TypeManager.byte_type){
                                //
                                // From byte to sbyte and char
                                //
                                if (real_target_type == TypeManager.sbyte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U1_I1);
                                if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U1_CH);
                        } else if (expr_type == TypeManager.short_type){
                                //
                                // From short to sbyte, byte, ushort, uint, ulong, char
                                //
                                if (real_target_type == TypeManager.sbyte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_I1);
                                if (real_target_type == TypeManager.byte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U1);
                                if (real_target_type == TypeManager.ushort_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U2);
                                if (real_target_type == TypeManager.uint32_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U4);
                                if (real_target_type == TypeManager.uint64_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U8);
                                if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_CH);
                        } else if (expr_type == TypeManager.ushort_type){
                                //
                                // From ushort to sbyte, byte, short, char
                                //
                                if (real_target_type == TypeManager.sbyte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_I1);
                                if (real_target_type == TypeManager.byte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_U1);
                                if (real_target_type == TypeManager.short_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_I2);
                                if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_CH);
                        } else if (expr_type == TypeManager.int32_type){
                                //
                                // From int to sbyte, byte, short, ushort, uint, ulong, char
                                //
                                if (real_target_type == TypeManager.sbyte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I1);
                                if (real_target_type == TypeManager.byte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U1);
                                if (real_target_type == TypeManager.short_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I2);
                                if (real_target_type == TypeManager.ushort_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U2);
                                if (real_target_type == TypeManager.uint32_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U4);
                                if (real_target_type == TypeManager.uint64_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U8);
                                if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I4_CH);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_CH);
                        } else if (expr_type == TypeManager.uint32_type){
                                //
                                // From uint to sbyte, byte, short, ushort, int, char
                                //
                                if (real_target_type == TypeManager.sbyte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I1);
                                if (real_target_type == TypeManager.byte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U1);
                                if (real_target_type == TypeManager.short_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I2);
                                if (real_target_type == TypeManager.ushort_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U2);
                                if (real_target_type == TypeManager.int32_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I4);
                                if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_CH);
                        } else if (expr_type == TypeManager.int64_type){
                                //
                                // From long to sbyte, byte, short, ushort, int, uint, ulong, char
                                //
                                if (real_target_type == TypeManager.sbyte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I1);
                                if (real_target_type == TypeManager.byte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U1);
                                if (real_target_type == TypeManager.short_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I2);
                                if (real_target_type == TypeManager.ushort_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U2);
                                if (real_target_type == TypeManager.int32_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I4);
                                if (real_target_type == TypeManager.uint32_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U4);
                                if (real_target_type == TypeManager.uint64_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U8);
                                if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_CH);
                        } else if (expr_type == TypeManager.uint64_type){
                                //
                                // From ulong to sbyte, byte, short, ushort, int, uint, long, char
                                //
                                if (real_target_type == TypeManager.sbyte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I1);
                                if (real_target_type == TypeManager.byte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U1);
                                if (real_target_type == TypeManager.short_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I2);
                                if (real_target_type == TypeManager.ushort_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U2);
                                if (real_target_type == TypeManager.int32_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I4);
                                if (real_target_type == TypeManager.uint32_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U4);
                                if (real_target_type == TypeManager.int64_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I8);
                                if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_CH);
                        } else if (expr_type == TypeManager.char_type){
                                //
                                // From char to sbyte, byte, short
                                //
                                if (real_target_type == TypeManager.sbyte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_I1);
                                if (real_target_type == TypeManager.byte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_U1);
                                if (real_target_type == TypeManager.short_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_I2);
                        } else if (expr_type == TypeManager.float_type){
                                //
                                // From float to sbyte, byte, short,
@@ -1438,25 +1490,25 @@ namespace Mono.CSharp {
                                // or decimal
                                //
                                if (real_target_type == TypeManager.sbyte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I1);
                                if (real_target_type == TypeManager.byte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U1);
                                if (real_target_type == TypeManager.short_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I2);
                                if (real_target_type == TypeManager.ushort_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U2);
                                if (real_target_type == TypeManager.int32_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I4);
                                if (real_target_type == TypeManager.uint32_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U4);
                                if (real_target_type == TypeManager.int64_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I8);
                                if (real_target_type == TypeManager.uint64_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U8);
                                if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_CH);
                                if (real_target_type == TypeManager.decimal_type)
-                                       return new CastToDecimal (expr, true);
+                                       return new CastToDecimal (ec, expr, true);
                        } else if (expr_type == TypeManager.double_type){
                                //
                                // From double to sbyte, byte, short,
@@ -1464,29 +1516,44 @@ namespace Mono.CSharp {
                                // char, float or decimal
                                //
                                if (real_target_type == TypeManager.sbyte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I1);
                                if (real_target_type == TypeManager.byte_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U1);
                                if (real_target_type == TypeManager.short_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I2);
                                if (real_target_type == TypeManager.ushort_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U2);
                                if (real_target_type == TypeManager.int32_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I4);
                                if (real_target_type == TypeManager.uint32_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U4);
                                if (real_target_type == TypeManager.int64_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I8);
                                if (real_target_type == TypeManager.uint64_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U8);
                                if (real_target_type == TypeManager.char_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_CH);
                                if (real_target_type == TypeManager.float_type)
-                                       return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4);
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4);
                                if (real_target_type == TypeManager.decimal_type)
-                                       return new CastToDecimal (expr, true);
+                                       return new CastToDecimal (ec, expr, true);
                        } else if (expr_type == TypeManager.decimal_type) {
-                               return new CastFromDecimal (expr, target_type).Resolve ();
+                               //
+                               // From decimal to sbyte, byte, short, ushort, int, uint,
+                               // long, ulong, char, double or float
+                               //
+                               if (real_target_type == TypeManager.sbyte_type ||
+                                   real_target_type == TypeManager.byte_type ||
+                                   real_target_type == TypeManager.short_type ||
+                                   real_target_type == TypeManager.ushort_type ||
+                                   real_target_type == TypeManager.int32_type ||
+                                   real_target_type == TypeManager.uint32_type ||
+                                   real_target_type == TypeManager.int64_type ||
+                                   real_target_type == TypeManager.uint64_type ||
+                                   real_target_type == TypeManager.char_type ||
+                                   real_target_type == TypeManager.double_type ||
+                                   real_target_type == TypeManager.float_type)
+                                       return new CastFromDecimal (ec, expr, target_type);
                        }
                        return null;
                }
@@ -1698,29 +1765,33 @@ namespace Mono.CSharp {
                ///   Performs an explicit conversion of the expression `expr' whose
                ///   type is expr.Type to `target_type'.
                /// </summary>
-               static public Expression ExplicitConversionCore (EmitContext ec, Expression expr,
+               static public Expression ExplicitConversion (EmitContext ec, Expression expr,
                                                             Type target_type, Location loc)
                {
                        Type expr_type = expr.Type;
+                       Type original_expr_type = expr_type;
 
                        Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc);
+
                        if (ne != null)
                                return ne;
 
-                       if (TypeManager.IsEnumType (expr_type)) {
-                               if (TypeManager.IsEnumType (target_type))
+                       if (expr_type.IsSubclassOf (TypeManager.enum_type)){
+                               if ((expr_type == TypeManager.enum_type) && target_type.IsValueType &&
+                                          target_type.IsSubclassOf (TypeManager.enum_type))
                                        return new UnboxCast (expr, target_type);
 
+                               //
+                               // Notice that we have kept the expr_type unmodified, which is only
+                               // used later on to 
                                if (expr is EnumConstant)
-                                       return ExplicitConversionCore (ec, ((EnumConstant) expr).Child, target_type, loc);
-
-                               return ExplicitConversionCore (ec, new EmptyCast (expr, TypeManager.EnumToUnderlying (expr_type)), target_type, loc);
+                                       expr = ((EnumConstant) expr).Child;
+                               else
+                                       expr = new EmptyCast (expr, TypeManager.EnumToUnderlying (expr_type));
+                               expr_type = expr.Type;
                        }
 
-                       if (TypeManager.IsEnumType (target_type))
-                               return new EmptyCast (ExplicitConversionCore (ec, expr, TypeManager.EnumToUnderlying (target_type), loc), target_type);
-
-                       ne = ExplicitNumericConversion (expr, target_type);
+                       ne = ExplicitNumericConversion (ec, expr, target_type, loc);
                        if (ne != null)
                                return ne;
 
@@ -1742,58 +1813,72 @@ namespace Mono.CSharp {
                        }
 
                        if (ec.InUnsafe){
-                               ne = ExplicitUnsafe (expr, target_type);
-                               if (ne != null)
-                                       return ne;
-                       }
-
-                       ne = ExplicitUserConversion (ec, expr, target_type, loc);
-                       if (ne != null)
-                               return ne;
+                               if (target_type.IsPointer){
+                                       if (expr_type.IsPointer)
+                                               return new EmptyCast (expr, target_type);
+                                       
+                                       if (expr_type == TypeManager.sbyte_type ||
+                                           expr_type == TypeManager.short_type ||
+                                           expr_type == TypeManager.int32_type ||
+                                           expr_type == TypeManager.int64_type)
+                                               return new OpcodeCast (expr, target_type, OpCodes.Conv_I);
+
+                                       if (expr_type == TypeManager.ushort_type ||
+                                           expr_type == TypeManager.uint32_type ||
+                                           expr_type == TypeManager.uint64_type ||
+                                           expr_type == TypeManager.byte_type)
+                                               return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
+                               }
+                               if (expr_type.IsPointer){
+                                       Expression e = null;
+                                       
+                                       if (target_type == TypeManager.sbyte_type)
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
+                                       else if (target_type == TypeManager.byte_type)
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
+                                       else if (target_type == TypeManager.short_type)
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
+                                       else if (target_type == TypeManager.ushort_type)
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
+                                       else if (target_type == TypeManager.int32_type)
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
+                                       else if (target_type == TypeManager.uint32_type)
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
+                                       else if (target_type == TypeManager.uint64_type)
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                                       else if (target_type == TypeManager.int64_type){
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                                       }
 
-                       return null;
-               }
+                                       if (e != null){
+                                               Expression ci, ce;
 
-               public static Expression ExplicitUnsafe (Expression expr, Type target_type)
-               {
-                       Type expr_type = expr.Type;
+                                               ci = ImplicitConversionStandard (ec, e, target_type, loc);
 
-                       if (target_type.IsPointer){
-                               if (expr_type.IsPointer)
-                                       return new EmptyCast (expr, target_type);
-                                       
-                               if (expr_type == TypeManager.sbyte_type ||
-                                       expr_type == TypeManager.short_type ||
-                                       expr_type == TypeManager.int32_type ||
-                                       expr_type == TypeManager.int64_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I);
-
-                               if (expr_type == TypeManager.ushort_type ||
-                                       expr_type == TypeManager.uint32_type ||
-                                       expr_type == TypeManager.uint64_type ||
-                                       expr_type == TypeManager.byte_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
-                       }
+                                               if (ci != null)
+                                                       return ci;
 
-                       if (expr_type.IsPointer){
-                               if (target_type == TypeManager.sbyte_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
-                               else if (target_type == TypeManager.byte_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
-                               else if (target_type == TypeManager.short_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
-                               else if (target_type == TypeManager.ushort_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
-                               else if (target_type == TypeManager.int32_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
-                               else if (target_type == TypeManager.uint32_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
-                               else if (target_type == TypeManager.uint64_type)
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
-                               else if (target_type == TypeManager.int64_type){
-                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                                               ce = ExplicitNumericConversion (ec, e, target_type, loc);
+                                               if (ce != null)
+                                                       return ce;
+                                               //
+                                               // We should always be able to go from an uint32
+                                               // implicitly or explicitly to the other integral
+                                               // types
+                                               //
+                                               throw new Exception ("Internal compiler error");
+                                       }
                                }
                        }
+
+                       ne = ExplicitUserConversion (ec, expr, target_type, loc);
+                       if (ne != null)
+                               return ne;
+
+                       if (expr is Constant)
+                               expr.Error_ValueCannotBeConverted (loc, target_type);
+                       else
+                               Error_CannotConvertType (loc, original_expr_type, target_type);
                        return null;
                }
 
@@ -1804,10 +1889,11 @@ namespace Mono.CSharp {
                                                                  Type target_type, Location l)
                {
                        Expression ne = ImplicitConversionStandard (ec, expr, target_type, l);
+
                        if (ne != null)
                                return ne;
 
-                       ne = ExplicitNumericConversion (expr, target_type);
+                       ne = ExplicitNumericConversion (ec, expr, target_type, l);
                        if (ne != null)
                                return ne;
 
@@ -1815,22 +1901,7 @@ namespace Mono.CSharp {
                        if (ne != null)
                                return ne;
 
-                       expr.Error_ValueCannotBeConverted (l, target_type, true);
-                       return null;
-               }
-
-               /// <summary>
-               ///   Performs an explicit conversion of the expression `expr' whose
-               ///   type is expr.Type to `target_type'.
-               /// </summary>
-               static public Expression ExplicitConversion (EmitContext ec, Expression expr,
-                       Type target_type, Location loc)
-               {
-                       Expression e = ExplicitConversionCore (ec, expr, target_type, loc);
-                       if (e != null)
-                               return e;
-
-                       expr.Error_ValueCannotBeConverted (loc, target_type, true);
+                       Error_CannotConvertType (l, expr.Type, target_type);
                        return null;
                }
        }
index 03cda0afaa258641f78846742789dbbaf93cc874..f6830971387f2710486429114afa10f93cac0878 100644 (file)
@@ -267,41 +267,9 @@ namespace Mono.CSharp {
                        Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name);
                }
 
-               public virtual void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
+               public virtual void Error_ValueCannotBeConverted (Location loc, Type t)
                {
-                       if (Type.Name == target.Name){
-                               Report.ExtraInformation (loc,
-                                       String.Format (
-                                       "The type {0} has two conflicting definitions, one comes from {1} and the other from {2}",
-                                       Type.Name, Type.Assembly.FullName, target.Assembly.FullName));
-                                                        
-                       }
-
-                       if (expl) {
-                               Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
-                                       GetSignatureForError (), TypeManager.CSharpName (target));
-                               return;
-                       }
-                       
-                       Expression e = (this is EnumConstant) ? ((EnumConstant)this).Child : this;
-                       bool b = Convert.ExplicitNumericConversion (e, target) != null;
-
-                       if (b || Convert.ExplicitReferenceConversionExists (Type, target) || Convert.ExplicitUnsafe (e, target) != null) {
-                               Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
-                                       GetSignatureForError (), TypeManager.CSharpName (target));
-                               return;
-                       }
-
-                       if (Type != TypeManager.string_type && this is Constant) {
-                               Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
-                                       GetSignatureForError (), TypeManager.CSharpName (target));
-                               return;
-                       }
-
-                       Report.Error (29, loc, "Cannot implicitly convert type {0} to `{1}'",
-                               Type == TypeManager.anonymous_method_type ?
-                               "anonymous method" : "`" + GetSignatureForError () + "'",
-                               TypeManager.CSharpName (target));
+                       Convert.Error_CannotImplicitConversion (loc, Type, t);
                }
 
                protected static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name)
@@ -548,6 +516,7 @@ namespace Mono.CSharp {
                ///   Returns a fully formed expression after a MemberLookup
                /// </summary>
                /// 
+               // TODO: This can be heavily cached
                public static Expression ExprClassFromMemberInfo (EmitContext ec, MemberInfo mi, Location loc)
                {
                        if (mi is EventInfo)
@@ -825,12 +794,12 @@ namespace Mono.CSharp {
                        //
                        // If no implicit conversion to bool exists, try using `operator true'
                        //
-                       converted = Expression.GetOperatorTrue (ec, e, loc);
-                       if (converted == null){
-                               e.Error_ValueCannotBeConverted (loc, TypeManager.bool_type, false);
+                       Expression operator_true = Expression.GetOperatorTrue (ec, e, loc);
+                       if (operator_true == null){
+                               Report.Error (31, loc, "Can not convert the expression to a boolean");
                                return null;
                        }
-                       return converted;
+                       return operator_true;
                }
                
                public virtual string ExprClassName
@@ -1047,7 +1016,7 @@ namespace Mono.CSharp {
                                        if (target == null){
                                                target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
                                                if (target == null)
-                                                       source.Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
+                                                       Convert.Error_CannotImplicitConversion (loc, source.Type, TypeManager.int32_type);
                                        }
                                }
                        } 
@@ -1159,30 +1128,36 @@ namespace Mono.CSharp {
 
                MethodInfo conversion_operator;
 
-               public CastToDecimal (Expression child)
-                       : this (child, false)
+               public CastToDecimal (EmitContext ec, Expression child)
+                       : this (ec, child, false)
                {
                }
 
-               public CastToDecimal (Expression child, bool find_explicit)
+               public CastToDecimal (EmitContext ec, Expression child, bool find_explicit)
                        : base (child, TypeManager.decimal_type)
                {
-                       conversion_operator = GetConversionOperator (find_explicit);
+                       conversion_operator = GetConversionOperator (ec, find_explicit);
 
                        if (conversion_operator == null)
-                               throw new InternalErrorException ("Outer conversion routine is out of sync");
+                               Convert.Error_CannotImplicitConversion (loc, child.Type, type);
                }
 
                // Returns the implicit operator that converts from
                // 'child.Type' to System.Decimal.
-               MethodInfo GetConversionOperator (bool find_explicit)
+               MethodInfo GetConversionOperator (EmitContext ec, bool find_explicit)
                {
-                       string operator_name = find_explicit ? "op_Explicit" : "op_Implicit";
+                       string operator_name = "op_Implicit";
+
+                       if (find_explicit)
+                               operator_name = "op_Explicit";
                        
-                       MemberInfo [] mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method,
-                               BindingFlags.Static | BindingFlags.Public, operator_name, null);
+                       MethodGroupExpr opers = Expression.MethodLookup (
+                               ec, type, operator_name, loc) as MethodGroupExpr;
 
-                       foreach (MethodInfo oper in mi) {
+                       if (opers == null)
+                               Convert.Error_CannotImplicitConversion (loc, child.Type, type);
+                       
+                       foreach (MethodInfo oper in opers.Methods) {
                                ParameterData pd = TypeManager.GetParameterData (oper);
 
                                if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
@@ -1199,48 +1174,49 @@ namespace Mono.CSharp {
                        ig.Emit (OpCodes.Call, conversion_operator);
                }
        }
-
        /// <summary>
        ///     This is an explicit numeric cast from a Decimal
        /// </summary>
        public class CastFromDecimal : EmptyCast
        {
-               static IDictionary operators;
-
-               public CastFromDecimal (Expression child, Type return_type)
+               MethodInfo conversion_operator;
+               public CastFromDecimal (EmitContext ec, Expression child, Type return_type)
                        : base (child, return_type)
                {
                        if (child.Type != TypeManager.decimal_type)
                                throw new InternalErrorException (
                                        "The expected type is Decimal, instead it is " + child.Type.FullName);
+
+                       conversion_operator = GetConversionOperator (ec);
+                       if (conversion_operator == null)
+                               Convert.Error_CannotImplicitConversion (loc, child.Type, type);
                }
 
                // Returns the explicit operator that converts from an
                // express of type System.Decimal to 'type'.
-               public Expression Resolve ()
-               {
-                       if (operators == null) {
-                                MemberInfo[] all_oper = TypeManager.MemberLookup (TypeManager.decimal_type,
-                                       TypeManager.decimal_type, TypeManager.decimal_type, MemberTypes.Method,
-                                       BindingFlags.Static | BindingFlags.Public, "op_Explicit", null);
-
-                               operators = new System.Collections.Specialized.HybridDictionary ();
-                               foreach (MethodInfo oper in all_oper) {
-                                       ParameterData pd = TypeManager.GetParameterData (oper);
-                                       if (pd.ParameterType (0) == TypeManager.decimal_type)
-                                               operators.Add (oper.ReturnType, oper);
-                               }
+               MethodInfo GetConversionOperator (EmitContext ec)
+               {                               
+                       MethodGroupExpr opers = Expression.MethodLookup (
+                               ec, child.Type, "op_Explicit", loc) as MethodGroupExpr;
+
+                       if (opers == null)
+                               Convert.Error_CannotImplicitConversion (loc, child.Type, type);
+                       
+                       foreach (MethodInfo oper in opers.Methods) {
+                               ParameterData pd = TypeManager.GetParameterData (oper);
+
+                               if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
+                                       return oper;
                        }
 
-                       return operators.Contains (type) ? this : null;
+                       return null;
                }
-
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
                        child.Emit (ec);
 
-                       ig.Emit (OpCodes.Call, (MethodInfo)operators [type]);
+                       ig.Emit (OpCodes.Call, conversion_operator);
                }
        }
 
@@ -1328,11 +1304,6 @@ namespace Mono.CSharp {
                        Child.Emit (ec);
                }
 
-               public override string GetSignatureForError()
-               {
-                       return TypeManager.CSharpName (Type);
-               }
-
                public override object GetValue ()
                {
                        return Child.GetValue ();
@@ -1348,6 +1319,11 @@ namespace Mono.CSharp {
                        return System.Enum.ToObject (type, Child.GetValue ());
                }
                
+               public override void Error_ValueCannotBeConverted (Location loc, Type t)
+               {
+                       Convert.Error_CannotImplicitConversion (loc, Type, t);
+               }
+
                public override string AsString ()
                {
                        return Child.AsString ();
@@ -1417,7 +1393,7 @@ namespace Mono.CSharp {
                        }
 
                        if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, this, type)){
-                               Error_ValueCannotBeConverted (loc, type, false);
+                               Error_ValueCannotBeConverted (loc, type);
                                return null;
                        }
 
@@ -1505,10 +1481,13 @@ namespace Mono.CSharp {
                }
 
                Mode mode;
+               // TODO: is redundant as can be read in Emit directly
+               bool checked_state;
                
-               public ConvCast (Expression child, Type return_type, Mode m)
+               public ConvCast (EmitContext ec, Expression child, Type return_type, Mode m)
                        : base (child, return_type)
                {
+                       checked_state = ec.CheckState;
                        mode = m;
                }
 
@@ -1531,7 +1510,7 @@ namespace Mono.CSharp {
                        
                        base.Emit (ec);
 
-                       if (ec.CheckState){
+                       if (checked_state){
                                switch (mode){
                                case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
                                case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
index bc518bb92d81d1169cc0e4c597eeced9d1923867..8b5115aaa42a65f4da5fc2e7c50e17d3d3918b7f 100644 (file)
@@ -110,9 +110,8 @@ namespace Mono.CSharp {
 
                        if (ValueExpr != null) {
                                in_transit = true;
-                               Constant c = ValueExpr.ResolveAsConstant (parent_enum.EmitContext, this);
-                               in_transit = false;
 
+                               Constant c = ValueExpr.ResolveAsConstant (parent_enum.EmitContext, this);
                                if (c == null)
                                        return false;
 
@@ -156,17 +155,15 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public bool Emit (EmitContext ec)
+               public void Emit (EmitContext ec)
                {
                        if (OptAttributes != null)
                                OptAttributes.Emit (ec, this); 
 
-                       if (!ResolveValue ())
-                               return false;
+                       if (ResolveValue ())
+                               builder.SetConstant (value.GetValue ());
 
-                       builder.SetConstant (value.GetValue ());
                        Emit ();
-                       return true;
                }
 
                public override string GetSignatureForError()
@@ -313,8 +310,7 @@ namespace Mono.CSharp {
                        }
 
                        foreach (EnumMember em in defined_names.Values) {
-                               if (!em.Emit (ec))
-                                       return;
+                               em.Emit (ec);
                        }
 
                        base.Emit ();
index 3fd8f5bea0bf32397173fc7adb7e3ee7744dda52..c743eadf94d92fa9872cf0212e765a6b9ae56fe5 100644 (file)
@@ -2070,7 +2070,7 @@ namespace Mono.CSharp {
                                                        if (ll >= 0)
                                                                right = new ULongConstant ((ulong) ll, right.Location);
                                                } else {
-                                                       e = Convert.ImplicitNumericConversion (ec, right, l);
+                                                       e = Convert.ImplicitNumericConversion (ec, right, l, loc);
                                                        if (e != null)
                                                                right = e;
                                                }
@@ -2087,7 +2087,7 @@ namespace Mono.CSharp {
                                                if (ll > 0)
                                                        left = new ULongConstant ((ulong) ll, right.Location);
                                        } else {
-                                               e = Convert.ImplicitNumericConversion (ec, left, r);
+                                               e = Convert.ImplicitNumericConversion (ec, left, r, loc);
                                                if (e != null)
                                                        left = e;
                                        }
index 639e5368c81699ea34af5cfb32eab4d7e8c5ceb3..6d3a4ceeac0c7a19c6e910c9e912c7bea0df4326 100644 (file)
@@ -100,7 +100,7 @@ namespace Mono.CSharp {
                        return "null";
                }
 
-               public override void Error_ValueCannotBeConverted (Location loc, Type t, bool expl)
+               public override void Error_ValueCannotBeConverted (Location loc, Type t)
                {
                        Report.Error (37, loc, "Cannot convert null to `{0}' because it is a value type",
                                TypeManager.CSharpName (t));
index 92e4b4fc904f1890a74d01db24c74398f4c398a6..d362d00aeb2cb978fdcdf20eb5f831b6c5b51ba5 100644 (file)
@@ -3423,7 +3423,7 @@ namespace Mono.CSharp {
                                                return false;
 
                                        if (!Convert.ImplicitConversionExists (ec, e, expr_type)) {
-                                               e.Error_ValueCannotBeConverted (e.Location, expr_type, false);
+                                               Convert.Error_CannotImplicitConversion (e.Location, e.Type, expr_type);
                                                return false;
                                        }