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