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