2007-01-01 Miguel de Icaza <miguel@novell.com>
[mono.git] / mcs / mcs / convert.cs
1 //
2 // conversion.cs: various routines for implementing conversions.
3 //
4 // Authors:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Ravi Pratap (ravi@ximian.com)
7 //   Marek Safar (marek.safar@gmail.com)
8 //
9 // (C) 2001, 2002, 2003 Ximian, Inc.
10 //
11
12 namespace Mono.CSharp {
13         using System;
14         using System.Collections;
15         using System.Diagnostics;
16         using System.Reflection;
17         using System.Reflection.Emit;
18
19         //
20         // A container class for all the conversion operations
21         //
22         public class Convert {
23 #if GMCS_SOURCE
24                 static bool TypeParameter_to_Null (Type target_type)
25                 {
26                         GenericConstraints gc = TypeManager.GetTypeParameterConstraints (target_type);
27                         if (gc == null)
28                                 return false;
29
30                         if (gc.HasReferenceTypeConstraint)
31                                 return true;
32                         if (gc.HasClassConstraint && !TypeManager.IsValueType (gc.ClassConstraint))
33                                 return true;
34
35                         return false;
36                 }
37
38                 static Type TypeParam_EffectiveBaseType (GenericConstraints gc)
39                 {
40                         ArrayList list = new ArrayList ();
41                         list.Add (gc.EffectiveBaseClass);
42                         foreach (Type t in gc.InterfaceConstraints) {
43                                 if (!TypeManager.IsGenericParameter (t))
44                                         continue;
45
46                                 GenericConstraints new_gc = TypeManager.GetTypeParameterConstraints (t);
47                                 if (new_gc != null)
48                                         list.Add (TypeParam_EffectiveBaseType (new_gc));
49                         }
50                         return FindMostEncompassedType (list);
51                 }
52 #endif
53
54                 //
55                 // From a one-dimensional array-type S[] to System.Collections.IList<S> and base
56                 // interfaces of this interface.
57                 //
58                 // From a one-dimensional array-type S[] to System.Collections.IList<T> and base
59                 // interfaces of this interface, provided there is an implicit reference conversion
60                 // from S to T.
61                 //
62                 static bool Array_To_IList (Type array, Type list)
63                 {
64 #if GMCS_SOURCE
65                         if (!array.IsArray || (array.GetArrayRank () != 1) || !list.IsGenericType)
66                                 return false;
67
68                         Type gt = list.GetGenericTypeDefinition ();
69                         if ((gt != TypeManager.generic_ilist_type) &&
70                             (gt != TypeManager.generic_icollection_type) &&
71                             (gt != TypeManager.generic_ienumerable_type))
72                                 return false;
73
74                         Type element_type = TypeManager.GetElementType (array);
75                         Type arg_type = TypeManager.GetTypeArguments (list) [0];
76
77                         if (element_type == arg_type)
78                                 return true;
79
80                         if (MyEmptyExpr == null)
81                                 MyEmptyExpr = new EmptyExpression ();
82                         MyEmptyExpr.SetType (TypeManager.GetElementType (array));
83
84                         return ImplicitReferenceConversionExists (MyEmptyExpr, arg_type);
85 #else
86                         return false;
87 #endif
88                 }
89
90                 static Expression ImplicitTypeParameterConversion (Expression expr,
91                                                                    Type target_type)
92                 {
93 #if GMCS_SOURCE
94                         Type expr_type = expr.Type;
95
96                         GenericConstraints gc = TypeManager.GetTypeParameterConstraints (expr_type);
97
98                         if (gc == null) {
99                                 if (target_type == TypeManager.object_type)
100                                         return new BoxedCast (expr, target_type);
101
102                                 return null;
103                         }
104
105                         // We're converting from a type parameter which is known to be a reference type.
106                         Type base_type = TypeParam_EffectiveBaseType (gc);
107
108                         if (TypeManager.IsSubclassOf (base_type, target_type))
109                                 return new ClassCast (expr, target_type);
110
111                         if (target_type.IsInterface) {
112                                 if (TypeManager.ImplementsInterface (base_type, target_type))
113                                         return new ClassCast (expr, target_type);
114
115                                 foreach (Type t in gc.InterfaceConstraints) {
116                                         if (TypeManager.IsSubclassOf (t, target_type))
117                                                 return new ClassCast (expr, target_type);
118                                         if (TypeManager.ImplementsInterface (t, target_type))
119                                                 return new ClassCast (expr, target_type);
120                                 }
121                         }
122
123                         foreach (Type t in gc.InterfaceConstraints) {
124                                 if (!TypeManager.IsGenericParameter (t))
125                                         continue;
126                                 if (TypeManager.IsSubclassOf (t, target_type))
127                                         return new ClassCast (expr, target_type);
128                                 if (TypeManager.ImplementsInterface (t, target_type))
129                                         return new ClassCast (expr, target_type);
130                         }
131 #endif
132                         return null;
133                 }
134
135                 static bool ExplicitTypeParameterConversionExists (Type source_type, Type target_type)
136                 {
137 #if GMCS_SOURCE
138                         if (target_type.IsInterface)
139                                 return true;
140
141                         if (TypeManager.IsGenericParameter (target_type)) {
142                                 GenericConstraints gc = TypeManager.GetTypeParameterConstraints (target_type);
143                                 if (gc == null)
144                                         return false;
145
146                                 foreach (Type iface in gc.InterfaceConstraints) {
147                                         if (!TypeManager.IsGenericParameter (iface))
148                                                 continue;
149
150                                         if (TypeManager.IsSubclassOf (source_type, iface))
151                                                 return true;
152                                 }
153                         }
154 #endif
155                         return false;
156                 }
157
158                 static Expression ExplicitTypeParameterConversion (Expression source, Type target_type)
159                 {
160 #if GMCS_SOURCE
161                         Type source_type = source.Type;
162
163                         if (target_type.IsInterface)
164                                 return new ClassCast (source, target_type);
165
166                         if (TypeManager.IsGenericParameter (target_type)) {
167                                 GenericConstraints gc = TypeManager.GetTypeParameterConstraints (target_type);
168                                 if (gc == null)
169                                         return null;
170
171                                 foreach (Type iface in gc.InterfaceConstraints) {
172                                         if (!TypeManager.IsGenericParameter (iface))
173                                                 continue;
174
175                                         if (TypeManager.IsSubclassOf (source_type, iface))
176                                                 return new ClassCast (source, target_type);
177                                 }
178                         }
179 #endif
180                         return null;
181                 }
182
183                 static EmptyExpression MyEmptyExpr;
184                 static public Expression ImplicitReferenceConversion (Expression expr, Type target_type)
185                 {
186                         Type expr_type = expr.Type;
187
188                         if (expr_type == null && expr.eclass == ExprClass.MethodGroup){
189                                 // if we are a method group, emit a warning
190
191                                 expr.Emit (null);
192                         }
193
194                         if (expr_type == TypeManager.void_type)
195                                 return null;
196
197                         if (TypeManager.IsGenericParameter (expr_type))
198                                 return ImplicitTypeParameterConversion (expr, target_type);
199
200                         //
201                         // notice that it is possible to write "ValueType v = 1", the ValueType here
202                         // is an abstract class, and not really a value type, so we apply the same rules.
203                         //
204                         if (target_type == TypeManager.object_type) {
205                                 //
206                                 // A pointer type cannot be converted to object
207                                 //
208                                 if (expr_type.IsPointer)
209                                         return null;
210
211                                 if (TypeManager.IsValueType (expr_type))
212                                         return new BoxedCast (expr, target_type);
213                                 if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type){
214                                         if (expr_type == TypeManager.anonymous_method_type)
215                                                 return null;
216                                         return new EmptyCast (expr, target_type);
217                                 }
218
219                                 return null;
220                         } else if (target_type == TypeManager.value_type) {
221                                 if (TypeManager.IsValueType (expr_type))
222                                         return new BoxedCast (expr, target_type);
223                                 if (expr_type == TypeManager.null_type)
224                                         return new EmptyConstantCast ((Constant)expr, target_type);
225
226                                 return null;
227                         } else if (TypeManager.IsSubclassOf (expr_type, target_type)) {
228                                 //
229                                 // Special case: enumeration to System.Enum.
230                                 // System.Enum is not a value type, it is a class, so we need
231                                 // a boxing conversion
232                                 //
233                                 if (expr_type.IsEnum || TypeManager.IsGenericParameter (expr_type))
234                                         return new BoxedCast (expr, target_type);
235
236                                 return new EmptyCast (expr, target_type);
237                         }
238
239                         // This code is kind of mirrored inside ImplicitStandardConversionExists
240                         // with the small distinction that we only probe there
241                         //
242                         // Always ensure that the code here and there is in sync
243
244                         // from the null type to any reference-type.
245                         if (expr_type == TypeManager.null_type) {
246                                 NullConstant nc = (NullConstant)expr;
247                                 return nc.ConvertImplicitly(target_type);
248                         }
249
250                         // from any class-type S to any interface-type T.
251                         if (target_type.IsInterface) {
252                                 if (target_type != TypeManager.iconvertible_type &&
253                                     expr_type.IsValueType && (expr is Constant) &&
254                                     !(expr is IntLiteral || expr is BoolLiteral ||
255                                       expr is FloatLiteral || expr is DoubleLiteral ||
256                                       expr is LongLiteral || expr is CharLiteral ||
257                                       expr is StringLiteral || expr is DecimalLiteral ||
258                                       expr is UIntLiteral || expr is ULongLiteral)) {
259                                         return null;
260                                 }
261
262                                 if (TypeManager.ImplementsInterface (expr_type, target_type)){
263                                         if (TypeManager.IsGenericParameter (expr_type) || TypeManager.IsValueType (expr_type))
264                                                 return new BoxedCast (expr, target_type);
265                                         else
266                                                 return new EmptyCast (expr, target_type);
267                                 }
268                         }
269
270                         // from any interface type S to interface-type T.
271                         if (expr_type.IsInterface && target_type.IsInterface) {
272                                 if (TypeManager.ImplementsInterface (expr_type, target_type))
273                                         return new EmptyCast (expr, target_type);
274                                 else
275                                         return null;
276                         }
277
278                         // from an array-type S to an array-type of type T
279                         if (expr_type.IsArray && target_type.IsArray) {
280                                 if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
281
282                                         Type expr_element_type = TypeManager.GetElementType (expr_type);
283
284                                         if (MyEmptyExpr == null)
285                                                 MyEmptyExpr = new EmptyExpression ();
286
287                                         MyEmptyExpr.SetType (expr_element_type);
288                                         Type target_element_type = TypeManager.GetElementType (target_type);
289
290                                         if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
291                                                 if (ImplicitStandardConversionExists (MyEmptyExpr,
292                                                                                       target_element_type))
293                                                         return new EmptyCast (expr, target_type);
294                                 }
295                         }
296
297                         // from an array-type to System.Array
298                         if (expr_type.IsArray && target_type == TypeManager.array_type)
299                                 return new EmptyCast (expr, target_type);
300
301                         // from an array-type of type T to IList<T>
302                         if (expr_type.IsArray && Array_To_IList (expr_type, target_type))
303                                 return new EmptyCast (expr, target_type);
304
305                         // from any delegate type to System.Delegate
306                         if ((expr_type == TypeManager.delegate_type || TypeManager.IsDelegateType (expr_type)) &&
307                             target_type == TypeManager.delegate_type)
308                                 return new EmptyCast (expr, target_type);
309
310                         // from any array-type or delegate type into System.ICloneable.
311                         if (expr_type.IsArray ||
312                             expr_type == TypeManager.delegate_type || TypeManager.IsDelegateType (expr_type))
313                                 if (target_type == TypeManager.icloneable_type)
314                                         return new EmptyCast (expr, target_type);
315
316                         // from a generic type definition to a generic instance.
317                         if (TypeManager.IsEqual (expr_type, target_type))
318                                 return new EmptyCast (expr, target_type);
319
320                         return null;
321                 }
322
323                 //
324                 // Tests whether an implicit reference conversion exists between expr_type
325                 // and target_type
326                 //
327                 public static bool ImplicitReferenceConversionExists (Expression expr, Type target_type)
328                 {
329                         if (target_type.IsValueType)
330                                 return false;
331
332                         Type expr_type = expr.Type;
333
334                         if (TypeManager.IsGenericParameter (expr_type))
335                                 return ImplicitTypeParameterConversion (expr, target_type) != null;
336
337                         //
338                         // This is the boxed case.
339                         //
340                         if (target_type == TypeManager.object_type) {
341                                 if (expr_type.IsClass || TypeManager.IsValueType (expr_type) ||
342                                     expr_type.IsInterface || expr_type == TypeManager.enum_type)
343                                         if (target_type != TypeManager.anonymous_method_type)
344                                         return true;
345
346                                 return false;
347                         } else if (TypeManager.IsSubclassOf (expr_type, target_type))
348                                 return true;
349
350                         // Please remember that all code below actually comes
351                         // from ImplicitReferenceConversion so make sure code remains in sync
352
353                         // from any class-type S to any interface-type T.
354                         if (target_type.IsInterface) {
355                                 if (target_type != TypeManager.iconvertible_type &&
356                                     expr_type.IsValueType && (expr is Constant) &&
357                                     !(expr is IntLiteral || expr is BoolLiteral ||
358                                       expr is FloatLiteral || expr is DoubleLiteral ||
359                                       expr is LongLiteral || expr is CharLiteral ||
360                                       expr is StringLiteral || expr is DecimalLiteral ||
361                                       expr is UIntLiteral || expr is ULongLiteral)) {
362                                         return false;
363                                 }
364
365                                 if (TypeManager.ImplementsInterface (expr_type, target_type))
366                                         return true;
367                         }
368
369                         // from any interface type S to interface-type T.
370                         if (expr_type.IsInterface && target_type.IsInterface)
371                                 if (TypeManager.ImplementsInterface (expr_type, target_type))
372                                         return true;
373
374                         // from an array-type S to an array-type of type T
375                         if (expr_type.IsArray && target_type.IsArray) {
376                                 if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
377
378                                         Type expr_element_type = expr_type.GetElementType ();
379
380                                         if (MyEmptyExpr == null)
381                                                 MyEmptyExpr = new EmptyExpression ();
382
383                                         MyEmptyExpr.SetType (expr_element_type);
384                                         Type target_element_type = TypeManager.GetElementType (target_type);
385
386                                         if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
387                                                 if (ImplicitStandardConversionExists (MyEmptyExpr,
388                                                                                       target_element_type))
389                                                         return true;
390                                 }
391                         }
392
393                         // from an array-type to System.Array
394                         if (expr_type.IsArray && (target_type == TypeManager.array_type))
395                                 return true;
396
397                         // from an array-type of type T to IList<T>
398                         if (expr_type.IsArray && Array_To_IList (expr_type, target_type))
399                                 return true;
400
401                         // from any delegate type to System.Delegate
402                         if ((expr_type == TypeManager.delegate_type || TypeManager.IsDelegateType (expr_type)) &&
403                             target_type == TypeManager.delegate_type)
404                                 if (target_type.IsAssignableFrom (expr_type))
405                                         return true;
406
407                         // from any array-type or delegate type into System.ICloneable.
408                         if (expr_type.IsArray ||
409                             expr_type == TypeManager.delegate_type || TypeManager.IsDelegateType (expr_type))
410                                 if (target_type == TypeManager.icloneable_type)
411                                         return true;
412
413                         // from the null type to any reference-type.
414                         if (expr_type == TypeManager.null_type){
415                                 if (target_type.IsPointer)
416                                         return true;
417
418                                 if (!target_type.IsValueType)
419                                         return true;
420                         }
421
422                         // from a generic type definition to a generic instance.
423                         if (TypeManager.IsEqual (expr_type, target_type))
424                                 return true;
425
426                         return false;
427                 }
428
429                 /// <summary>
430                 ///   Implicit Numeric Conversions.
431                 ///
432                 ///   expr is the expression to convert, returns a new expression of type
433                 ///   target_type or null if an implicit conversion is not possible.
434                 /// </summary>
435                 static public Expression ImplicitNumericConversion (Expression expr,
436                                                                     Type target_type)
437                 {
438                         Type expr_type = expr.Type;
439
440                         //
441                         // Attempt to do the implicit constant expression conversions
442
443                         if (expr is Constant){
444                                 if (expr is IntConstant){
445                                         Expression e;
446
447                                         e = TryImplicitIntConversion (target_type, (IntConstant) expr);
448
449                                         if (e != null)
450                                                 return e;
451                                 } else if (expr is LongConstant && target_type == TypeManager.uint64_type){
452                                         //
453                                         // Try the implicit constant expression conversion
454                                         // from long to ulong, instead of a nice routine,
455                                         // we just inline it
456                                         //
457                                         long v = ((LongConstant) expr).Value;
458                                         if (v >= 0)
459                                                 return new ULongConstant ((ulong) v, expr.Location);
460                                 }
461                         }
462
463                         Type real_target_type = target_type;
464
465                         if (expr_type == TypeManager.sbyte_type){
466                                 //
467                                 // From sbyte to short, int, long, float, double, decimal
468                                 //
469                                 if (real_target_type == TypeManager.int32_type)
470                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
471                                 if (real_target_type == TypeManager.int64_type)
472                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
473                                 if (real_target_type == TypeManager.double_type)
474                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
475                                 if (real_target_type == TypeManager.float_type)
476                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
477                                 if (real_target_type == TypeManager.short_type)
478                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
479                                 if (real_target_type == TypeManager.decimal_type)
480                                         return new CastToDecimal (expr);
481                         } else if (expr_type == TypeManager.byte_type){
482                                 //
483                                 // From byte to short, ushort, int, uint, long, ulong, float, double, decimal
484                                 //
485                                 if ((real_target_type == TypeManager.short_type) ||
486                                     (real_target_type == TypeManager.ushort_type) ||
487                                     (real_target_type == TypeManager.int32_type) ||
488                                     (real_target_type == TypeManager.uint32_type))
489                                         return new EmptyCast (expr, target_type);
490
491                                 if (real_target_type == TypeManager.uint64_type)
492                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
493                                 if (real_target_type == TypeManager.int64_type)
494                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
495                                 if (real_target_type == TypeManager.float_type)
496                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
497                                 if (real_target_type == TypeManager.double_type)
498                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
499                                 if (real_target_type == TypeManager.decimal_type)
500                                         return new CastToDecimal (expr);
501
502                         } else if (expr_type == TypeManager.short_type){
503                                 //
504                                 // From short to int, long, float, double, decimal
505                                 //
506                                 if (real_target_type == TypeManager.int32_type)
507                                         return new EmptyCast (expr, target_type);
508                                 if (real_target_type == TypeManager.int64_type)
509                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
510                                 if (real_target_type == TypeManager.double_type)
511                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
512                                 if (real_target_type == TypeManager.float_type)
513                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
514                                 if (real_target_type == TypeManager.decimal_type)
515                                         return new CastToDecimal (expr);
516
517                         } else if (expr_type == TypeManager.ushort_type){
518                                 //
519                                 // From ushort to int, uint, long, ulong, float, double, decimal
520                                 //
521                                 if (real_target_type == TypeManager.uint32_type)
522                                         return new EmptyCast (expr, target_type);
523
524                                 if (real_target_type == TypeManager.uint64_type)
525                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
526                                 if (real_target_type == TypeManager.int32_type)
527                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
528                                 if (real_target_type == TypeManager.int64_type)
529                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
530                                 if (real_target_type == TypeManager.double_type)
531                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
532                                 if (real_target_type == TypeManager.float_type)
533                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
534                                 if (real_target_type == TypeManager.decimal_type)
535                                         return new CastToDecimal (expr);
536                         } else if (expr_type == TypeManager.int32_type){
537                                 //
538                                 // From int to long, float, double, decimal
539                                 //
540                                 if (real_target_type == TypeManager.int64_type)
541                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
542                                 if (real_target_type == TypeManager.double_type)
543                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
544                                 if (real_target_type == TypeManager.float_type)
545                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
546                                 if (real_target_type == TypeManager.decimal_type)
547                                         return new CastToDecimal (expr);
548                         } else if (expr_type == TypeManager.uint32_type){
549                                 //
550                                 // From uint to long, ulong, float, double, decimal
551                                 //
552                                 if (real_target_type == TypeManager.int64_type)
553                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
554                                 if (real_target_type == TypeManager.uint64_type)
555                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
556                                 if (real_target_type == TypeManager.double_type)
557                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
558                                                                OpCodes.Conv_R8);
559                                 if (real_target_type == TypeManager.float_type)
560                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
561                                                                OpCodes.Conv_R4);
562                                 if (real_target_type == TypeManager.decimal_type)
563                                         return new CastToDecimal (expr);
564                         } else if (expr_type == TypeManager.int64_type){
565                                 //
566                                 // From long/ulong to float, double
567                                 //
568                                 if (real_target_type == TypeManager.double_type)
569                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
570                                 if (real_target_type == TypeManager.float_type)
571                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
572                                 if (real_target_type == TypeManager.decimal_type)
573                                         return new CastToDecimal (expr);
574                         } else if (expr_type == TypeManager.uint64_type){
575                                 //
576                                 // From ulong to float, double
577                                 //
578                                 if (real_target_type == TypeManager.double_type)
579                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
580                                                                OpCodes.Conv_R8);
581                                 if (real_target_type == TypeManager.float_type)
582                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
583                                                                OpCodes.Conv_R4);
584                                 if (real_target_type == TypeManager.decimal_type)
585                                         return new CastToDecimal (expr);
586                         } else if (expr_type == TypeManager.char_type){
587                                 //
588                                 // From char to ushort, int, uint, long, ulong, float, double, decimal
589                                 //
590                                 if ((real_target_type == TypeManager.ushort_type) ||
591                                     (real_target_type == TypeManager.int32_type) ||
592                                     (real_target_type == TypeManager.uint32_type))
593                                         return new EmptyCast (expr, target_type);
594                                 if (real_target_type == TypeManager.uint64_type)
595                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
596                                 if (real_target_type == TypeManager.int64_type)
597                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
598                                 if (real_target_type == TypeManager.float_type)
599                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
600                                 if (real_target_type == TypeManager.double_type)
601                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
602                                 if (real_target_type == TypeManager.decimal_type)
603                                         return new CastToDecimal (expr);
604                         } else if (expr_type == TypeManager.float_type){
605                                 //
606                                 // float to double
607                                 //
608                                 if (real_target_type == TypeManager.double_type)
609                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
610                         }
611
612                         return null;
613                 }
614
615                 /// <summary>
616                 ///  Same as ImplicitStandardConversionExists except that it also looks at
617                 ///  implicit user defined conversions - needed for overload resolution
618                 /// </summary>
619                 public static bool ImplicitConversionExists (EmitContext ec, Expression expr, Type target_type)
620                 {
621 #if GMCS_SOURCE
622                         if (expr is NullLiteral) {
623                                 if (TypeManager.IsGenericParameter (target_type))
624                                         return TypeParameter_to_Null (target_type);
625
626                                 if (TypeManager.IsNullableType (target_type))
627                                         return true;
628                         }
629 #endif
630                         if (ImplicitStandardConversionExists (expr, target_type))
631                                 return true;
632
633                         return ImplicitUserConversion (ec, expr, target_type, Location.Null) != null;
634                 }
635
636                 public static bool ImplicitUserConversionExists (EmitContext ec, Type source, Type target)
637                 {
638                         return ImplicitUserConversion (ec, new EmptyExpression (source), target, Location.Null) != null;
639                 }
640
641                 /// <summary>
642                 ///  Determines if a standard implicit conversion exists from
643                 ///  expr_type to target_type
644                 ///
645                 ///  ec should point to a real EmitContext if expr.Type is TypeManager.anonymous_method_type.
646                 /// </summary>
647                 public static bool ImplicitStandardConversionExists (Expression expr, Type target_type)
648                 {
649                         Type expr_type = expr.Type;
650 #if GMCS_SOURCE
651                         if (TypeManager.IsNullableType (target_type)) {
652                                 // if implicit standard conversion S -> T exists, S -> T? and S? -> T? also exists
653                                 target_type = TypeManager.GetTypeArguments (target_type) [0];
654
655                                 // S? -> T?
656                                 if (TypeManager.IsNullableType (expr_type)) {
657                                         EmptyExpression new_expr = EmptyExpression.Grab ();
658                                         new_expr.SetType (TypeManager.GetTypeArguments (expr_type) [0]);
659                                         bool retval = ImplicitStandardConversionExists (new_expr, target_type);
660                                         EmptyExpression.Release (new_expr);
661                                         return retval;
662                                 }
663                         }
664 #endif
665                         if (expr_type == TypeManager.void_type)
666                                 return false;
667
668                         //Console.WriteLine ("Expr is {0}", expr);
669                         //Console.WriteLine ("{0} -> {1} ?", expr_type, target_type);
670                         if (TypeManager.IsEqual (expr_type, target_type))
671                                 return true;
672
673
674                         // First numeric conversions
675
676                         if (expr_type == TypeManager.sbyte_type){
677                                 //
678                                 // From sbyte to short, int, long, float, double, decimal
679                                 //
680                                 if ((target_type == TypeManager.int32_type) ||
681                                     (target_type == TypeManager.int64_type) ||
682                                     (target_type == TypeManager.double_type) ||
683                                     (target_type == TypeManager.float_type)  ||
684                                     (target_type == TypeManager.short_type) ||
685                                     (target_type == TypeManager.decimal_type))
686                                         return true;
687
688                         } else if (expr_type == TypeManager.byte_type){
689                                 //
690                                 // From byte to short, ushort, int, uint, long, ulong, float, double, decimal
691                                 //
692                                 if ((target_type == TypeManager.short_type) ||
693                                     (target_type == TypeManager.ushort_type) ||
694                                     (target_type == TypeManager.int32_type) ||
695                                     (target_type == TypeManager.uint32_type) ||
696                                     (target_type == TypeManager.uint64_type) ||
697                                     (target_type == TypeManager.int64_type) ||
698                                     (target_type == TypeManager.float_type) ||
699                                     (target_type == TypeManager.double_type) ||
700                                     (target_type == TypeManager.decimal_type))
701                                         return true;
702
703                         } else if (expr_type == TypeManager.short_type){
704                                 //
705                                 // From short to int, long, double, float, decimal 
706                                 //
707                                 if ((target_type == TypeManager.int32_type) ||
708                                     (target_type == TypeManager.int64_type) ||
709                                     (target_type == TypeManager.double_type) ||
710                                     (target_type == TypeManager.float_type) ||
711                                     (target_type == TypeManager.decimal_type))
712                                         return true;
713
714                         } else if (expr_type == TypeManager.ushort_type){
715                                 //
716                                 // From ushort to int, uint, long, ulong, double, float, decimal
717                                 //
718                                 if ((target_type == TypeManager.uint32_type) ||
719                                     (target_type == TypeManager.uint64_type) ||
720                                     (target_type == TypeManager.int32_type) ||
721                                     (target_type == TypeManager.int64_type) ||
722                                     (target_type == TypeManager.double_type) ||
723                                     (target_type == TypeManager.float_type) ||
724                                     (target_type == TypeManager.decimal_type))
725                                         return true;
726
727                         } else if (expr_type == TypeManager.int32_type){
728                                 //
729                                 // From int to long, double, float, decimal
730                                 //
731                                 if ((target_type == TypeManager.int64_type) ||
732                                     (target_type == TypeManager.double_type) ||
733                                     (target_type == TypeManager.float_type) ||
734                                     (target_type == TypeManager.decimal_type))
735                                         return true;
736
737                         } else if (expr_type == TypeManager.uint32_type){
738                                 //
739                                 // From uint to long, ulong, double, float, decimal
740                                 //
741                                 if ((target_type == TypeManager.int64_type) ||
742                                     (target_type == TypeManager.uint64_type) ||
743                                     (target_type == TypeManager.double_type) ||
744                                     (target_type == TypeManager.float_type) ||
745                                     (target_type == TypeManager.decimal_type))
746                                         return true;
747
748                         } else if ((expr_type == TypeManager.uint64_type) ||
749                                    (expr_type == TypeManager.int64_type)) {
750                                 //
751                                 // From long/ulong to double, float, decimal
752                                 //
753                                 if ((target_type == TypeManager.double_type) ||
754                                     (target_type == TypeManager.float_type) ||
755                                     (target_type == TypeManager.decimal_type))
756                                         return true;
757
758                         } else if (expr_type == TypeManager.char_type){
759                                 //
760                                 // From char to ushort, int, uint, ulong, long, float, double, decimal
761                                 //
762                                 if ((target_type == TypeManager.ushort_type) ||
763                                     (target_type == TypeManager.int32_type) ||
764                                     (target_type == TypeManager.uint32_type) ||
765                                     (target_type == TypeManager.uint64_type) ||
766                                     (target_type == TypeManager.int64_type) ||
767                                     (target_type == TypeManager.float_type) ||
768                                     (target_type == TypeManager.double_type) ||
769                                     (target_type == TypeManager.decimal_type))
770                                         return true;
771
772                         } else if (expr_type == TypeManager.float_type){
773                                 //
774                                 // float to double
775                                 //
776                                 if (target_type == TypeManager.double_type)
777                                         return true;
778                         }
779
780                         if (expr.eclass == ExprClass.MethodGroup){
781                                 if (TypeManager.IsDelegateType (target_type) && RootContext.Version != LanguageVersion.ISO_1){
782                                         MethodGroupExpr mg = expr as MethodGroupExpr;
783                                         if (mg != null){
784                                                 return DelegateCreation.ImplicitStandardConversionExists (mg, target_type) != null;
785                                         }
786                                 }
787                         }
788
789                         if (ImplicitReferenceConversionExists (expr, target_type))
790                                 return true;
791
792                         //
793                         // Implicit Constant Expression Conversions
794                         //
795                         if (expr is IntConstant){
796                                 int value = ((IntConstant) expr).Value;
797
798                                 if (target_type == TypeManager.sbyte_type){
799                                         if (value >= SByte.MinValue && value <= SByte.MaxValue)
800                                                 return true;
801                                 } else if (target_type == TypeManager.byte_type){
802                                         if (value >= 0 && value <= Byte.MaxValue)
803                                                 return true;
804                                 } else if (target_type == TypeManager.short_type){
805                                         if (value >= Int16.MinValue && value <= Int16.MaxValue)
806                                                 return true;
807                                 } else if (target_type == TypeManager.ushort_type){
808                                         if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
809                                                 return true;
810                                 } else if (target_type == TypeManager.uint32_type){
811                                         if (value >= 0)
812                                                 return true;
813                                 } else if (target_type == TypeManager.uint64_type){
814                                          //
815                                          // we can optimize this case: a positive int32
816                                          // always fits on a uint64.  But we need an opcode
817                                          // to do it.
818                                          //
819                                         if (value >= 0)
820                                                 return true;
821                                 }
822
823                                 if (value == 0 && expr is IntLiteral && TypeManager.IsEnumType (target_type))
824                                         return true;
825                         }
826
827                         if (expr is LongConstant && target_type == TypeManager.uint64_type){
828                                 //
829                                 // Try the implicit constant expression conversion
830                                 // from long to ulong, instead of a nice routine,
831                                 // we just inline it
832                                 //
833                                 long v = ((LongConstant) expr).Value;
834                                 if (v >= 0)
835                                         return true;
836                         }
837
838                         if ((target_type == TypeManager.enum_type ||
839                              target_type.IsSubclassOf (TypeManager.enum_type)) &&
840                              expr is IntLiteral){
841                                 IntLiteral i = (IntLiteral) expr;
842
843                                 if (i.Value == 0)
844                                         return true;
845                         }
846
847                         //
848                         // If `expr_type' implements `target_type' (which is an iface)
849                         // see TryImplicitIntConversion
850                         //
851                         if (target_type.IsInterface && target_type.IsAssignableFrom (expr_type))
852                                 return true;
853
854                         if (target_type == TypeManager.void_ptr_type && expr_type.IsPointer)
855                                 return true;
856
857                         if (expr_type == TypeManager.anonymous_method_type){
858                                 if (!TypeManager.IsDelegateType (target_type))
859                                         return false;
860
861                                 AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
862                                 return ame.ImplicitStandardConversionExists (target_type);
863                         }
864
865                         return false;
866                 }
867
868                 /// <summary>
869                 ///  Finds "most encompassed type" according to the spec (13.4.2)
870                 ///  amongst the methods in the MethodGroupExpr
871                 /// </summary>
872                 static Type FindMostEncompassedType (ArrayList types)
873                 {
874                         Type best = null;
875
876                         if (types.Count == 0)
877                                 return null;
878
879                         if (types.Count == 1)
880                                 return (Type) types [0];
881
882                         EmptyExpression expr = EmptyExpression.Grab ();
883
884                         foreach (Type t in types) {
885                                 if (best == null) {
886                                         best = t;
887                                         continue;
888                                 }
889
890                                 expr.SetType (t);
891                                 if (ImplicitStandardConversionExists (expr, best))
892                                         best = t;
893                         }
894
895                         expr.SetType (best);
896                         foreach (Type t in types) {
897                                 if (best == t)
898                                         continue;
899                                 if (!ImplicitStandardConversionExists (expr, t)) {
900                                         best = null;
901                                         break;
902                                 }
903                         }
904
905                         EmptyExpression.Release (expr);
906
907                         return best;
908                 }
909
910                 /// <summary>
911                 ///  Finds "most encompassing type" according to the spec (13.4.2)
912                 ///  amongst the types in the given set
913                 /// </summary>
914                 static Type FindMostEncompassingType (ArrayList types)
915                 {
916                         Type best = null;
917
918                         if (types.Count == 0)
919                                 return null;
920
921                         if (types.Count == 1)
922                                 return (Type) types [0];
923
924                         EmptyExpression expr = EmptyExpression.Grab ();
925
926                         foreach (Type t in types) {
927                                 if (best == null) {
928                                         best = t;
929                                         continue;
930                                 }
931
932                                 expr.SetType (best);
933                                 if (ImplicitStandardConversionExists (expr, t))
934                                         best = t;
935                         }
936
937                         foreach (Type t in types) {
938                                 if (best == t)
939                                         continue;
940                                 expr.SetType (t);
941                                 if (!ImplicitStandardConversionExists (expr, best)) {
942                                         best = null;
943                                         break;
944                                 }
945                         }
946
947                         EmptyExpression.Release (expr);
948
949                         return best;
950                 }
951
952                 /// <summary>
953                 ///   Finds the most specific source Sx according to the rules of the spec (13.4.4)
954                 ///   by making use of FindMostEncomp* methods. Applies the correct rules separately
955                 ///   for explicit and implicit conversion operators.
956                 /// </summary>
957                 static public Type FindMostSpecificSource (IList list,
958                                                            Expression source, bool apply_explicit_conv_rules)
959                 {
960                         ArrayList src_types_set = new ArrayList ();
961
962                         //
963                         // If any operator converts from S then Sx = S
964                         //
965                         Type source_type = source.Type;
966                         foreach (MethodBase mb in list){
967                                 ParameterData pd = TypeManager.GetParameterData (mb);
968                                 Type param_type = pd.ParameterType (0);
969
970                                 if (param_type == source_type)
971                                         return param_type;
972
973                                 src_types_set.Add (param_type);
974                         }
975
976                         //
977                         // Explicit Conv rules
978                         //
979                         if (apply_explicit_conv_rules) {
980                                 ArrayList candidate_set = new ArrayList ();
981
982                                 foreach (Type param_type in src_types_set){
983                                         if (ImplicitStandardConversionExists (source, param_type))
984                                                 candidate_set.Add (param_type);
985                                 }
986
987                                 if (candidate_set.Count != 0)
988                                         return FindMostEncompassedType (candidate_set);
989                         }
990
991                         //
992                         // Final case
993                         //
994                         if (apply_explicit_conv_rules)
995                                 return FindMostEncompassingType (src_types_set);
996                         else
997                                 return FindMostEncompassedType (src_types_set);
998                 }
999
1000                 /// <summary>
1001                 ///  Finds the most specific target Tx according to section 13.4.4
1002                 /// </summary>
1003                 static public Type FindMostSpecificTarget (IList list,
1004                                                            Type target, bool apply_explicit_conv_rules)
1005                 {
1006                         ArrayList tgt_types_set = new ArrayList ();
1007
1008                         //
1009                         // If any operator converts to T then Tx = T
1010                         //
1011                         foreach (MethodInfo mi in list){
1012                                 Type ret_type = mi.ReturnType;
1013                                 if (ret_type == target)
1014                                         return ret_type;
1015
1016                                 tgt_types_set.Add (ret_type);
1017                         }
1018
1019                         //
1020                         // Explicit conv rules
1021                         //
1022                         if (apply_explicit_conv_rules) {
1023                                 ArrayList candidate_set = new ArrayList ();
1024
1025                                 EmptyExpression expr = EmptyExpression.Grab ();
1026
1027                                 foreach (Type ret_type in tgt_types_set){
1028                                         expr.SetType (ret_type);
1029
1030                                         if (ImplicitStandardConversionExists (expr, target))
1031                                                 candidate_set.Add (ret_type);
1032                                 }
1033
1034                                 EmptyExpression.Release (expr);
1035
1036                                 if (candidate_set.Count != 0)
1037                                         return FindMostEncompassingType (candidate_set);
1038                         }
1039
1040                         //
1041                         // Okay, final case !
1042                         //
1043                         if (apply_explicit_conv_rules)
1044                                 return FindMostEncompassedType (tgt_types_set);
1045                         else
1046                                 return FindMostEncompassingType (tgt_types_set);
1047                 }
1048
1049                 /// <summary>
1050                 ///  User-defined Implicit conversions
1051                 /// </summary>
1052                 static public Expression ImplicitUserConversion (EmitContext ec, Expression source,
1053                                                                  Type target, Location loc)
1054                 {
1055                         return UserDefinedConversion (ec, source, target, loc, false);
1056                 }
1057
1058                 /// <summary>
1059                 ///  User-defined Explicit conversions
1060                 /// </summary>
1061                 static public Expression ExplicitUserConversion (EmitContext ec, Expression source,
1062                                                                  Type target, Location loc)
1063                 {
1064                         return UserDefinedConversion (ec, source, target, loc, true);
1065                 }
1066
1067                 static void AddConversionOperators (ArrayList list,
1068                                                     Expression source, Type target_type,
1069                                                     bool look_for_explicit,
1070                                                     MethodGroupExpr mg)
1071                 {
1072                         if (mg == null)
1073                                 return;
1074
1075                         Type source_type = source.Type;
1076                         EmptyExpression expr = EmptyExpression.Grab ();
1077                         foreach (MethodInfo m in mg.Methods) {
1078                                 ParameterData pd = TypeManager.GetParameterData (m);
1079                                 Type return_type = m.ReturnType;
1080                                 Type arg_type = pd.ParameterType (0);
1081
1082                                 if (source_type != arg_type) {
1083                                         if (!ImplicitStandardConversionExists (source, arg_type)) {
1084                                                 if (!look_for_explicit)
1085                                                         continue;
1086                                                 expr.SetType (arg_type);
1087                                                 if (!ImplicitStandardConversionExists (expr, source_type))
1088                                                         continue;
1089                                         }
1090                                 }
1091
1092                                 if (target_type != return_type) {
1093                                         expr.SetType (return_type);
1094                                         if (!ImplicitStandardConversionExists (expr, target_type)) {
1095                                                 if (!look_for_explicit)
1096                                                         continue;
1097                                                 expr.SetType (target_type);
1098                                                 if (!ImplicitStandardConversionExists (expr, return_type))
1099                                                         continue;
1100                                         }
1101                                 }
1102
1103                                 list.Add (m);
1104                         }
1105
1106                         EmptyExpression.Release (expr);
1107                 }
1108
1109                 /// <summary>
1110                 ///   Compute the user-defined conversion operator from source_type to target_type.
1111                 ///   `look_for_explicit' controls whether we should also include the list of explicit operators
1112                 /// </summary>
1113                 static MethodInfo GetConversionOperator (Type container_type, Expression source, Type target_type, bool look_for_explicit)
1114                 {
1115                         ArrayList ops = new ArrayList (4);
1116
1117                         Type source_type = source.Type;
1118
1119                         if (source_type != TypeManager.decimal_type) {
1120                                 AddConversionOperators (ops, source, target_type, look_for_explicit,
1121                                         Expression.MethodLookup (container_type, source_type, "op_Implicit", Location.Null) as MethodGroupExpr);
1122                                 if (look_for_explicit) {
1123                                         AddConversionOperators (ops, source, target_type, look_for_explicit,
1124                                                 Expression.MethodLookup (
1125                                                         container_type, source_type, "op_Explicit", Location.Null) as MethodGroupExpr);
1126                                 }
1127                         }
1128
1129                         if (target_type != TypeManager.decimal_type) {
1130                                 AddConversionOperators (ops, source, target_type, look_for_explicit,
1131                                         Expression.MethodLookup (container_type, target_type, "op_Implicit", Location.Null) as MethodGroupExpr);
1132                                 if (look_for_explicit) {
1133                                         AddConversionOperators (ops, source, target_type, look_for_explicit,
1134                                                 Expression.MethodLookup (
1135                                                         container_type, target_type, "op_Explicit", Location.Null) as MethodGroupExpr);
1136                                 }
1137                         }
1138
1139                         if (ops.Count == 0)
1140                                 return null;
1141
1142                         Type most_specific_source = FindMostSpecificSource (ops, source, look_for_explicit);
1143                         if (most_specific_source == null)
1144                                 return null;
1145
1146                         Type most_specific_target = FindMostSpecificTarget (ops, target_type, look_for_explicit);
1147                         if (most_specific_target == null)
1148                                 return null;
1149
1150                         MethodInfo method = null;
1151
1152                         foreach (MethodInfo m in ops) {
1153                                 if (m.ReturnType != most_specific_target)
1154                                         continue;
1155                                 if (TypeManager.GetParameterData (m).ParameterType (0) != most_specific_source)
1156                                         continue;
1157                                 // Ambiguous: more than one conversion operator satisfies the signature.
1158                                 if (method != null)
1159                                         return null;
1160                                 method = m;
1161                         }
1162
1163                         return method;
1164                 }
1165
1166                 static DoubleHash explicit_conv = new DoubleHash (100);
1167                 static DoubleHash implicit_conv = new DoubleHash (100);
1168
1169                 /// <summary>
1170                 ///   User-defined conversions
1171                 /// </summary>
1172                 static public Expression UserDefinedConversion (EmitContext ec, Expression source,
1173                                                                 Type target, Location loc,
1174                                                                 bool look_for_explicit)
1175                 {
1176                         Type source_type = source.Type;
1177                         MethodInfo method = null;
1178
1179                         object o;
1180                         DoubleHash hash = look_for_explicit ? explicit_conv : implicit_conv;
1181
1182                         if (!(source is Constant) && hash.Lookup (source_type, target, out o)) {
1183                                 method = (MethodInfo) o;
1184                         } else {
1185                                 method = GetConversionOperator (null, source, target, look_for_explicit);
1186                                 if (!(source is Constant))
1187                                         hash.Insert (source_type, target, method);
1188                         }
1189
1190                         if (method == null)
1191                                 return null;
1192
1193                         Type most_specific_source = TypeManager.GetParameterData (method).ParameterType (0);
1194
1195                         //
1196                         // This will do the conversion to the best match that we
1197                         // found.  Now we need to perform an implict standard conversion
1198                         // if the best match was not the type that we were requested
1199                         // by target.
1200                         //
1201                         if (look_for_explicit)
1202                                 source = ExplicitConversionStandard (ec, source, most_specific_source, loc);
1203                         else
1204                                 source = ImplicitConversionStandard (ec, source, most_specific_source, loc);
1205
1206                         if (source == null)
1207                                 return null;
1208
1209                         Expression e;
1210                         e =  new UserCast (method, source, loc);
1211                         if (e.Type != target){
1212                                 if (!look_for_explicit)
1213                                         e = ImplicitConversionStandard (ec, e, target, loc);
1214                                 else
1215                                         e = ExplicitConversionStandard (ec, e, target, loc);
1216                         }
1217
1218                         return e;
1219                 }
1220
1221                 /// <summary>
1222                 ///   Converts implicitly the resolved expression `expr' into the
1223                 ///   `target_type'.  It returns a new expression that can be used
1224                 ///   in a context that expects a `target_type'.
1225                 /// </summary>
1226                 static public Expression ImplicitConversion (EmitContext ec, Expression expr,
1227                                                              Type target_type, Location loc)
1228                 {
1229                         Expression e;
1230
1231                         if (target_type == null)
1232                                 throw new Exception ("Target type is null");
1233
1234                         e = ImplicitConversionStandard (ec, expr, target_type, loc);
1235                         if (e != null)
1236                                 return e;
1237
1238                         e = ImplicitUserConversion (ec, expr, target_type, loc);
1239                         if (e != null)
1240                                 return e;
1241
1242                         return null;
1243                 }
1244
1245
1246                 /// <summary>
1247                 ///   Attempts to apply the `Standard Implicit
1248                 ///   Conversion' rules to the expression `expr' into
1249                 ///   the `target_type'.  It returns a new expression
1250                 ///   that can be used in a context that expects a
1251                 ///   `target_type'.
1252                 ///
1253                 ///   This is different from `ImplicitConversion' in that the
1254                 ///   user defined implicit conversions are excluded.
1255                 /// </summary>
1256                 static public Expression ImplicitConversionStandard (EmitContext ec, Expression expr,
1257                                                                      Type target_type, Location loc)
1258                 {
1259                         Type expr_type = expr.Type;
1260                         Expression e;
1261 #if GMCS_SOURCE
1262                         // TODO: refactor to be a part of constant infrastructure
1263                         if (expr is NullLiteral) {
1264                             if (TypeManager.IsNullableType (target_type))
1265                                 return new Nullable.NullableLiteral (target_type, loc);
1266                         }
1267
1268                         if (TypeManager.IsNullableType (target_type)) {
1269                                 Type target = TypeManager.GetTypeArguments (target_type) [0];
1270
1271                                 if (TypeManager.IsNullableType (expr.Type)) {
1272                                         e = new Nullable.LiftedConversion (
1273                                                 expr, target_type, false, false, loc).Resolve (ec);
1274                                         if (e != null)
1275                                                 return e;
1276                                 } else {
1277                                         e = ImplicitConversion (ec, expr, target, loc);
1278                                         if (e != null)
1279                                                 return Nullable.Wrap.Create (e, ec);
1280                                 }
1281                         }
1282 #endif
1283                         if (expr.eclass == ExprClass.MethodGroup){
1284                                 if (!TypeManager.IsDelegateType (target_type)){
1285                                         return null;
1286                                 }
1287
1288                                 //
1289                                 // Only allow anonymous method conversions on post ISO_1
1290                                 //
1291                                 if (RootContext.Version != LanguageVersion.ISO_1){
1292                                         MethodGroupExpr mg = expr as MethodGroupExpr;
1293                                         if (mg != null)
1294                                                 return ImplicitDelegateCreation.Create (
1295                                                         ec, mg, target_type, loc);
1296                                 }
1297                         }
1298
1299                         if (expr_type.Equals (target_type) && !TypeManager.IsNullType (expr_type))
1300                                 return expr;
1301
1302                         e = ImplicitNumericConversion (expr, target_type);
1303                         if (e != null)
1304                                 return e;
1305
1306                         e = ImplicitReferenceConversion (expr, target_type);
1307                         if (e != null)
1308                                 return e;
1309
1310                         if (TypeManager.IsEnumType (target_type) && expr is IntLiteral){
1311                                 IntLiteral i = (IntLiteral) expr;
1312
1313                                 if (i.Value == 0)
1314                                         return new EnumConstant ((Constant) expr, target_type);
1315                         }
1316
1317                         if (ec.InUnsafe) {
1318                                 if (expr_type.IsPointer){
1319                                         if (target_type == TypeManager.void_ptr_type)
1320                                                 return new EmptyCast (expr, target_type);
1321
1322                                         //
1323                                         // yep, comparing pointer types cant be done with
1324                                         // t1 == t2, we have to compare their element types.
1325                                         //
1326                                         if (target_type.IsPointer){
1327                                                 if (TypeManager.GetElementType(target_type) == TypeManager.GetElementType(expr_type))
1328                                                         return expr;
1329
1330                                                 //return null;
1331                                         }
1332                                 }
1333
1334                                 if (expr_type == TypeManager.null_type && target_type.IsPointer)
1335                                         return new EmptyCast (NullPointer.Null, target_type);
1336                         }
1337
1338                         if (expr_type == TypeManager.anonymous_method_type){
1339                                 AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
1340
1341                                 int errors = Report.Errors;
1342
1343                                 Expression conv = ame.Compatible (ec, target_type);
1344                                 if (conv != null)
1345                                         return conv;
1346                                 
1347                                 //
1348                                 // We return something instead of null, to avoid
1349                                 // the duplicate error, since am.Compatible would have
1350                                 // reported that already
1351                                 //
1352                                 if (errors != Report.Errors)
1353                                         return new EmptyCast (expr, target_type);
1354                         }
1355
1356                         return null;
1357                 }
1358
1359                 /// <summary>
1360                 ///   Attempts to perform an implicit constant conversion of the IntConstant
1361                 ///   into a different data type using casts (See Implicit Constant
1362                 ///   Expression Conversions)
1363                 /// </summary>
1364                 static public Expression TryImplicitIntConversion (Type target_type, IntConstant ic)
1365                 {
1366                         int value = ic.Value;
1367
1368                         if (target_type == TypeManager.sbyte_type){
1369                                 if (value >= SByte.MinValue && value <= SByte.MaxValue)
1370                                         return new SByteConstant ((sbyte) value, ic.Location);
1371                         } else if (target_type == TypeManager.byte_type){
1372                                 if (value >= Byte.MinValue && value <= Byte.MaxValue)
1373                                         return new ByteConstant ((byte) value, ic.Location);
1374                         } else if (target_type == TypeManager.short_type){
1375                                 if (value >= Int16.MinValue && value <= Int16.MaxValue)
1376                                         return new ShortConstant ((short) value, ic.Location);
1377                         } else if (target_type == TypeManager.ushort_type){
1378                                 if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
1379                                         return new UShortConstant ((ushort) value, ic.Location);
1380                         } else if (target_type == TypeManager.uint32_type){
1381                                 if (value >= 0)
1382                                         return new UIntConstant ((uint) value, ic.Location);
1383                         } else if (target_type == TypeManager.uint64_type){
1384                                 //
1385                                 // we can optimize this case: a positive int32
1386                                 // always fits on a uint64.  But we need an opcode
1387                                 // to do it.
1388                                 //
1389                                 if (value >= 0)
1390                                         return new ULongConstant ((ulong) value, ic.Location);
1391                         } else if (target_type == TypeManager.double_type)
1392                                 return new DoubleConstant ((double) value, ic.Location);
1393                         else if (target_type == TypeManager.float_type)
1394                                 return new FloatConstant ((float) value, ic.Location);
1395
1396                         if (value == 0 && ic is IntLiteral && TypeManager.IsEnumType (target_type)){
1397                                 Type underlying = TypeManager.EnumToUnderlying (target_type);
1398                                 Constant e = (Constant) ic;
1399
1400                                 //
1401                                 // Possibly, we need to create a different 0 literal before passing
1402                                 // to EnumConstant
1403                                 //
1404                                 if (underlying == TypeManager.int64_type)
1405                                         e = new LongLiteral (0, ic.Location);
1406                                 else if (underlying == TypeManager.uint64_type)
1407                                         e = new ULongLiteral (0, ic.Location);
1408
1409                                 return new EnumConstant (e, target_type);
1410                         }
1411
1412                         //
1413                         // If `target_type' is an interface and the type of `ic' implements the interface
1414                         // e.g. target_type is IComparable, IConvertible, IFormattable
1415                         //
1416                         if (target_type.IsInterface && target_type.IsAssignableFrom (ic.Type))
1417                                 return new BoxedCast (ic, target_type);
1418
1419                         return null;
1420                 }
1421
1422                 /// <summary>
1423                 ///   Attempts to implicitly convert `source' into `target_type', using
1424                 ///   ImplicitConversion.  If there is no implicit conversion, then
1425                 ///   an error is signaled
1426                 /// </summary>
1427                 static public Expression ImplicitConversionRequired (EmitContext ec, Expression source,
1428                                                                      Type target_type, Location loc)
1429                 {
1430                         Expression e = ImplicitConversion (ec, source, target_type, loc);
1431                         if (e != null)
1432                                 return e;
1433
1434                         source.Error_ValueCannotBeConverted (ec, loc, target_type, false);
1435                         return null;
1436                 }
1437
1438                 /// <summary>
1439                 ///   Performs the explicit numeric conversions
1440                 ///
1441                 /// There are a few conversions that are not part of the C# standard,
1442                 /// they were interim hacks in the C# compiler that were supposed to
1443                 /// become explicit operators in the UIntPtr class and IntPtr class,
1444                 /// but for historical reasons it did not happen, so the C# compiler
1445                 /// ended up with these special hacks.
1446                 ///
1447                 /// See bug 59800 for details.
1448                 ///
1449                 /// The conversion are:
1450                 ///   UIntPtr->SByte
1451                 ///   UIntPtr->Int16
1452                 ///   UIntPtr->Int32
1453                 ///   IntPtr->UInt64
1454                 ///   UInt64->IntPtr
1455                 ///   SByte->UIntPtr
1456                 ///   Int16->UIntPtr
1457                 ///
1458                 /// </summary>
1459                 public static Expression ExplicitNumericConversion (Expression expr, Type target_type)
1460                 {
1461                         Type expr_type = expr.Type;
1462                         Type real_target_type = target_type;
1463
1464                         if (expr_type == TypeManager.sbyte_type){
1465                                 //
1466                                 // From sbyte to byte, ushort, uint, ulong, char, uintptr
1467                                 //
1468                                 if (real_target_type == TypeManager.byte_type)
1469                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1);
1470                                 if (real_target_type == TypeManager.ushort_type)
1471                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2);
1472                                 if (real_target_type == TypeManager.uint32_type)
1473                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4);
1474                                 if (real_target_type == TypeManager.uint64_type)
1475                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8);
1476                                 if (real_target_type == TypeManager.char_type)
1477                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH);
1478
1479                                 // One of the built-in conversions that belonged in the class library
1480                                 if (real_target_type == TypeManager.uintptr_type){
1481                                         Expression u8e = new ConvCast (expr, TypeManager.uint64_type, ConvCast.Mode.I1_U8);
1482
1483                                         return new OperatorCast (u8e, TypeManager.uintptr_type, true);
1484                                 }
1485                         } else if (expr_type == TypeManager.byte_type){
1486                                 //
1487                                 // From byte to sbyte and char
1488                                 //
1489                                 if (real_target_type == TypeManager.sbyte_type)
1490                                         return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1);
1491                                 if (real_target_type == TypeManager.char_type)
1492                                         return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH);
1493                         } else if (expr_type == TypeManager.short_type){
1494                                 //
1495                                 // From short to sbyte, byte, ushort, uint, ulong, char, uintptr
1496                                 //
1497                                 if (real_target_type == TypeManager.sbyte_type)
1498                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1);
1499                                 if (real_target_type == TypeManager.byte_type)
1500                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1);
1501                                 if (real_target_type == TypeManager.ushort_type)
1502                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2);
1503                                 if (real_target_type == TypeManager.uint32_type)
1504                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4);
1505                                 if (real_target_type == TypeManager.uint64_type)
1506                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8);
1507                                 if (real_target_type == TypeManager.char_type)
1508                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH);
1509
1510                                 // One of the built-in conversions that belonged in the class library
1511                                 if (real_target_type == TypeManager.uintptr_type){
1512                                         Expression u8e = new ConvCast (expr, TypeManager.uint64_type, ConvCast.Mode.I2_U8);
1513
1514                                         return new OperatorCast (u8e, TypeManager.uintptr_type, true);
1515                                 }
1516                         } else if (expr_type == TypeManager.ushort_type){
1517                                 //
1518                                 // From ushort to sbyte, byte, short, char
1519                                 //
1520                                 if (real_target_type == TypeManager.sbyte_type)
1521                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1);
1522                                 if (real_target_type == TypeManager.byte_type)
1523                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1);
1524                                 if (real_target_type == TypeManager.short_type)
1525                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2);
1526                                 if (real_target_type == TypeManager.char_type)
1527                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH);
1528                         } else if (expr_type == TypeManager.int32_type){
1529                                 //
1530                                 // From int to sbyte, byte, short, ushort, uint, ulong, char, uintptr
1531                                 //
1532                                 if (real_target_type == TypeManager.sbyte_type)
1533                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1);
1534                                 if (real_target_type == TypeManager.byte_type)
1535                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1);
1536                                 if (real_target_type == TypeManager.short_type)
1537                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2);
1538                                 if (real_target_type == TypeManager.ushort_type)
1539                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2);
1540                                 if (real_target_type == TypeManager.uint32_type)
1541                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4);
1542                                 if (real_target_type == TypeManager.uint64_type)
1543                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8);
1544                                 if (real_target_type == TypeManager.char_type)
1545                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_CH);
1546
1547                                 // One of the built-in conversions that belonged in the class library
1548                                 if (real_target_type == TypeManager.uintptr_type){
1549                                         Expression u8e = new ConvCast (expr, TypeManager.uint64_type, ConvCast.Mode.I2_U8);
1550
1551                                         return new OperatorCast (u8e, TypeManager.uintptr_type, true);
1552                                 }
1553                         } else if (expr_type == TypeManager.uint32_type){
1554                                 //
1555                                 // From uint to sbyte, byte, short, ushort, int, char
1556                                 //
1557                                 if (real_target_type == TypeManager.sbyte_type)
1558                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1);
1559                                 if (real_target_type == TypeManager.byte_type)
1560                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1);
1561                                 if (real_target_type == TypeManager.short_type)
1562                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2);
1563                                 if (real_target_type == TypeManager.ushort_type)
1564                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2);
1565                                 if (real_target_type == TypeManager.int32_type)
1566                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4);
1567                                 if (real_target_type == TypeManager.char_type)
1568                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH);
1569                         } else if (expr_type == TypeManager.int64_type){
1570                                 //
1571                                 // From long to sbyte, byte, short, ushort, int, uint, ulong, char
1572                                 //
1573                                 if (real_target_type == TypeManager.sbyte_type)
1574                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1);
1575                                 if (real_target_type == TypeManager.byte_type)
1576                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1);
1577                                 if (real_target_type == TypeManager.short_type)
1578                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2);
1579                                 if (real_target_type == TypeManager.ushort_type)
1580                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2);
1581                                 if (real_target_type == TypeManager.int32_type)
1582                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4);
1583                                 if (real_target_type == TypeManager.uint32_type)
1584                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4);
1585                                 if (real_target_type == TypeManager.uint64_type)
1586                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8);
1587                                 if (real_target_type == TypeManager.char_type)
1588                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH);
1589                         } else if (expr_type == TypeManager.uint64_type){
1590                                 //
1591                                 // From ulong to sbyte, byte, short, ushort, int, uint, long, char
1592                                 //
1593                                 if (real_target_type == TypeManager.sbyte_type)
1594                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1);
1595                                 if (real_target_type == TypeManager.byte_type)
1596                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1);
1597                                 if (real_target_type == TypeManager.short_type)
1598                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2);
1599                                 if (real_target_type == TypeManager.ushort_type)
1600                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2);
1601                                 if (real_target_type == TypeManager.int32_type)
1602                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4);
1603                                 if (real_target_type == TypeManager.uint32_type)
1604                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4);
1605                                 if (real_target_type == TypeManager.int64_type)
1606                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8);
1607                                 if (real_target_type == TypeManager.char_type)
1608                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH);
1609
1610                                 // One of the built-in conversions that belonged in the class library
1611                                 if (real_target_type == TypeManager.intptr_type){
1612                                         return new OperatorCast (new EmptyCast (expr, TypeManager.int64_type),
1613                                                                  TypeManager.intptr_type, true);
1614                                 }
1615                         } else if (expr_type == TypeManager.char_type){
1616                                 //
1617                                 // From char to sbyte, byte, short
1618                                 //
1619                                 if (real_target_type == TypeManager.sbyte_type)
1620                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1);
1621                                 if (real_target_type == TypeManager.byte_type)
1622                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1);
1623                                 if (real_target_type == TypeManager.short_type)
1624                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2);
1625                         } else if (expr_type == TypeManager.float_type){
1626                                 //
1627                                 // From float to sbyte, byte, short,
1628                                 // ushort, int, uint, long, ulong, char
1629                                 // or decimal
1630                                 //
1631                                 if (real_target_type == TypeManager.sbyte_type)
1632                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1);
1633                                 if (real_target_type == TypeManager.byte_type)
1634                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1);
1635                                 if (real_target_type == TypeManager.short_type)
1636                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2);
1637                                 if (real_target_type == TypeManager.ushort_type)
1638                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2);
1639                                 if (real_target_type == TypeManager.int32_type)
1640                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4);
1641                                 if (real_target_type == TypeManager.uint32_type)
1642                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4);
1643                                 if (real_target_type == TypeManager.int64_type)
1644                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8);
1645                                 if (real_target_type == TypeManager.uint64_type)
1646                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8);
1647                                 if (real_target_type == TypeManager.char_type)
1648                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH);
1649                                 if (real_target_type == TypeManager.decimal_type)
1650                                         return new CastToDecimal (expr, true);
1651                         } else if (expr_type == TypeManager.double_type){
1652                                 //
1653                                 // From double to sbyte, byte, short,
1654                                 // ushort, int, uint, long, ulong,
1655                                 // char, float or decimal
1656                                 //
1657                                 if (real_target_type == TypeManager.sbyte_type)
1658                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1);
1659                                 if (real_target_type == TypeManager.byte_type)
1660                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1);
1661                                 if (real_target_type == TypeManager.short_type)
1662                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2);
1663                                 if (real_target_type == TypeManager.ushort_type)
1664                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2);
1665                                 if (real_target_type == TypeManager.int32_type)
1666                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4);
1667                                 if (real_target_type == TypeManager.uint32_type)
1668                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4);
1669                                 if (real_target_type == TypeManager.int64_type)
1670                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8);
1671                                 if (real_target_type == TypeManager.uint64_type)
1672                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8);
1673                                 if (real_target_type == TypeManager.char_type)
1674                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH);
1675                                 if (real_target_type == TypeManager.float_type)
1676                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4);
1677                                 if (real_target_type == TypeManager.decimal_type)
1678                                         return new CastToDecimal (expr, true);
1679                         } else if (expr_type == TypeManager.uintptr_type){
1680                                 //
1681                                 // Various built-in conversions that belonged in the class library
1682                                 //
1683                                 // from uintptr to sbyte, short, int32
1684                                 //
1685                                 if (real_target_type == TypeManager.sbyte_type){
1686                                         Expression uint32e = new OperatorCast (expr, TypeManager.uint32_type, true);
1687                                         return new ConvCast (uint32e, TypeManager.sbyte_type, ConvCast.Mode.U4_I1);
1688                                 }
1689                                 if (real_target_type == TypeManager.short_type){
1690                                         Expression uint32e = new OperatorCast (expr, TypeManager.uint32_type, true);
1691                                         return new ConvCast (uint32e, TypeManager.sbyte_type, ConvCast.Mode.U4_I2);
1692                                 }
1693                                 if (real_target_type == TypeManager.int32_type){
1694                                         return new EmptyCast (new OperatorCast (expr, TypeManager.uint32_type, true),
1695                                                               TypeManager.int32_type);
1696                                 }
1697                         } else if (expr_type == TypeManager.intptr_type){
1698                                 if (real_target_type == TypeManager.uint64_type){
1699                                         return new EmptyCast (new OperatorCast (expr, TypeManager.int64_type, true),
1700                                                               TypeManager.uint64_type);
1701                                 }
1702                         } else if (expr_type == TypeManager.decimal_type) {
1703                                 return new CastFromDecimal (expr, target_type).Resolve ();
1704                         }
1705                         return null;
1706                 }
1707
1708                 /// <summary>
1709                 ///  Returns whether an explicit reference conversion can be performed
1710                 ///  from source_type to target_type
1711                 /// </summary>
1712                 public static bool ExplicitReferenceConversionExists (Type source_type, Type target_type)
1713                 {
1714                         bool target_is_type_param = TypeManager.IsGenericParameter (target_type);
1715                         bool target_is_value_type = target_type.IsValueType;
1716
1717                         if (source_type == target_type)
1718                                 return true;
1719
1720                         //
1721                         // From generic parameter to any type
1722                         //
1723                         if (TypeManager.IsGenericParameter (source_type))
1724                                 return ExplicitTypeParameterConversionExists (source_type, target_type);
1725
1726                         //
1727                         // From object to a generic parameter
1728                         //
1729                         if (source_type == TypeManager.object_type && target_is_type_param)
1730                                 return true;
1731
1732                         //
1733                         // From object to any reference type
1734                         //
1735                         if (source_type == TypeManager.object_type && !target_is_value_type)
1736                                 return true;
1737
1738                         //
1739                         // From any class S to any class-type T, provided S is a base class of T
1740                         //
1741                         if (TypeManager.IsSubclassOf (target_type, source_type))
1742                                 return true;
1743
1744                         //
1745                         // From any interface type S to any interface T provided S is not derived from T
1746                         //
1747                         if (source_type.IsInterface && target_type.IsInterface){
1748                                 if (!TypeManager.IsSubclassOf (target_type, source_type))
1749                                         return true;
1750                         }
1751
1752                         //
1753                         // From any class type S to any interface T, provided S is not sealed
1754                         // and provided S does not implement T.
1755                         //
1756                         if (target_type.IsInterface && !source_type.IsSealed &&
1757                             !TypeManager.ImplementsInterface (source_type, target_type))
1758                                 return true;
1759
1760                         //
1761                         // From any interface-type S to to any class type T, provided T is not
1762                         // sealed, or provided T implements S.
1763                         //
1764                         if (source_type.IsInterface &&
1765                             (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type)))
1766                                 return true;
1767
1768
1769                         // From an array type S with an element type Se to an array type T with an
1770                         // element type Te provided all the following are true:
1771                         //     * S and T differe only in element type, in other words, S and T
1772                         //       have the same number of dimensions.
1773                         //     * Both Se and Te are reference types
1774                         //     * An explicit referenc conversions exist from Se to Te
1775                         //
1776                         if (source_type.IsArray && target_type.IsArray) {
1777                                 if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
1778
1779                                         Type source_element_type = TypeManager.GetElementType (source_type);
1780                                         Type target_element_type = TypeManager.GetElementType (target_type);
1781
1782                                         if (TypeManager.IsGenericParameter (source_element_type) ||
1783                                             (!source_element_type.IsValueType && !target_element_type.IsValueType))
1784                                                 if (ExplicitReferenceConversionExists (source_element_type,
1785                                                                                        target_element_type))
1786                                                         return true;
1787                                 }
1788                         }
1789
1790
1791                         // From System.Array to any array-type
1792                         if (source_type == TypeManager.array_type &&
1793                             target_type.IsArray){
1794                                 return true;
1795                         }
1796
1797                         //
1798                         // From System delegate to any delegate-type
1799                         //
1800                         if (source_type == TypeManager.delegate_type &&
1801                             TypeManager.IsDelegateType (target_type))
1802                                 return true;
1803
1804                         //
1805                         // From ICloneable to Array or Delegate types
1806                         //
1807                         if (source_type == TypeManager.icloneable_type &&
1808                             (target_type == TypeManager.array_type ||
1809                              target_type == TypeManager.delegate_type))
1810                                 return true;
1811
1812                         return false;
1813                 }
1814
1815                 /// <summary>
1816                 ///   Implements Explicit Reference conversions
1817                 /// </summary>
1818                 static Expression ExplicitReferenceConversion (Expression source, Type target_type)
1819                 {
1820                         Type source_type = source.Type;
1821                         bool target_is_type_param = TypeManager.IsGenericParameter (target_type);
1822                         bool target_is_value_type = target_type.IsValueType;
1823
1824                         //
1825                         // From object to a generic parameter
1826                         //
1827                         if (source_type == TypeManager.object_type && target_is_type_param)
1828                                 return new UnboxCast (source, target_type);
1829
1830                         //
1831                         // Explicit type parameter conversion.
1832                         //
1833
1834                         if (TypeManager.IsGenericParameter (source_type))
1835                                 return ExplicitTypeParameterConversion (source, target_type);
1836
1837                         //
1838                         // From object to any reference type
1839                         //
1840                         if (source_type == TypeManager.object_type && !target_is_value_type)
1841                                 return new ClassCast (source, target_type);
1842
1843                         //
1844                         // Unboxing conversion.
1845                         //
1846                         if (((source_type == TypeManager.enum_type &&
1847                                 !(source is EmptyCast)) ||
1848                                 source_type == TypeManager.value_type) && target_is_value_type)
1849                                 return new UnboxCast (source, target_type);
1850
1851                         //
1852                         // From any class S to any class-type T, provided S is a base class of T
1853                         //
1854                         if (TypeManager.IsSubclassOf (target_type, source_type))
1855                                 return new ClassCast (source, target_type);
1856
1857                         //
1858                         // From any interface type S to any interface T provided S is not derived from T
1859                         //
1860                         if (source_type.IsInterface && target_type.IsInterface){
1861                                 if (TypeManager.ImplementsInterface (source_type, target_type))
1862                                         return null;
1863                                 else
1864                                         return new ClassCast (source, target_type);
1865                         }
1866
1867                         //
1868                         // From any class type S to any interface T, provides S is not sealed
1869                         // and provided S does not implement T.
1870                         //
1871                         if (target_type.IsInterface && !source_type.IsSealed) {
1872                                 if (TypeManager.ImplementsInterface (source_type, target_type))
1873                                         return null;
1874                                 else
1875                                         return new ClassCast (source, target_type);
1876
1877                         }
1878
1879                         //
1880                         // From any interface-type S to to any class type T, provided T is not
1881                         // sealed, or provided T implements S.
1882                         //
1883                         if (source_type.IsInterface) {
1884                                 if (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type)) {
1885                                         if (target_type.IsClass)
1886                                                 return new ClassCast (source, target_type);
1887                                         else
1888                                                 return new UnboxCast (source, target_type);
1889                                 }
1890
1891                                 return null;
1892                         }
1893
1894                         // From an array type S with an element type Se to an array type T with an
1895                         // element type Te provided all the following are true:
1896                         //     * S and T differe only in element type, in other words, S and T
1897                         //       have the same number of dimensions.
1898                         //     * Both Se and Te are reference types
1899                         //     * An explicit referenc conversions exist from Se to Te
1900                         //
1901                         if (source_type.IsArray && target_type.IsArray) {
1902                                 if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
1903
1904                                         Type source_element_type = TypeManager.GetElementType (source_type);
1905                                         Type target_element_type = TypeManager.GetElementType (target_type);
1906
1907                                         if (!source_element_type.IsValueType && !target_element_type.IsValueType)
1908                                                 if (ExplicitReferenceConversionExists (source_element_type,
1909                                                                                        target_element_type))
1910                                                         return new ClassCast (source, target_type);
1911                                 }
1912                         }
1913
1914
1915                         // From System.Array to any array-type
1916                         if (source_type == TypeManager.array_type &&
1917                             target_type.IsArray) {
1918                                 return new ClassCast (source, target_type);
1919                         }
1920
1921                         //
1922                         // From System delegate to any delegate-type
1923                         //
1924                         if (source_type == TypeManager.delegate_type &&
1925                             TypeManager.IsDelegateType (target_type))
1926                                 return new ClassCast (source, target_type);
1927
1928                         //
1929                         // From ICloneable to Array or Delegate types
1930                         //
1931                         if (source_type == TypeManager.icloneable_type &&
1932                             (target_type == TypeManager.array_type ||
1933                              target_type == TypeManager.delegate_type))
1934                                 return new ClassCast (source, target_type);
1935
1936                         return null;
1937                 }
1938
1939                 /// <summary>
1940                 ///   Performs an explicit conversion of the expression `expr' whose
1941                 ///   type is expr.Type to `target_type'.
1942                 /// </summary>
1943                 static public Expression ExplicitConversionCore (EmitContext ec, Expression expr,
1944                                                                  Type target_type, Location loc)
1945                 {
1946                         Type expr_type = expr.Type;
1947
1948                         // Explicit conversion includes implicit conversion and it used for enum underlying types too
1949                         Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc);
1950                         if (ne != null)
1951                                 return ne;
1952
1953                         //
1954                         // Unboxing conversions; only object types can be convertible to enum
1955                         //
1956                         if (expr_type == TypeManager.object_type && target_type.IsValueType)
1957                                 return new UnboxCast (expr, target_type);
1958
1959                         if (TypeManager.IsEnumType (expr_type)) {
1960                                 if (expr is EnumConstant)
1961                                         return ExplicitConversionCore (ec, ((EnumConstant) expr).Child, target_type, loc);
1962
1963                                 return ExplicitConversionCore (ec, new EmptyCast (expr, TypeManager.EnumToUnderlying (expr_type)), target_type, loc);
1964                         }
1965
1966                         if (TypeManager.IsEnumType (target_type)){
1967                                 if (expr_type == TypeManager.enum_type)
1968                                         return new UnboxCast (expr, target_type);
1969
1970                                 Expression ce = ExplicitConversionCore (ec, expr, TypeManager.EnumToUnderlying (target_type), loc);
1971                                 if (ce != null)
1972                                         return new EmptyCast (ce, target_type);
1973                         }
1974
1975                         ne = ExplicitNumericConversion (expr, target_type);
1976                         if (ne != null)
1977                                 return ne;
1978
1979                         //
1980                         // Skip the ExplicitReferenceConversion because we can not convert
1981                         // from Null to a ValueType, and ExplicitReference wont check against
1982                         // null literal explicitly
1983                         //
1984                         if (expr_type != TypeManager.null_type){
1985                                 ne = ExplicitReferenceConversion (expr, target_type);
1986                                 if (ne != null)
1987                                         return ne;
1988                         }
1989
1990                         if (ec.InUnsafe){
1991                                 ne = ExplicitUnsafe (expr, target_type);
1992                                 if (ne != null)
1993                                         return ne;
1994                         }
1995
1996                         ne = ExplicitUserConversion (ec, expr, target_type, loc);
1997                         if (ne != null)
1998                                 return ne;
1999
2000                         return null;
2001                 }
2002
2003                 public static Expression ExplicitUnsafe (Expression expr, Type target_type)
2004                 {
2005                         Type expr_type = expr.Type;
2006
2007                         if (target_type.IsPointer){
2008                                 if (expr_type.IsPointer)
2009                                         return new EmptyCast (expr, target_type);
2010
2011                                 if (expr_type == TypeManager.sbyte_type ||
2012                                         expr_type == TypeManager.short_type ||
2013                                         expr_type == TypeManager.int32_type ||
2014                                         expr_type == TypeManager.int64_type)
2015                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I);
2016
2017                                 if (expr_type == TypeManager.ushort_type ||
2018                                         expr_type == TypeManager.uint32_type ||
2019                                         expr_type == TypeManager.uint64_type ||
2020                                         expr_type == TypeManager.byte_type)
2021                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
2022                         }
2023
2024                         if (expr_type.IsPointer){
2025                                 if (target_type == TypeManager.sbyte_type)
2026                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
2027                                 else if (target_type == TypeManager.byte_type)
2028                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
2029                                 else if (target_type == TypeManager.short_type)
2030                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
2031                                 else if (target_type == TypeManager.ushort_type)
2032                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
2033                                 else if (target_type == TypeManager.int32_type)
2034                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
2035                                 else if (target_type == TypeManager.uint32_type)
2036                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
2037                                 else if (target_type == TypeManager.uint64_type)
2038                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
2039                                 else if (target_type == TypeManager.int64_type){
2040                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
2041                                 }
2042                         }
2043                         return null;
2044                 }
2045
2046                 /// <summary>
2047                 ///   Same as ExplicitConversion, only it doesn't include user defined conversions
2048                 /// </summary>
2049                 static public Expression ExplicitConversionStandard (EmitContext ec, Expression expr,
2050                                                                      Type target_type, Location l)
2051                 {
2052                         int errors = Report.Errors;
2053                         Expression ne = ImplicitConversionStandard (ec, expr, target_type, l);
2054                         if (Report.Errors > errors)
2055                                 return null;
2056
2057                         if (ne != null)
2058                                 return ne;
2059
2060                         ne = ExplicitNumericConversion (expr, target_type);
2061                         if (ne != null)
2062                                 return ne;
2063
2064                         ne = ExplicitReferenceConversion (expr, target_type);
2065                         if (ne != null)
2066                                 return ne;
2067
2068                         if (ec.InUnsafe && expr.Type == TypeManager.void_ptr_type && target_type.IsPointer)
2069                                 return new EmptyCast (expr, target_type);
2070
2071                         expr.Error_ValueCannotBeConverted (ec, l, target_type, true);
2072                         return null;
2073                 }
2074
2075                 /// <summary>
2076                 ///   Performs an explicit conversion of the expression `expr' whose
2077                 ///   type is expr.Type to `target_type'.
2078                 /// </summary>
2079                 static public Expression ExplicitConversion (EmitContext ec, Expression expr,
2080                         Type target_type, Location loc)
2081                 {
2082                         Expression e;
2083 #if GMCS_SOURCE
2084                         Type expr_type = expr.Type;
2085                         if (TypeManager.IsNullableType (target_type)) {
2086                                 if (TypeManager.IsNullableType (expr_type)) {
2087                                         e = new Nullable.LiftedConversion (
2088                                                 expr, target_type, false, true, loc).Resolve (ec);
2089                                         if (e != null)
2090                                                 return e;
2091                                 } else if (expr_type == TypeManager.object_type) {
2092                                         return new UnboxCast (expr, target_type);
2093                                 } else {
2094                                         Type target = TypeManager.GetTypeArguments (target_type) [0];
2095
2096                                         e = ExplicitConversionCore (ec, expr, target, loc);
2097                                         if (e != null)
2098                                                 return Nullable.Wrap.Create (e, ec);
2099                                 }
2100                         } else if (TypeManager.IsNullableType (expr_type)) {
2101                                 Expression source = Nullable.Unwrap.Create (expr, ec);
2102                                 if (source != null) {
2103                                         e = ExplicitConversionCore (ec, source, target_type, loc);
2104                                         if (e != null)
2105                                                 return e;
2106                                 }
2107                         }
2108 #endif
2109                         e = ExplicitConversionCore (ec, expr, target_type, loc);
2110                         if (e != null)
2111                                 return e;
2112
2113                         expr.Error_ValueCannotBeConverted (ec, loc, target_type, true);
2114                         return null;
2115                 }
2116         }
2117 }