X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fconvert.cs;h=09b56abea571f6d9475bc7913a03054cebce792f;hb=8dd8c3d59a76f59d85e0bcb7ca4ca6cb5c382188;hp=fc570be240ac7d798e5c60d629f55a62638fba59;hpb=53497da09c4928635f4d4c4776c8c7e48c6098c3;p=mono.git diff --git a/mcs/mcs/convert.cs b/mcs/mcs/convert.cs index fc570be240a..09b56abea57 100644 --- a/mcs/mcs/convert.cs +++ b/mcs/mcs/convert.cs @@ -97,7 +97,7 @@ namespace Mono.CSharp { // from the null type to any reference-type. if (expr_type == TypeManager.null_type){ if (target_type.IsPointer) - return new EmptyCast (expr, target_type); + return new EmptyCast (NullPointer.Null, target_type); if (!target_type.IsValueType) return new NullCast (expr, target_type); @@ -303,7 +303,7 @@ namespace Mono.CSharp { if (expr_type == TypeManager.sbyte_type){ // - // From sbyte to short, int, long, float, double. + // From sbyte to short, int, long, float, double, decimal // if (real_target_type == TypeManager.int32_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_I4); @@ -315,9 +315,11 @@ namespace Mono.CSharp { return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); 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 (ec, expr); } else if (expr_type == TypeManager.byte_type){ // - // From byte to short, ushort, int, uint, long, ulong, float, double + // From byte to short, ushort, int, uint, long, ulong, float, double, decimal // if ((real_target_type == TypeManager.short_type) || (real_target_type == TypeManager.ushort_type) || @@ -333,9 +335,12 @@ namespace Mono.CSharp { return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); 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 (ec, expr); + } else if (expr_type == TypeManager.short_type){ // - // From short to int, long, float, double + // From short to int, long, float, double, decimal // if (real_target_type == TypeManager.int32_type) return new EmptyCast (expr, target_type); @@ -345,9 +350,12 @@ namespace Mono.CSharp { return new OpcodeCast (expr, target_type, OpCodes.Conv_R8); 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 (ec, expr); + } else if (expr_type == TypeManager.ushort_type){ // - // From ushort to int, uint, long, ulong, float, double + // From ushort to int, uint, long, ulong, float, double, decimal // if (real_target_type == TypeManager.uint32_type) return new EmptyCast (expr, target_type); @@ -362,9 +370,11 @@ namespace Mono.CSharp { return new OpcodeCast (expr, target_type, OpCodes.Conv_R8); 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 (ec, expr); } else if (expr_type == TypeManager.int32_type){ // - // From int to long, float, double + // From int to long, float, double, decimal // if (real_target_type == TypeManager.int64_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_I8); @@ -372,9 +382,11 @@ namespace Mono.CSharp { return new OpcodeCast (expr, target_type, OpCodes.Conv_R8); 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 (ec, expr); } else if (expr_type == TypeManager.uint32_type){ // - // From uint to long, ulong, float, double + // From uint to long, ulong, float, double, decimal // if (real_target_type == TypeManager.int64_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_U8); @@ -386,6 +398,8 @@ namespace Mono.CSharp { if (real_target_type == TypeManager.float_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4); + if (real_target_type == TypeManager.decimal_type) + return new CastToDecimal (ec, expr); } else if (expr_type == TypeManager.int64_type){ // // From long/ulong to float, double @@ -393,7 +407,9 @@ namespace Mono.CSharp { if (real_target_type == TypeManager.double_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_R8); if (real_target_type == TypeManager.float_type) - return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + if (real_target_type == TypeManager.decimal_type) + return new CastToDecimal (ec, expr); } else if (expr_type == TypeManager.uint64_type){ // // From ulong to float, double @@ -403,10 +419,12 @@ namespace Mono.CSharp { OpCodes.Conv_R8); if (real_target_type == TypeManager.float_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un, - OpCodes.Conv_R4); + OpCodes.Conv_R4); + if (real_target_type == TypeManager.decimal_type) + return new CastToDecimal (ec, expr); } else if (expr_type == TypeManager.char_type){ // - // From char to ushort, int, uint, long, ulong, float, double + // From char to ushort, int, uint, long, ulong, float, double, decimal // if ((real_target_type == TypeManager.ushort_type) || (real_target_type == TypeManager.int32_type) || @@ -420,6 +438,8 @@ namespace Mono.CSharp { return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); 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 (ec, expr); } else if (expr_type == TypeManager.float_type){ // // float to double @@ -477,7 +497,7 @@ namespace Mono.CSharp { if (expr_type == TypeManager.sbyte_type){ // - // From sbyte to short, int, long, float, double. + // From sbyte to short, int, long, float, double, decimal // if ((target_type == TypeManager.int32_type) || (target_type == TypeManager.int64_type) || @@ -489,7 +509,7 @@ namespace Mono.CSharp { } else if (expr_type == TypeManager.byte_type){ // - // From byte to short, ushort, int, uint, long, ulong, float, double + // From byte to short, ushort, int, uint, long, ulong, float, double, decimal // if ((target_type == TypeManager.short_type) || (target_type == TypeManager.ushort_type) || @@ -504,7 +524,7 @@ namespace Mono.CSharp { } else if (expr_type == TypeManager.short_type){ // - // From short to int, long, float, double + // From short to int, long, double, float, decimal // if ((target_type == TypeManager.int32_type) || (target_type == TypeManager.int64_type) || @@ -515,7 +535,7 @@ namespace Mono.CSharp { } else if (expr_type == TypeManager.ushort_type){ // - // From ushort to int, uint, long, ulong, float, double + // From ushort to int, uint, long, ulong, double, float, decimal // if ((target_type == TypeManager.uint32_type) || (target_type == TypeManager.uint64_type) || @@ -528,7 +548,7 @@ namespace Mono.CSharp { } else if (expr_type == TypeManager.int32_type){ // - // From int to long, float, double + // From int to long, double, float, decimal // if ((target_type == TypeManager.int64_type) || (target_type == TypeManager.double_type) || @@ -538,7 +558,7 @@ namespace Mono.CSharp { } else if (expr_type == TypeManager.uint32_type){ // - // From uint to long, ulong, float, double + // From uint to long, ulong, double, float, decimal // if ((target_type == TypeManager.int64_type) || (target_type == TypeManager.uint64_type) || @@ -550,7 +570,7 @@ namespace Mono.CSharp { } else if ((expr_type == TypeManager.uint64_type) || (expr_type == TypeManager.int64_type)) { // - // From long/ulong to float, double + // From long/ulong to double, float, decimal // if ((target_type == TypeManager.double_type) || (target_type == TypeManager.float_type) || @@ -559,7 +579,7 @@ namespace Mono.CSharp { } else if (expr_type == TypeManager.char_type){ // - // From char to ushort, int, uint, long, ulong, float, double + // From char to ushort, int, uint, ulong, long, float, double, decimal // if ((target_type == TypeManager.ushort_type) || (target_type == TypeManager.int32_type) || @@ -587,7 +607,8 @@ namespace Mono.CSharp { // This should not happen frequently, so we can create an object // to test compatibility // - Expression c = ImplicitDelegateCreation.Create (ec, mg, target_type, Location.Null); + Expression c = ImplicitDelegateCreation.Create ( + ec, mg, target_type, true, Location.Null); return c != null; } } @@ -675,13 +696,6 @@ namespace Mono.CSharp { return false; } - // - // Used internally by FindMostEncompassedType, this is used - // to avoid creating lots of objects in the tight loop inside - // FindMostEncompassedType - // - static EmptyExpression priv_fmet_param; - /// /// Finds "most encompassed type" according to the spec (13.4.2) /// amongst the methods in the MethodGroupExpr @@ -690,31 +704,40 @@ namespace Mono.CSharp { { Type best = null; - if (priv_fmet_param == null) - priv_fmet_param = new EmptyExpression (); + if (types.Count == 0) + return null; + + if (types.Count == 1) + return (Type) types [0]; - foreach (Type t in types){ - priv_fmet_param.SetType (t); - + EmptyExpression expr = EmptyExpression.Grab (); + + foreach (Type t in types) { if (best == null) { best = t; continue; } - - if (ImplicitStandardConversionExists (ec, priv_fmet_param, best)) + + expr.SetType (t); + if (ImplicitStandardConversionExists (ec, expr, best)) best = t; } + expr.SetType (best); + foreach (Type t in types) { + if (best == t) + continue; + if (!ImplicitStandardConversionExists (ec, expr, t)) { + best = null; + break; + } + } + + EmptyExpression.Release (expr); + return best; } - - // - // Used internally by FindMostEncompassingType, this is used - // to avoid creating lots of objects in the tight loop inside - // FindMostEncompassingType - // - static EmptyExpression priv_fmee_ret; - + /// /// Finds "most encompassing type" according to the spec (13.4.2) /// amongst the types in the given set @@ -723,77 +746,63 @@ namespace Mono.CSharp { { Type best = null; - if (priv_fmee_ret == null) - priv_fmee_ret = new EmptyExpression (); + if (types.Count == 0) + return null; + + if (types.Count == 1) + return (Type) types [0]; - foreach (Type t in types){ - priv_fmee_ret.SetType (best); + EmptyExpression expr = EmptyExpression.Grab (); + foreach (Type t in types) { if (best == null) { best = t; continue; } - if (ImplicitStandardConversionExists (ec, priv_fmee_ret, t)) + expr.SetType (best); + if (ImplicitStandardConversionExists (ec, expr, t)) best = t; } - + + foreach (Type t in types) { + if (best == t) + continue; + expr.SetType (t); + if (!ImplicitStandardConversionExists (ec, expr, best)) { + best = null; + break; + } + } + + EmptyExpression.Release (expr); + return best; } - // - // Used to avoid creating too many objects - // - static EmptyExpression priv_fms_expr; - /// /// Finds the most specific source Sx according to the rules of the spec (13.4.4) /// by making use of FindMostEncomp* methods. Applies the correct rules separately /// for explicit and implicit conversion operators. /// - static public Type FindMostSpecificSource (EmitContext ec, MethodGroupExpr me, + static public Type FindMostSpecificSource (EmitContext ec, IList list, Expression source, bool apply_explicit_conv_rules, Location loc) { ArrayList src_types_set = new ArrayList (); - if (priv_fms_expr == null) - priv_fms_expr = new EmptyExpression (); - // // If any operator converts from S then Sx = S // Type source_type = source.Type; - foreach (MethodBase mb in me.Methods){ + foreach (MethodBase mb in list){ ParameterData pd = TypeManager.GetParameterData (mb); Type param_type = pd.ParameterType (0); if (param_type == source_type) return param_type; - if (apply_explicit_conv_rules) { - // - // From the spec : - // Find the set of applicable user-defined conversion operators, U. This set - // consists of the - // user-defined implicit or explicit conversion operators declared by - // the classes or structs in D that convert from a type encompassing - // or encompassed by S to a type encompassing or encompassed by T - // - priv_fms_expr.SetType (param_type); - if (ImplicitStandardConversionExists (ec, priv_fms_expr, source_type)) - src_types_set.Add (param_type); - else { - if (ImplicitStandardConversionExists (ec, source, param_type)) - src_types_set.Add (param_type); - } - } else { - // - // Only if S is encompassed by param_type - // - if (ImplicitStandardConversionExists (ec, source, param_type)) - src_types_set.Add (param_type); - } + src_types_set.Add (param_type); } // @@ -819,59 +828,25 @@ namespace Mono.CSharp { else return FindMostEncompassedType (ec, src_types_set); } - - // - // Useful in avoiding proliferation of objects - // - static EmptyExpression priv_fmt_expr; /// /// Finds the most specific target Tx according to section 13.4.4 /// - static public Type FindMostSpecificTarget (EmitContext ec, MethodGroupExpr me, + static public Type FindMostSpecificTarget (EmitContext ec, IList list, Type target, bool apply_explicit_conv_rules, Location loc) { ArrayList tgt_types_set = new ArrayList (); - if (priv_fmt_expr == null) - priv_fmt_expr = new EmptyExpression (); - // // If any operator converts to T then Tx = T // - foreach (MethodInfo mi in me.Methods){ + foreach (MethodInfo mi in list){ Type ret_type = mi.ReturnType; - if (ret_type == target) return ret_type; - if (apply_explicit_conv_rules) { - // - // From the spec : - // Find the set of applicable user-defined conversion operators, U. - // - // This set consists of the - // user-defined implicit or explicit conversion operators declared by - // the classes or structs in D that convert from a type encompassing - // or encompassed by S to a type encompassing or encompassed by T - // - priv_fms_expr.SetType (ret_type); - if (ImplicitStandardConversionExists (ec, priv_fms_expr, target)) - tgt_types_set.Add (ret_type); - else { - priv_fms_expr.SetType (target); - if (ImplicitStandardConversionExists (ec, priv_fms_expr, ret_type)) - tgt_types_set.Add (ret_type); - } - } else { - // - // Only if T is encompassed by param_type - // - priv_fms_expr.SetType (ret_type); - if (ImplicitStandardConversionExists (ec, priv_fms_expr, target)) - tgt_types_set.Add (ret_type); - } + tgt_types_set.Add (ret_type); } // @@ -880,13 +855,17 @@ namespace Mono.CSharp { if (apply_explicit_conv_rules) { ArrayList candidate_set = new ArrayList (); + EmptyExpression expr = EmptyExpression.Grab (); + foreach (Type ret_type in tgt_types_set){ - priv_fmt_expr.SetType (ret_type); + expr.SetType (ret_type); - if (ImplicitStandardConversionExists (ec, priv_fmt_expr, target)) + if (ImplicitStandardConversionExists (ec, expr, target)) candidate_set.Add (ret_type); } + EmptyExpression.Release (expr); + if (candidate_set.Count != 0) return FindMostEncompassingType (ec, candidate_set); } @@ -918,82 +897,90 @@ namespace Mono.CSharp { return UserDefinedConversion (ec, source, target, loc, true); } - static DoubleHash explicit_conv = new DoubleHash (100); - static DoubleHash implicit_conv = new DoubleHash (100); + static void AddConversionOperators (EmitContext ec, ArrayList list, + Expression source, Type target_type, + bool look_for_explicit, + MethodGroupExpr mg) + { + if (mg == null) + return; + + Type source_type = source.Type; + EmptyExpression expr = EmptyExpression.Grab (); + foreach (MethodInfo m in mg.Methods) { + ParameterData pd = TypeManager.GetParameterData (m); + Type return_type = m.ReturnType; + Type arg_type = pd.ParameterType (0); + + if (source_type != arg_type) { + if (!ImplicitStandardConversionExists (ec, source, arg_type)) { + if (!look_for_explicit) + continue; + expr.SetType (arg_type); + if (!ImplicitStandardConversionExists (ec, expr, source_type)) + continue; + } + } + + if (target_type != return_type) { + expr.SetType (return_type); + if (!ImplicitStandardConversionExists (ec, expr, target_type)) { + if (!look_for_explicit) + continue; + expr.SetType (target_type); + if (!ImplicitStandardConversionExists (ec, expr, return_type)) + continue; + } + } + + list.Add (m); + } + + EmptyExpression.Release (expr); + } + /// - /// Computes the MethodGroup for the user-defined conversion + /// Computes the list of the user-defined conversion /// operators from source_type to target_type. `look_for_explicit' /// controls whether we should also include the list of explicit /// operators /// - static MethodGroupExpr GetConversionOperators (EmitContext ec, - Type source_type, Type target_type, - Location loc, bool look_for_explicit) + static IList GetConversionOperators (EmitContext ec, + Expression source, Type target_type, + Location loc, bool look_for_explicit) { - Expression mg1 = null, mg2 = null; - Expression mg5 = null, mg6 = null, mg7 = null, mg8 = null; - string op_name; - - op_name = "op_Implicit"; + ArrayList ret = new ArrayList (4); - MethodGroupExpr union3; - object r; - if ((look_for_explicit ? explicit_conv : implicit_conv).Lookup (source_type, target_type, out r)) - return (MethodGroupExpr) r; - - mg1 = Expression.MethodLookup (ec, source_type, op_name, loc); - if (source_type.BaseType != null) - mg2 = Expression.MethodLookup (ec, source_type.BaseType, op_name, loc); - - if (mg1 == null) - union3 = (MethodGroupExpr) mg2; - else if (mg2 == null) - union3 = (MethodGroupExpr) mg1; - else - union3 = Invocation.MakeUnionSet (mg1, mg2, loc); + Type source_type = source.Type; - mg1 = Expression.MethodLookup (ec, target_type, op_name, loc); - if (mg1 != null){ - if (union3 != null) - union3 = Invocation.MakeUnionSet (union3, mg1, loc); - else - union3 = (MethodGroupExpr) mg1; + if (source_type != TypeManager.decimal_type) { + AddConversionOperators (ec, ret, source, target_type, look_for_explicit, + Expression.MethodLookup ( + ec, source_type, "op_Implicit", loc) as MethodGroupExpr); + if (look_for_explicit) { + AddConversionOperators (ec, ret, source, target_type, look_for_explicit, + Expression.MethodLookup ( + ec, source_type, "op_Explicit", loc) as MethodGroupExpr); + } } - if (target_type.BaseType != null) - mg1 = Expression.MethodLookup (ec, target_type.BaseType, op_name, loc); - - if (mg1 != null){ - if (union3 != null) - union3 = Invocation.MakeUnionSet (union3, mg1, loc); - else - union3 = (MethodGroupExpr) mg1; + if (target_type != TypeManager.decimal_type) { + AddConversionOperators (ec, ret, source, target_type, look_for_explicit, + Expression.MethodLookup ( + ec, target_type, "op_Implicit", loc) as MethodGroupExpr); + if (look_for_explicit) { + AddConversionOperators (ec, ret, source, target_type, look_for_explicit, + Expression.MethodLookup ( + ec, target_type, "op_Explicit", loc) as MethodGroupExpr); + } } - MethodGroupExpr union4 = null; - - if (look_for_explicit) { - op_name = "op_Explicit"; - - mg5 = Expression.MemberLookup (ec, source_type, op_name, loc); - if (source_type.BaseType != null) - mg6 = Expression.MethodLookup (ec, source_type.BaseType, op_name, loc); - - mg7 = Expression.MemberLookup (ec, target_type, op_name, loc); - if (target_type.BaseType != null) - mg8 = Expression.MethodLookup (ec, target_type.BaseType, op_name, loc); - - MethodGroupExpr union5 = Invocation.MakeUnionSet (mg5, mg6, loc); - MethodGroupExpr union6 = Invocation.MakeUnionSet (mg7, mg8, loc); - - union4 = Invocation.MakeUnionSet (union5, union6, loc); - } - - MethodGroupExpr ret = Invocation.MakeUnionSet (union3, union4, loc); - (look_for_explicit ? explicit_conv : implicit_conv).Insert (source_type, target_type, ret); return ret; } - + + static DoubleHash explicit_conv = new DoubleHash (100); + static DoubleHash implicit_conv = new DoubleHash (100); + /// /// User-defined conversions /// @@ -1001,42 +988,62 @@ namespace Mono.CSharp { Type target, Location loc, bool look_for_explicit) { - MethodGroupExpr union; Type source_type = source.Type; - MethodBase method = null; - - union = GetConversionOperators (ec, source_type, target, loc, look_for_explicit); - if (union == null) - return null; - - Type most_specific_source, most_specific_target; - - most_specific_source = FindMostSpecificSource (ec, union, source, look_for_explicit, loc); - if (most_specific_source == null) - return null; - - most_specific_target = FindMostSpecificTarget (ec, union, target, look_for_explicit, loc); - if (most_specific_target == null) - return null; - - int count = 0; - - - foreach (MethodBase mb in union.Methods){ - ParameterData pd = TypeManager.GetParameterData (mb); - MethodInfo mi = (MethodInfo) mb; + MethodInfo method = null; + Type most_specific_source = null; + Type most_specific_target = null; + + object o; + DoubleHash hash = look_for_explicit ? explicit_conv : implicit_conv; + + if (!(source is Constant) && hash.Lookup (source_type, target, out o)) { + method = (MethodInfo) o; + if (method != null) { + ParameterData pd = TypeManager.GetParameterData (method); + most_specific_source = pd.ParameterType (0); + most_specific_target = method.ReturnType; + } + } else { + IList ops = GetConversionOperators (ec, source, target, loc, look_for_explicit); + if (ops == null || ops.Count == 0) { + method = null; + goto skip; + } + + most_specific_source = FindMostSpecificSource (ec, ops, source, look_for_explicit, loc); + if (most_specific_source == null) { + method = null; + goto skip; + } - if (pd.ParameterType (0) == most_specific_source && - mi.ReturnType == most_specific_target) { - method = mb; - count++; + most_specific_target = FindMostSpecificTarget (ec, ops, target, look_for_explicit, loc); + if (most_specific_target == null) { + method = null; + goto skip; } + + int count = 0; + + foreach (MethodInfo m in ops) { + ParameterData pd = TypeManager.GetParameterData (m); + + if (pd.ParameterType (0) == most_specific_source && + m.ReturnType == most_specific_target) { + method = m; + count++; + } + } + if (count > 1) + method = null; + + skip: + if (!(source is Constant)) + hash.Insert (source_type, target, method); } - - if (method == null || count > 1) + + if (method == null) return null; - // // This will do the conversion to the best match that we // found. Now we need to perform an implict standard conversion @@ -1052,7 +1059,7 @@ namespace Mono.CSharp { return null; Expression e; - e = new UserCast ((MethodInfo) method, source, loc); + e = new UserCast (method, source, loc); if (e.Type != target){ if (!look_for_explicit) e = ImplicitConversionStandard (ec, e, target, loc); @@ -1115,7 +1122,8 @@ namespace Mono.CSharp { if (RootContext.Version != LanguageVersion.ISO_1){ MethodGroupExpr mg = expr as MethodGroupExpr; if (mg != null) - return ImplicitDelegateCreation.Create (ec, mg, target_type, loc); + return ImplicitDelegateCreation.Create ( + ec, mg, target_type, false, loc); } } @@ -1156,7 +1164,7 @@ namespace Mono.CSharp { if (target_type.IsPointer) { if (expr_type == TypeManager.null_type) - return new EmptyCast (expr, target_type); + return new EmptyCast (NullPointer.Null, target_type); if (expr_type == TypeManager.void_ptr_type) return new EmptyCast (expr, target_type); @@ -1494,9 +1502,11 @@ namespace Mono.CSharp { return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U8); if (real_target_type == TypeManager.char_type) return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_CH); + if (real_target_type == TypeManager.decimal_type) + return new CastToDecimal (ec, expr, true); } else if (expr_type == TypeManager.double_type){ // - // From double to byte, byte, short, + // From double to sbyte, byte, short, // ushort, int, uint, long, ulong, // char, float or decimal // @@ -1520,10 +1530,26 @@ namespace Mono.CSharp { return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_CH); if (real_target_type == TypeManager.float_type) return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4); - } - - // decimal is taken care of by the op_Explicit methods. - + if (real_target_type == TypeManager.decimal_type) + return new CastToDecimal (ec, expr, true); + } else if (expr_type == TypeManager.decimal_type) { + // + // 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; } @@ -1788,7 +1814,6 @@ namespace Mono.CSharp { return ne; } - skip_explicit: if (ec.InUnsafe){ if (target_type.IsPointer){ if (expr_type.IsPointer) @@ -1857,7 +1882,7 @@ namespace Mono.CSharp { TypeManager.CSharpName (target_type) + "'"); return null; } - + Error_CannotConvertType (loc, original_expr_type, target_type); return null; }