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