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