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