2 // conversion.cs: various routines for implementing conversions.
5 // Miguel de Icaza (miguel@ximian.com)
6 // Ravi Pratap (ravi@ximian.com)
8 // (C) 2001, 2002, 2003 Ximian, Inc.
11 namespace Mono.CSharp {
13 using System.Collections;
14 using System.Diagnostics;
15 using System.Reflection;
16 using System.Reflection.Emit;
19 // A container class for all the conversion operations
21 public class Convert {
22 static public void Error_CannotConvertType (Location loc, Type source, Type target)
24 Report.Error (30, loc, "Cannot convert type '" +
25 TypeManager.CSharpName (source) + "' to '" +
26 TypeManager.CSharpName (target) + "'");
29 static EmptyExpression MyEmptyExpr;
30 static public Expression ImplicitReferenceConversion (Expression expr, Type target_type)
32 Type expr_type = expr.Type;
34 if (expr_type == null && expr.eclass == ExprClass.MethodGroup){
35 // if we are a method group, emit a warning
40 if (expr_type == TypeManager.void_type)
44 // notice that it is possible to write "ValueType v = 1", the ValueType here
45 // is an abstract class, and not really a value type, so we apply the same rules.
47 if (target_type == TypeManager.object_type) {
49 // A pointer type cannot be converted to object
51 if (expr_type.IsPointer)
54 if (TypeManager.IsValueType (expr_type))
55 return new BoxedCast (expr);
56 if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type)
57 return new EmptyCast (expr, target_type);
58 } else if (target_type == TypeManager.value_type) {
59 if (TypeManager.IsValueType (expr_type))
60 return new BoxedCast (expr);
61 if (expr is NullLiteral)
62 return new NullCast (expr, target_type);
63 } else if (TypeManager.IsSubclassOf (expr_type, target_type)) {
65 // Special case: enumeration to System.Enum.
66 // System.Enum is not a value type, it is a class, so we need
67 // a boxing conversion
69 if (expr_type.IsEnum || expr_type.IsGenericParameter)
70 return new BoxedCast (expr);
72 return new EmptyCast (expr, target_type);
75 // This code is kind of mirrored inside ImplicitStandardConversionExists
76 // with the small distinction that we only probe there
78 // Always ensure that the code here and there is in sync
80 // from the null type to any reference-type.
81 if (expr is NullLiteral){
82 if (target_type.IsPointer)
83 return NullPointer.Null;
85 if (!target_type.IsValueType)
86 return new NullCast (expr, target_type);
89 // from any class-type S to any interface-type T.
90 if (target_type.IsInterface) {
91 if (TypeManager.ImplementsInterface (expr_type, target_type)){
92 if (expr_type.IsGenericParameter)
93 return new BoxedCast (expr, target_type);
94 else if (expr_type.IsClass)
95 return new EmptyCast (expr, target_type);
96 else if (TypeManager.IsValueType (expr_type) ||
97 TypeManager.IsEnumType (expr_type))
98 return new BoxedCast (expr, target_type);
100 return new EmptyCast (expr, target_type);
104 // from any interface type S to interface-type T.
105 if (expr_type.IsInterface && target_type.IsInterface) {
106 if (TypeManager.ImplementsInterface (expr_type, target_type))
107 return new EmptyCast (expr, target_type);
112 // from an array-type S to an array-type of type T
113 if (expr_type.IsArray && target_type.IsArray) {
114 if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
116 Type expr_element_type = TypeManager.GetElementType (expr_type);
118 if (MyEmptyExpr == null)
119 MyEmptyExpr = new EmptyExpression ();
121 MyEmptyExpr.SetType (expr_element_type);
122 Type target_element_type = TypeManager.GetElementType (target_type);
124 if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
125 if (ImplicitStandardConversionExists (MyEmptyExpr,
126 target_element_type))
127 return new EmptyCast (expr, target_type);
132 // from an array-type to System.Array
133 if (expr_type.IsArray && target_type == TypeManager.array_type)
134 return new EmptyCast (expr, target_type);
136 // from any delegate type to System.Delegate
137 if ((expr_type == TypeManager.delegate_type ||
138 TypeManager.IsDelegateType (expr_type)) &&
139 target_type == TypeManager.delegate_type)
140 return new EmptyCast (expr, target_type);
142 // from any array-type or delegate type into System.ICloneable.
143 if (expr_type.IsArray ||
144 expr_type == TypeManager.delegate_type ||
145 TypeManager.IsDelegateType (expr_type))
146 if (target_type == TypeManager.icloneable_type)
147 return new EmptyCast (expr, target_type);
149 // from a generic type definition to a generic instance.
150 if (TypeManager.IsEqualGenericType (expr_type, target_type))
151 return new EmptyCast (expr, target_type);
161 // Tests whether an implicit reference conversion exists between expr_type
164 public static bool ImplicitReferenceConversionExists (Expression expr, Type target_type)
166 Type expr_type = expr.Type;
169 // This is the boxed case.
171 if (target_type == TypeManager.object_type) {
172 if (expr_type.IsClass || TypeManager.IsValueType (expr_type) ||
173 expr_type.IsInterface || expr_type == TypeManager.enum_type)
175 } else if (TypeManager.IsSubclassOf (expr_type, target_type))
178 // Please remember that all code below actually comes
179 // from ImplicitReferenceConversion so make sure code remains in sync
181 // from any class-type S to any interface-type T.
182 if (target_type.IsInterface) {
183 if (TypeManager.ImplementsInterface (expr_type, target_type))
187 // from any interface type S to interface-type T.
188 if (expr_type.IsInterface && target_type.IsInterface)
189 if (TypeManager.ImplementsInterface (expr_type, target_type))
192 // from an array-type S to an array-type of type T
193 if (expr_type.IsArray && target_type.IsArray) {
194 if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
196 Type expr_element_type = expr_type.GetElementType ();
198 if (MyEmptyExpr == null)
199 MyEmptyExpr = new EmptyExpression ();
201 MyEmptyExpr.SetType (expr_element_type);
202 Type target_element_type = TypeManager.GetElementType (target_type);
204 if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
205 if (ImplicitStandardConversionExists (MyEmptyExpr,
206 target_element_type))
211 // from an array-type to System.Array
212 if (expr_type.IsArray && (target_type == TypeManager.array_type))
215 // from any delegate type to System.Delegate
216 if ((expr_type == TypeManager.delegate_type ||
217 TypeManager.IsDelegateType (expr_type)) &&
218 target_type == TypeManager.delegate_type)
219 if (target_type.IsAssignableFrom (expr_type))
222 // from any array-type or delegate type into System.ICloneable.
223 if (expr_type.IsArray ||
224 expr_type == TypeManager.delegate_type ||
225 TypeManager.IsDelegateType (expr_type))
226 if (target_type == TypeManager.icloneable_type)
229 // from the null type to any reference-type.
230 if (expr is NullLiteral && !target_type.IsValueType &&
231 !TypeManager.IsEnumType (target_type))
234 // from a generic type definition to a generic instance.
235 if (TypeManager.IsEqualGenericType (expr_type, target_type))
242 /// Implicit Numeric Conversions.
244 /// expr is the expression to convert, returns a new expression of type
245 /// target_type or null if an implicit conversion is not possible.
247 static public Expression ImplicitNumericConversion (EmitContext ec, Expression expr,
248 Type target_type, Location loc)
250 Type expr_type = expr.Type;
253 // Attempt to do the implicit constant expression conversions
255 if (expr is Constant){
257 if (expr is IntConstant){
260 e = TryImplicitIntConversion (target_type, (IntConstant) expr);
264 } else if (expr is LongConstant && target_type == TypeManager.uint64_type){
266 // Try the implicit constant expression conversion
267 // from long to ulong, instead of a nice routine,
270 long v = ((LongConstant) expr).Value;
272 return new ULongConstant ((ulong) v);
276 Type real_target_type = target_type;
278 if (expr_type == TypeManager.sbyte_type){
280 // From sbyte to short, int, long, float, double.
282 if (real_target_type == TypeManager.int32_type)
283 return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
284 if (real_target_type == TypeManager.int64_type)
285 return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
286 if (real_target_type == TypeManager.double_type)
287 return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
288 if (real_target_type == TypeManager.float_type)
289 return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
290 if (real_target_type == TypeManager.short_type)
291 return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
292 } else if (expr_type == TypeManager.byte_type){
294 // From byte to short, ushort, int, uint, long, ulong, float, double
296 if ((real_target_type == TypeManager.short_type) ||
297 (real_target_type == TypeManager.ushort_type) ||
298 (real_target_type == TypeManager.int32_type) ||
299 (real_target_type == TypeManager.uint32_type))
300 return new EmptyCast (expr, target_type);
302 if (real_target_type == TypeManager.uint64_type)
303 return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
304 if (real_target_type == TypeManager.int64_type)
305 return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
306 if (real_target_type == TypeManager.float_type)
307 return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
308 if (real_target_type == TypeManager.double_type)
309 return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
310 } else if (expr_type == TypeManager.short_type){
312 // From short to int, long, float, double
314 if (real_target_type == TypeManager.int32_type)
315 return new EmptyCast (expr, target_type);
316 if (real_target_type == TypeManager.int64_type)
317 return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
318 if (real_target_type == TypeManager.double_type)
319 return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
320 if (real_target_type == TypeManager.float_type)
321 return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
322 } else if (expr_type == TypeManager.ushort_type){
324 // From ushort to int, uint, long, ulong, float, double
326 if (real_target_type == TypeManager.uint32_type)
327 return new EmptyCast (expr, target_type);
329 if (real_target_type == TypeManager.uint64_type)
330 return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
331 if (real_target_type == TypeManager.int32_type)
332 return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
333 if (real_target_type == TypeManager.int64_type)
334 return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
335 if (real_target_type == TypeManager.double_type)
336 return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
337 if (real_target_type == TypeManager.float_type)
338 return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
339 } else if (expr_type == TypeManager.int32_type){
341 // From int to long, float, double
343 if (real_target_type == TypeManager.int64_type)
344 return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
345 if (real_target_type == TypeManager.double_type)
346 return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
347 if (real_target_type == TypeManager.float_type)
348 return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
349 } else if (expr_type == TypeManager.uint32_type){
351 // From uint to long, ulong, float, double
353 if (real_target_type == TypeManager.int64_type)
354 return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
355 if (real_target_type == TypeManager.uint64_type)
356 return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
357 if (real_target_type == TypeManager.double_type)
358 return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
360 if (real_target_type == TypeManager.float_type)
361 return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
363 } else if (expr_type == TypeManager.int64_type){
365 // From long/ulong to float, double
367 if (real_target_type == TypeManager.double_type)
368 return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
369 if (real_target_type == TypeManager.float_type)
370 return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
371 } else if (expr_type == TypeManager.uint64_type){
373 // From ulong to float, double
375 if (real_target_type == TypeManager.double_type)
376 return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
378 if (real_target_type == TypeManager.float_type)
379 return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
381 } else if (expr_type == TypeManager.char_type){
383 // From char to ushort, int, uint, long, ulong, float, double
385 if ((real_target_type == TypeManager.ushort_type) ||
386 (real_target_type == TypeManager.int32_type) ||
387 (real_target_type == TypeManager.uint32_type))
388 return new EmptyCast (expr, target_type);
389 if (real_target_type == TypeManager.uint64_type)
390 return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
391 if (real_target_type == TypeManager.int64_type)
392 return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
393 if (real_target_type == TypeManager.float_type)
394 return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
395 if (real_target_type == TypeManager.double_type)
396 return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
397 } else if (expr_type == TypeManager.float_type){
401 if (real_target_type == TypeManager.double_type)
402 return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
410 /// Same as ImplicitStandardConversionExists except that it also looks at
411 /// implicit user defined conversions - needed for overload resolution
413 public static bool ImplicitConversionExists (EmitContext ec, Expression expr, Type target_type)
415 if (ImplicitStandardConversionExists (expr, target_type))
418 Expression dummy = ImplicitUserConversion (ec, expr, target_type, Location.Null);
426 public static bool ImplicitUserConversionExists (EmitContext ec, Type source, Type target)
428 Expression dummy = ImplicitUserConversion (
429 ec, new EmptyExpression (source), target, Location.Null);
430 return dummy != null;
434 /// Determines if a standard implicit conversion exists from
435 /// expr_type to target_type
437 public static bool ImplicitStandardConversionExists (Expression expr, Type target_type)
439 Type expr_type = expr.Type;
441 if (expr_type == TypeManager.void_type)
444 //Console.WriteLine ("Expr is {0}", expr);
445 //Console.WriteLine ("{0} -> {1} ?", expr_type, target_type);
446 if (expr_type.Equals (target_type))
449 // First numeric conversions
451 if (expr_type == TypeManager.sbyte_type){
453 // From sbyte to short, int, long, float, double.
455 if ((target_type == TypeManager.int32_type) ||
456 (target_type == TypeManager.int64_type) ||
457 (target_type == TypeManager.double_type) ||
458 (target_type == TypeManager.float_type) ||
459 (target_type == TypeManager.short_type) ||
460 (target_type == TypeManager.decimal_type))
463 } else if (expr_type == TypeManager.byte_type){
465 // From byte to short, ushort, int, uint, long, ulong, float, double
467 if ((target_type == TypeManager.short_type) ||
468 (target_type == TypeManager.ushort_type) ||
469 (target_type == TypeManager.int32_type) ||
470 (target_type == TypeManager.uint32_type) ||
471 (target_type == TypeManager.uint64_type) ||
472 (target_type == TypeManager.int64_type) ||
473 (target_type == TypeManager.float_type) ||
474 (target_type == TypeManager.double_type) ||
475 (target_type == TypeManager.decimal_type))
478 } else if (expr_type == TypeManager.short_type){
480 // From short to int, long, float, double
482 if ((target_type == TypeManager.int32_type) ||
483 (target_type == TypeManager.int64_type) ||
484 (target_type == TypeManager.double_type) ||
485 (target_type == TypeManager.float_type) ||
486 (target_type == TypeManager.decimal_type))
489 } else if (expr_type == TypeManager.ushort_type){
491 // From ushort to int, uint, long, ulong, float, double
493 if ((target_type == TypeManager.uint32_type) ||
494 (target_type == TypeManager.uint64_type) ||
495 (target_type == TypeManager.int32_type) ||
496 (target_type == TypeManager.int64_type) ||
497 (target_type == TypeManager.double_type) ||
498 (target_type == TypeManager.float_type) ||
499 (target_type == TypeManager.decimal_type))
502 } else if (expr_type == TypeManager.int32_type){
504 // From int to long, float, double
506 if ((target_type == TypeManager.int64_type) ||
507 (target_type == TypeManager.double_type) ||
508 (target_type == TypeManager.float_type) ||
509 (target_type == TypeManager.decimal_type))
512 } else if (expr_type == TypeManager.uint32_type){
514 // From uint to long, ulong, float, double
516 if ((target_type == TypeManager.int64_type) ||
517 (target_type == TypeManager.uint64_type) ||
518 (target_type == TypeManager.double_type) ||
519 (target_type == TypeManager.float_type) ||
520 (target_type == TypeManager.decimal_type))
523 } else if ((expr_type == TypeManager.uint64_type) ||
524 (expr_type == TypeManager.int64_type)) {
526 // From long/ulong to float, double
528 if ((target_type == TypeManager.double_type) ||
529 (target_type == TypeManager.float_type) ||
530 (target_type == TypeManager.decimal_type))
533 } else if (expr_type == TypeManager.char_type){
535 // From char to ushort, int, uint, long, ulong, float, double
537 if ((target_type == TypeManager.ushort_type) ||
538 (target_type == TypeManager.int32_type) ||
539 (target_type == TypeManager.uint32_type) ||
540 (target_type == TypeManager.uint64_type) ||
541 (target_type == TypeManager.int64_type) ||
542 (target_type == TypeManager.float_type) ||
543 (target_type == TypeManager.double_type) ||
544 (target_type == TypeManager.decimal_type))
547 } else if (expr_type == TypeManager.float_type){
551 if (target_type == TypeManager.double_type)
555 if (ImplicitReferenceConversionExists (expr, target_type))
559 // Implicit Constant Expression Conversions
561 if (expr is IntConstant){
562 int value = ((IntConstant) expr).Value;
564 if (target_type == TypeManager.sbyte_type){
565 if (value >= SByte.MinValue && value <= SByte.MaxValue)
567 } else if (target_type == TypeManager.byte_type){
568 if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
570 } else if (target_type == TypeManager.short_type){
571 if (value >= Int16.MinValue && value <= Int16.MaxValue)
573 } else if (target_type == TypeManager.ushort_type){
574 if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
576 } else if (target_type == TypeManager.uint32_type){
579 } else if (target_type == TypeManager.uint64_type){
581 // we can optimize this case: a positive int32
582 // always fits on a uint64. But we need an opcode
589 if (value == 0 && expr is IntLiteral && TypeManager.IsEnumType (target_type))
593 if (expr is LongConstant && target_type == TypeManager.uint64_type){
595 // Try the implicit constant expression conversion
596 // from long to ulong, instead of a nice routine,
599 long v = ((LongConstant) expr).Value;
604 if ((target_type == TypeManager.enum_type ||
605 target_type.IsSubclassOf (TypeManager.enum_type)) &&
607 IntLiteral i = (IntLiteral) expr;
613 if (target_type == TypeManager.void_ptr_type && expr_type.IsPointer)
620 // Used internally by FindMostEncompassedType, this is used
621 // to avoid creating lots of objects in the tight loop inside
622 // FindMostEncompassedType
624 static EmptyExpression priv_fmet_param;
627 /// Finds "most encompassed type" according to the spec (13.4.2)
628 /// amongst the methods in the MethodGroupExpr
630 static Type FindMostEncompassedType (ArrayList types)
634 if (priv_fmet_param == null)
635 priv_fmet_param = new EmptyExpression ();
637 foreach (Type t in types){
638 priv_fmet_param.SetType (t);
645 if (ImplicitStandardConversionExists (priv_fmet_param, best))
653 // Used internally by FindMostEncompassingType, this is used
654 // to avoid creating lots of objects in the tight loop inside
655 // FindMostEncompassingType
657 static EmptyExpression priv_fmee_ret;
660 /// Finds "most encompassing type" according to the spec (13.4.2)
661 /// amongst the types in the given set
663 static Type FindMostEncompassingType (ArrayList types)
667 if (priv_fmee_ret == null)
668 priv_fmee_ret = new EmptyExpression ();
670 foreach (Type t in types){
671 priv_fmee_ret.SetType (best);
678 if (ImplicitStandardConversionExists (priv_fmee_ret, t))
686 // Used to avoid creating too many objects
688 static EmptyExpression priv_fms_expr;
691 /// Finds the most specific source Sx according to the rules of the spec (13.4.4)
692 /// by making use of FindMostEncomp* methods. Applies the correct rules separately
693 /// for explicit and implicit conversion operators.
695 static public Type FindMostSpecificSource (MethodGroupExpr me, Expression source,
696 bool apply_explicit_conv_rules,
699 ArrayList src_types_set = new ArrayList ();
701 if (priv_fms_expr == null)
702 priv_fms_expr = new EmptyExpression ();
705 // If any operator converts from S then Sx = S
707 Type source_type = source.Type;
708 foreach (MethodBase mb in me.Methods){
709 ParameterData pd = Invocation.GetParameterData (mb);
710 Type param_type = pd.ParameterType (0);
712 if (param_type == source_type)
715 if (apply_explicit_conv_rules) {
718 // Find the set of applicable user-defined conversion operators, U. This set
720 // user-defined implicit or explicit conversion operators declared by
721 // the classes or structs in D that convert from a type encompassing
722 // or encompassed by S to a type encompassing or encompassed by T
724 priv_fms_expr.SetType (param_type);
725 if (ImplicitStandardConversionExists (priv_fms_expr, source_type))
726 src_types_set.Add (param_type);
728 if (ImplicitStandardConversionExists (source, param_type))
729 src_types_set.Add (param_type);
733 // Only if S is encompassed by param_type
735 if (ImplicitStandardConversionExists (source, param_type))
736 src_types_set.Add (param_type);
741 // Explicit Conv rules
743 if (apply_explicit_conv_rules) {
744 ArrayList candidate_set = new ArrayList ();
746 foreach (Type param_type in src_types_set){
747 if (ImplicitStandardConversionExists (source, param_type))
748 candidate_set.Add (param_type);
751 if (candidate_set.Count != 0)
752 return FindMostEncompassedType (candidate_set);
758 if (apply_explicit_conv_rules)
759 return FindMostEncompassingType (src_types_set);
761 return FindMostEncompassedType (src_types_set);
765 // Useful in avoiding proliferation of objects
767 static EmptyExpression priv_fmt_expr;
770 /// Finds the most specific target Tx according to section 13.4.4
772 static public Type FindMostSpecificTarget (MethodGroupExpr me, Type target,
773 bool apply_explicit_conv_rules,
776 ArrayList tgt_types_set = new ArrayList ();
778 if (priv_fmt_expr == null)
779 priv_fmt_expr = new EmptyExpression ();
782 // If any operator converts to T then Tx = T
784 foreach (MethodInfo mi in me.Methods){
785 Type ret_type = mi.ReturnType;
787 if (ret_type == target)
790 if (apply_explicit_conv_rules) {
793 // Find the set of applicable user-defined conversion operators, U.
795 // This set consists of the
796 // user-defined implicit or explicit conversion operators declared by
797 // the classes or structs in D that convert from a type encompassing
798 // or encompassed by S to a type encompassing or encompassed by T
800 priv_fms_expr.SetType (ret_type);
801 if (ImplicitStandardConversionExists (priv_fms_expr, target))
802 tgt_types_set.Add (ret_type);
804 priv_fms_expr.SetType (target);
805 if (ImplicitStandardConversionExists (priv_fms_expr, ret_type))
806 tgt_types_set.Add (ret_type);
810 // Only if T is encompassed by param_type
812 priv_fms_expr.SetType (ret_type);
813 if (ImplicitStandardConversionExists (priv_fms_expr, target))
814 tgt_types_set.Add (ret_type);
819 // Explicit conv rules
821 if (apply_explicit_conv_rules) {
822 ArrayList candidate_set = new ArrayList ();
824 foreach (Type ret_type in tgt_types_set){
825 priv_fmt_expr.SetType (ret_type);
827 if (ImplicitStandardConversionExists (priv_fmt_expr, target))
828 candidate_set.Add (ret_type);
831 if (candidate_set.Count != 0)
832 return FindMostEncompassingType (candidate_set);
836 // Okay, final case !
838 if (apply_explicit_conv_rules)
839 return FindMostEncompassedType (tgt_types_set);
841 return FindMostEncompassingType (tgt_types_set);
845 /// User-defined Implicit conversions
847 static public Expression ImplicitUserConversion (EmitContext ec, Expression source,
848 Type target, Location loc)
850 return UserDefinedConversion (ec, source, target, loc, false);
854 /// User-defined Explicit conversions
856 static public Expression ExplicitUserConversion (EmitContext ec, Expression source,
857 Type target, Location loc)
859 return UserDefinedConversion (ec, source, target, loc, true);
863 /// Computes the MethodGroup for the user-defined conversion
864 /// operators from source_type to target_type. `look_for_explicit'
865 /// controls whether we should also include the list of explicit
868 static MethodGroupExpr GetConversionOperators (EmitContext ec,
869 Type source_type, Type target_type,
870 Location loc, bool look_for_explicit)
872 Expression mg1 = null, mg2 = null;
873 Expression mg5 = null, mg6 = null, mg7 = null, mg8 = null;
876 op_name = "op_Implicit";
878 MethodGroupExpr union3;
880 mg1 = Expression.MethodLookup (ec, source_type, op_name, loc);
881 if (source_type.BaseType != null)
882 mg2 = Expression.MethodLookup (ec, source_type.BaseType, op_name, loc);
885 union3 = (MethodGroupExpr) mg2;
886 else if (mg2 == null)
887 union3 = (MethodGroupExpr) mg1;
889 union3 = Invocation.MakeUnionSet (mg1, mg2, loc);
891 mg1 = Expression.MethodLookup (ec, target_type, op_name, loc);
894 union3 = Invocation.MakeUnionSet (union3, mg1, loc);
896 union3 = (MethodGroupExpr) mg1;
899 if (target_type.BaseType != null)
900 mg1 = Expression.MethodLookup (ec, target_type.BaseType, op_name, loc);
904 union3 = Invocation.MakeUnionSet (union3, mg1, loc);
906 union3 = (MethodGroupExpr) mg1;
909 MethodGroupExpr union4 = null;
911 if (look_for_explicit) {
912 op_name = "op_Explicit";
914 mg5 = Expression.MemberLookup (ec, source_type, op_name, loc);
915 if (source_type.BaseType != null)
916 mg6 = Expression.MethodLookup (ec, source_type.BaseType, op_name, loc);
918 mg7 = Expression.MemberLookup (ec, target_type, op_name, loc);
919 if (target_type.BaseType != null)
920 mg8 = Expression.MethodLookup (ec, target_type.BaseType, op_name, loc);
922 MethodGroupExpr union5 = Invocation.MakeUnionSet (mg5, mg6, loc);
923 MethodGroupExpr union6 = Invocation.MakeUnionSet (mg7, mg8, loc);
925 union4 = Invocation.MakeUnionSet (union5, union6, loc);
928 return Invocation.MakeUnionSet (union3, union4, loc);
932 /// User-defined conversions
934 static public Expression UserDefinedConversion (EmitContext ec, Expression source,
935 Type target, Location loc,
936 bool look_for_explicit)
938 MethodGroupExpr union;
939 Type source_type = source.Type;
940 MethodBase method = null;
942 union = GetConversionOperators (ec, source_type, target, loc, look_for_explicit);
946 Type most_specific_source, most_specific_target;
948 most_specific_source = FindMostSpecificSource (union, source, look_for_explicit, loc);
949 if (most_specific_source == null)
952 most_specific_target = FindMostSpecificTarget (union, target, look_for_explicit, loc);
953 if (most_specific_target == null)
959 foreach (MethodBase mb in union.Methods){
960 ParameterData pd = Invocation.GetParameterData (mb);
961 MethodInfo mi = (MethodInfo) mb;
963 if (pd.ParameterType (0) == most_specific_source &&
964 mi.ReturnType == most_specific_target) {
970 if (method == null || count > 1)
975 // This will do the conversion to the best match that we
976 // found. Now we need to perform an implict standard conversion
977 // if the best match was not the type that we were requested
980 if (look_for_explicit)
981 source = ExplicitConversionStandard (ec, source, most_specific_source, loc);
983 source = ImplicitConversionStandard (ec, source, most_specific_source, loc);
989 e = new UserCast ((MethodInfo) method, source, loc);
990 if (e.Type != target){
991 if (!look_for_explicit)
992 e = ImplicitConversionStandard (ec, e, target, loc);
994 e = ExplicitConversionStandard (ec, e, target, loc);
1001 /// Converts implicitly the resolved expression `expr' into the
1002 /// `target_type'. It returns a new expression that can be used
1003 /// in a context that expects a `target_type'.
1005 static public Expression ImplicitConversion (EmitContext ec, Expression expr,
1006 Type target_type, Location loc)
1010 if (target_type == null)
1011 throw new Exception ("Target type is null");
1013 e = ImplicitConversionStandard (ec, expr, target_type, loc);
1017 e = ImplicitUserConversion (ec, expr, target_type, loc);
1026 /// Attempts to apply the `Standard Implicit
1027 /// Conversion' rules to the expression `expr' into
1028 /// the `target_type'. It returns a new expression
1029 /// that can be used in a context that expects a
1032 /// This is different from `ImplicitConversion' in that the
1033 /// user defined implicit conversions are excluded.
1035 static public Expression ImplicitConversionStandard (EmitContext ec, Expression expr,
1036 Type target_type, Location loc)
1038 Type expr_type = expr.Type;
1041 if (expr.eclass == ExprClass.MethodGroup){
1042 if (!TypeManager.IsDelegateType (target_type)){
1043 Report.Error (428, loc,
1045 "Cannot convert method group to `{0}', since it is not a delegate",
1046 TypeManager.CSharpName (target_type)));
1050 return ImplicitDelegateCreation.Create (ec, (MethodGroupExpr) expr, target_type, loc);
1053 if (expr_type.Equals (target_type) && !(expr is NullLiteral))
1056 e = ImplicitNumericConversion (ec, expr, target_type, loc);
1060 e = ImplicitReferenceConversion (expr, target_type);
1064 if ((target_type == TypeManager.enum_type ||
1065 target_type.IsSubclassOf (TypeManager.enum_type)) &&
1066 expr is IntLiteral){
1067 IntLiteral i = (IntLiteral) expr;
1070 return new EnumConstant ((Constant) expr, target_type);
1074 if (expr_type.IsPointer){
1075 if (target_type == TypeManager.void_ptr_type)
1076 return new EmptyCast (expr, target_type);
1079 // yep, comparing pointer types cant be done with
1080 // t1 == t2, we have to compare their element types.
1082 if (target_type.IsPointer){
1083 if (TypeManager.GetElementType(target_type) == TypeManager.GetElementType(expr_type))
1088 if (target_type.IsPointer) {
1089 if (expr is NullLiteral)
1090 return new EmptyCast (expr, target_type);
1092 if (expr_type == TypeManager.void_ptr_type)
1093 return new EmptyCast (expr, target_type);
1101 /// Attemps to perform an implict constant conversion of the IntConstant
1102 /// into a different data type using casts (See Implicit Constant
1103 /// Expression Conversions)
1105 static public Expression TryImplicitIntConversion (Type target_type, IntConstant ic)
1107 int value = ic.Value;
1109 if (target_type == TypeManager.sbyte_type){
1110 if (value >= SByte.MinValue && value <= SByte.MaxValue)
1111 return new SByteConstant ((sbyte) value);
1112 } else if (target_type == TypeManager.byte_type){
1113 if (value >= Byte.MinValue && value <= Byte.MaxValue)
1114 return new ByteConstant ((byte) value);
1115 } else if (target_type == TypeManager.short_type){
1116 if (value >= Int16.MinValue && value <= Int16.MaxValue)
1117 return new ShortConstant ((short) value);
1118 } else if (target_type == TypeManager.ushort_type){
1119 if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
1120 return new UShortConstant ((ushort) value);
1121 } else if (target_type == TypeManager.uint32_type){
1123 return new UIntConstant ((uint) value);
1124 } else if (target_type == TypeManager.uint64_type){
1126 // we can optimize this case: a positive int32
1127 // always fits on a uint64. But we need an opcode
1131 return new ULongConstant ((ulong) value);
1132 } else if (target_type == TypeManager.double_type)
1133 return new DoubleConstant ((double) value);
1134 else if (target_type == TypeManager.float_type)
1135 return new FloatConstant ((float) value);
1137 if (value == 0 && ic is IntLiteral && TypeManager.IsEnumType (target_type)){
1138 Type underlying = TypeManager.EnumToUnderlying (target_type);
1139 Constant e = (Constant) ic;
1142 // Possibly, we need to create a different 0 literal before passing
1145 if (underlying == TypeManager.int64_type)
1146 e = new LongLiteral (0);
1147 else if (underlying == TypeManager.uint64_type)
1148 e = new ULongLiteral (0);
1150 return new EnumConstant (e, target_type);
1155 static public void Error_CannotImplicitConversion (Location loc, Type source, Type target)
1157 string msg = "Cannot convert implicitly from `"+
1158 TypeManager.CSharpName (source) + "' to `" +
1159 TypeManager.CSharpName (target) + "'";
1161 Report.Error (29, loc, msg);
1165 /// Attemptes to implicityly convert `target' into `type', using
1166 /// ImplicitConversion. If there is no implicit conversion, then
1167 /// an error is signaled
1169 static public Expression ImplicitConversionRequired (EmitContext ec, Expression source,
1170 Type target_type, Location loc)
1174 e = ImplicitConversion (ec, source, target_type, loc);
1178 if (source is DoubleLiteral && target_type == TypeManager.float_type){
1179 Report.Error (664, loc,
1180 "Double literal cannot be implicitly converted to " +
1181 "float type, use F suffix to create a float literal");
1184 if (source is Constant){
1185 Constant c = (Constant) source;
1187 Expression.Error_ConstantValueCannotBeConverted (loc, c.AsString (), target_type);
1191 Error_CannotImplicitConversion (loc, source.Type, target_type);
1197 /// Performs the explicit numeric conversions
1199 static Expression ExplicitNumericConversion (EmitContext ec, Expression expr, Type target_type, Location loc)
1201 Type expr_type = expr.Type;
1204 // If we have an enumeration, extract the underlying type,
1205 // use this during the comparison, but wrap around the original
1208 Type real_target_type = target_type;
1210 if (TypeManager.IsEnumType (real_target_type))
1211 real_target_type = TypeManager.EnumToUnderlying (real_target_type);
1213 if (ImplicitStandardConversionExists (expr, real_target_type)){
1214 Expression ce = ImplicitConversionStandard (ec, expr, real_target_type, loc);
1216 if (real_target_type != target_type)
1217 return new EmptyCast (ce, target_type);
1221 if (expr_type == TypeManager.sbyte_type){
1223 // From sbyte to byte, ushort, uint, ulong, char
1225 if (real_target_type == TypeManager.byte_type)
1226 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U1);
1227 if (real_target_type == TypeManager.ushort_type)
1228 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U2);
1229 if (real_target_type == TypeManager.uint32_type)
1230 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U4);
1231 if (real_target_type == TypeManager.uint64_type)
1232 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U8);
1233 if (real_target_type == TypeManager.char_type)
1234 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_CH);
1235 } else if (expr_type == TypeManager.byte_type){
1237 // From byte to sbyte and char
1239 if (real_target_type == TypeManager.sbyte_type)
1240 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U1_I1);
1241 if (real_target_type == TypeManager.char_type)
1242 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U1_CH);
1243 } else if (expr_type == TypeManager.short_type){
1245 // From short to sbyte, byte, ushort, uint, ulong, char
1247 if (real_target_type == TypeManager.sbyte_type)
1248 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_I1);
1249 if (real_target_type == TypeManager.byte_type)
1250 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U1);
1251 if (real_target_type == TypeManager.ushort_type)
1252 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U2);
1253 if (real_target_type == TypeManager.uint32_type)
1254 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U4);
1255 if (real_target_type == TypeManager.uint64_type)
1256 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U8);
1257 if (real_target_type == TypeManager.char_type)
1258 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_CH);
1259 } else if (expr_type == TypeManager.ushort_type){
1261 // From ushort to sbyte, byte, short, char
1263 if (real_target_type == TypeManager.sbyte_type)
1264 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_I1);
1265 if (real_target_type == TypeManager.byte_type)
1266 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_U1);
1267 if (real_target_type == TypeManager.short_type)
1268 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_I2);
1269 if (real_target_type == TypeManager.char_type)
1270 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_CH);
1271 } else if (expr_type == TypeManager.int32_type){
1273 // From int to sbyte, byte, short, ushort, uint, ulong, char
1275 if (real_target_type == TypeManager.sbyte_type)
1276 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I1);
1277 if (real_target_type == TypeManager.byte_type)
1278 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U1);
1279 if (real_target_type == TypeManager.short_type)
1280 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I2);
1281 if (real_target_type == TypeManager.ushort_type)
1282 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U2);
1283 if (real_target_type == TypeManager.uint32_type)
1284 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U4);
1285 if (real_target_type == TypeManager.uint64_type)
1286 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U8);
1287 if (real_target_type == TypeManager.char_type)
1288 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_CH);
1289 } else if (expr_type == TypeManager.uint32_type){
1291 // From uint to sbyte, byte, short, ushort, int, char
1293 if (real_target_type == TypeManager.sbyte_type)
1294 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I1);
1295 if (real_target_type == TypeManager.byte_type)
1296 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U1);
1297 if (real_target_type == TypeManager.short_type)
1298 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I2);
1299 if (real_target_type == TypeManager.ushort_type)
1300 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U2);
1301 if (real_target_type == TypeManager.int32_type)
1302 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I4);
1303 if (real_target_type == TypeManager.char_type)
1304 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_CH);
1305 } else if (expr_type == TypeManager.int64_type){
1307 // From long to sbyte, byte, short, ushort, int, uint, ulong, char
1309 if (real_target_type == TypeManager.sbyte_type)
1310 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I1);
1311 if (real_target_type == TypeManager.byte_type)
1312 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U1);
1313 if (real_target_type == TypeManager.short_type)
1314 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I2);
1315 if (real_target_type == TypeManager.ushort_type)
1316 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U2);
1317 if (real_target_type == TypeManager.int32_type)
1318 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I4);
1319 if (real_target_type == TypeManager.uint32_type)
1320 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U4);
1321 if (real_target_type == TypeManager.uint64_type)
1322 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U8);
1323 if (real_target_type == TypeManager.char_type)
1324 return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_CH);
1325 } else if (expr_type == TypeManager.uint64_type){
1327 // From ulong to sbyte, byte, short, ushort, int, uint, long, char
1329 if (real_target_type == TypeManager.sbyte_type)
1330 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I1);
1331 if (real_target_type == TypeManager.byte_type)
1332 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U1);
1333 if (real_target_type == TypeManager.short_type)
1334 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I2);
1335 if (real_target_type == TypeManager.ushort_type)
1336 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U2);
1337 if (real_target_type == TypeManager.int32_type)
1338 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I4);
1339 if (real_target_type == TypeManager.uint32_type)
1340 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U4);
1341 if (real_target_type == TypeManager.int64_type)
1342 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I8);
1343 if (real_target_type == TypeManager.char_type)
1344 return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_CH);
1345 } else if (expr_type == TypeManager.char_type){
1347 // From char to sbyte, byte, short
1349 if (real_target_type == TypeManager.sbyte_type)
1350 return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_I1);
1351 if (real_target_type == TypeManager.byte_type)
1352 return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_U1);
1353 if (real_target_type == TypeManager.short_type)
1354 return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_I2);
1355 } else if (expr_type == TypeManager.float_type){
1357 // From float to sbyte, byte, short,
1358 // ushort, int, uint, long, ulong, char
1361 if (real_target_type == TypeManager.sbyte_type)
1362 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I1);
1363 if (real_target_type == TypeManager.byte_type)
1364 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U1);
1365 if (real_target_type == TypeManager.short_type)
1366 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I2);
1367 if (real_target_type == TypeManager.ushort_type)
1368 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U2);
1369 if (real_target_type == TypeManager.int32_type)
1370 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I4);
1371 if (real_target_type == TypeManager.uint32_type)
1372 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U4);
1373 if (real_target_type == TypeManager.int64_type)
1374 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I8);
1375 if (real_target_type == TypeManager.uint64_type)
1376 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U8);
1377 if (real_target_type == TypeManager.char_type)
1378 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_CH);
1379 } else if (expr_type == TypeManager.double_type){
1381 // From double to byte, byte, short,
1382 // ushort, int, uint, long, ulong,
1383 // char, float or decimal
1385 if (real_target_type == TypeManager.sbyte_type)
1386 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I1);
1387 if (real_target_type == TypeManager.byte_type)
1388 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U1);
1389 if (real_target_type == TypeManager.short_type)
1390 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I2);
1391 if (real_target_type == TypeManager.ushort_type)
1392 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U2);
1393 if (real_target_type == TypeManager.int32_type)
1394 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I4);
1395 if (real_target_type == TypeManager.uint32_type)
1396 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U4);
1397 if (real_target_type == TypeManager.int64_type)
1398 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I8);
1399 if (real_target_type == TypeManager.uint64_type)
1400 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U8);
1401 if (real_target_type == TypeManager.char_type)
1402 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_CH);
1403 if (real_target_type == TypeManager.float_type)
1404 return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4);
1407 // decimal is taken care of by the op_Explicit methods.
1413 /// Returns whether an explicit reference conversion can be performed
1414 /// from source_type to target_type
1416 public static bool ExplicitReferenceConversionExists (Type source_type, Type target_type)
1418 bool target_is_type_param = target_type.IsGenericParameter;
1419 bool target_is_value_type = target_type.IsValueType;
1421 if (source_type == target_type)
1425 // From object to a generic parameter
1427 if (source_type == TypeManager.object_type && target_is_type_param)
1431 // From object to any reference type
1433 if (source_type == TypeManager.object_type && !target_is_value_type)
1437 // From any class S to any class-type T, provided S is a base class of T
1439 if (TypeManager.IsSubclassOf (target_type, source_type))
1443 // From any interface type S to any interface T provided S is not derived from T
1445 if (source_type.IsInterface && target_type.IsInterface){
1446 if (!TypeManager.IsSubclassOf (target_type, source_type))
1451 // From any class type S to any interface T, provided S is not sealed
1452 // and provided S does not implement T.
1454 if (target_type.IsInterface && !source_type.IsSealed &&
1455 !TypeManager.ImplementsInterface (source_type, target_type))
1459 // From any interface-type S to to any class type T, provided T is not
1460 // sealed, or provided T implements S.
1462 if (source_type.IsInterface &&
1463 (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type)))
1467 // From an array type S with an element type Se to an array type T with an
1468 // element type Te provided all the following are true:
1469 // * S and T differe only in element type, in other words, S and T
1470 // have the same number of dimensions.
1471 // * Both Se and Te are reference types
1472 // * An explicit referenc conversions exist from Se to Te
1474 if (source_type.IsArray && target_type.IsArray) {
1475 if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
1477 Type source_element_type = TypeManager.GetElementType (source_type);
1478 Type target_element_type = TypeManager.GetElementType (target_type);
1480 if (!source_element_type.IsValueType && !target_element_type.IsValueType)
1481 if (ExplicitReferenceConversionExists (source_element_type,
1482 target_element_type))
1488 // From System.Array to any array-type
1489 if (source_type == TypeManager.array_type &&
1490 target_type.IsArray){
1495 // From System delegate to any delegate-type
1497 if (source_type == TypeManager.delegate_type &&
1498 TypeManager.IsDelegateType (target_type))
1502 // From ICloneable to Array or Delegate types
1504 if (source_type == TypeManager.icloneable_type &&
1505 (target_type == TypeManager.array_type ||
1506 target_type == TypeManager.delegate_type))
1513 /// Implements Explicit Reference conversions
1515 static Expression ExplicitReferenceConversion (Expression source, Type target_type)
1517 Type source_type = source.Type;
1518 bool target_is_type_param = target_type.IsGenericParameter;
1519 bool target_is_value_type = target_type.IsValueType;
1522 // From object to a generic parameter
1524 if (source_type == TypeManager.object_type && target_is_type_param)
1525 return new UnboxCast (source, target_type);
1528 // From object to any reference type
1530 if (source_type == TypeManager.object_type && !target_is_value_type)
1531 return new ClassCast (source, target_type);
1534 // Unboxing conversion.
1536 if (((source_type == TypeManager.enum_type &&
1537 !(source is EmptyCast)) ||
1538 source_type == TypeManager.value_type) && target_is_value_type)
1539 return new UnboxCast (source, target_type);
1542 // From any class S to any class-type T, provided S is a base class of T
1544 if (TypeManager.IsSubclassOf (target_type, source_type))
1545 return new ClassCast (source, target_type);
1548 // From any interface type S to any interface T provided S is not derived from T
1550 if (source_type.IsInterface && target_type.IsInterface){
1551 if (TypeManager.ImplementsInterface (source_type, target_type))
1554 return new ClassCast (source, target_type);
1558 // From any class type S to any interface T, provides S is not sealed
1559 // and provided S does not implement T.
1561 if (target_type.IsInterface && !source_type.IsSealed) {
1562 if (TypeManager.ImplementsInterface (source_type, target_type))
1565 return new ClassCast (source, target_type);
1570 // From any interface-type S to to any class type T, provided T is not
1571 // sealed, or provided T implements S.
1573 if (source_type.IsInterface) {
1574 if (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type)) {
1575 if (target_type.IsClass)
1576 return new ClassCast (source, target_type);
1578 return new UnboxCast (source, target_type);
1584 // From an array type S with an element type Se to an array type T with an
1585 // element type Te provided all the following are true:
1586 // * S and T differe only in element type, in other words, S and T
1587 // have the same number of dimensions.
1588 // * Both Se and Te are reference types
1589 // * An explicit referenc conversions exist from Se to Te
1591 if (source_type.IsArray && target_type.IsArray) {
1592 if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
1594 Type source_element_type = TypeManager.GetElementType (source_type);
1595 Type target_element_type = TypeManager.GetElementType (target_type);
1597 if (!source_element_type.IsValueType && !target_element_type.IsValueType)
1598 if (ExplicitReferenceConversionExists (source_element_type,
1599 target_element_type))
1600 return new ClassCast (source, target_type);
1605 // From System.Array to any array-type
1606 if (source_type == TypeManager.array_type &&
1607 target_type.IsArray) {
1608 return new ClassCast (source, target_type);
1612 // From System delegate to any delegate-type
1614 if (source_type == TypeManager.delegate_type &&
1615 TypeManager.IsDelegateType (target_type))
1616 return new ClassCast (source, target_type);
1619 // From ICloneable to Array or Delegate types
1621 if (source_type == TypeManager.icloneable_type &&
1622 (target_type == TypeManager.array_type ||
1623 target_type == TypeManager.delegate_type))
1624 return new ClassCast (source, target_type);
1630 /// Performs an explicit conversion of the expression `expr' whose
1631 /// type is expr.Type to `target_type'.
1633 static public Expression ExplicitConversion (EmitContext ec, Expression expr,
1634 Type target_type, Location loc)
1636 Type expr_type = expr.Type;
1637 Type original_expr_type = expr_type;
1639 if (expr_type.IsSubclassOf (TypeManager.enum_type)){
1640 if (target_type == TypeManager.enum_type ||
1641 target_type == TypeManager.object_type) {
1642 if (expr is EnumConstant)
1643 expr = ((EnumConstant) expr).Child;
1644 // We really need all these casts here .... :-(
1645 expr = new BoxedCast (new EmptyCast (expr, expr_type));
1646 return new EmptyCast (expr, target_type);
1647 } else if ((expr_type == TypeManager.enum_type) && target_type.IsValueType &&
1648 target_type.IsSubclassOf (TypeManager.enum_type))
1649 return new UnboxCast (expr, target_type);
1652 // Notice that we have kept the expr_type unmodified, which is only
1654 if (expr is EnumConstant)
1655 expr = ((EnumConstant) expr).Child;
1657 expr = new EmptyCast (expr, TypeManager.EnumToUnderlying (expr_type));
1658 expr_type = expr.Type;
1661 Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc);
1666 ne = ExplicitNumericConversion (ec, expr, target_type, loc);
1671 // Unboxing conversion.
1673 if (expr_type == TypeManager.object_type && target_type.IsValueType){
1674 if (expr is NullLiteral){
1676 // Skip the ExplicitReferenceConversion because we can not convert
1677 // from Null to a ValueType, and ExplicitReference wont check against
1678 // null literal explicitly
1682 return new UnboxCast (expr, target_type);
1686 ne = ExplicitReferenceConversion (expr, target_type);
1692 if (target_type.IsPointer){
1693 if (expr_type.IsPointer)
1694 return new EmptyCast (expr, target_type);
1696 if (expr_type == TypeManager.sbyte_type ||
1697 expr_type == TypeManager.byte_type ||
1698 expr_type == TypeManager.short_type ||
1699 expr_type == TypeManager.ushort_type ||
1700 expr_type == TypeManager.int32_type ||
1701 expr_type == TypeManager.uint32_type ||
1702 expr_type == TypeManager.uint64_type ||
1703 expr_type == TypeManager.int64_type)
1704 return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
1706 if (expr_type.IsPointer){
1707 Expression e = null;
1709 if (target_type == TypeManager.sbyte_type)
1710 e = new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
1711 else if (target_type == TypeManager.byte_type)
1712 e = new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
1713 else if (target_type == TypeManager.short_type)
1714 e = new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
1715 else if (target_type == TypeManager.ushort_type)
1716 e = new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1717 else if (target_type == TypeManager.int32_type)
1718 e = new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
1719 else if (target_type == TypeManager.uint32_type)
1720 e = new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
1721 else if (target_type == TypeManager.uint64_type)
1722 e = new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
1723 else if (target_type == TypeManager.int64_type){
1724 e = new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
1730 ci = ImplicitConversionStandard (ec, e, target_type, loc);
1735 ce = ExplicitNumericConversion (ec, e, target_type, loc);
1739 // We should always be able to go from an uint32
1740 // implicitly or explicitly to the other integral
1743 throw new Exception ("Internal compiler error");
1748 ne = ExplicitUserConversion (ec, expr, target_type, loc);
1752 if (expr is NullLiteral){
1753 Report.Error (37, loc, "Cannot convert null to value type `" +
1754 TypeManager.CSharpName (target_type) + "'");
1758 Error_CannotConvertType (loc, original_expr_type, target_type);
1763 /// Same as ExplicitConversion, only it doesn't include user defined conversions
1765 static public Expression ExplicitConversionStandard (EmitContext ec, Expression expr,
1766 Type target_type, Location l)
1768 Expression ne = ImplicitConversionStandard (ec, expr, target_type, l);
1773 ne = ExplicitNumericConversion (ec, expr, target_type, l);
1777 ne = ExplicitReferenceConversion (expr, target_type);
1781 Error_CannotConvertType (l, expr.Type, target_type);