moving the JVM specific directory
[mono.git] / mcs / bmcs / 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 public void Error_CannotConvertType (Location loc, Type source, Type target)
33                 {
34                         Report.Error (30, loc, "Cannot convert type '" +
35                                       TypeManager.CSharpName (source) + "' to '" +
36                                       TypeManager.CSharpName (target) + "'");
37                 }
38
39                 static Expression TypeParameter_to_Null (Expression expr, Type target_type,
40                                                          Location loc)
41                 {
42                         if (!TypeParameter_to_Null (target_type)) {
43                                 Report.Error (403, loc, "Cannot convert null to the type " +
44                                               "parameter `{0}' becaues it could be a value " +
45                                               "type.  Consider using `default ({0})' instead.",
46                                               target_type);
47                                 return null;
48                         }
49
50                         return new NullCast (expr, target_type);
51                 }
52
53                 static bool TypeParameter_to_Null (Type target_type)
54                 {
55                         GenericConstraints gc = TypeManager.GetTypeParameterConstraints (target_type);
56                         if (gc == null)
57                                 return false;
58
59                         if (gc.HasReferenceTypeConstraint)
60                                 return true;
61                         if (gc.HasClassConstraint && !TypeManager.IsValueType (gc.ClassConstraint))
62                                 return true;
63
64                         return false;
65                 }
66
67                 static Type TypeParam_EffectiveBaseType (EmitContext ec, Type t)
68                 {
69                         GenericConstraints gc = TypeManager.GetTypeParameterConstraints (t);
70                         if (gc == null)
71                                 return TypeManager.object_type;
72
73                         return TypeParam_EffectiveBaseType (ec, gc);
74                 }
75
76                 static Type TypeParam_EffectiveBaseType (EmitContext ec, GenericConstraints gc)
77                 {
78                         ArrayList list = new ArrayList ();
79                         list.Add (gc.EffectiveBaseClass);
80                         foreach (Type t in gc.InterfaceConstraints) {
81                                 if (!t.IsGenericParameter)
82                                         continue;
83
84                                 GenericConstraints new_gc = TypeManager.GetTypeParameterConstraints (t);
85                                 if (new_gc != null)
86                                         list.Add (TypeParam_EffectiveBaseType (ec, new_gc));
87                         }
88                         return FindMostEncompassedType (ec, list);
89                 }
90
91                 static Expression TypeParameterConversion (Expression expr, bool is_reference, Type target_type)
92                 {
93                         if (is_reference)
94                                 return new EmptyCast (expr, target_type);
95                         else
96                                 return new BoxedCast (expr, target_type);
97                 }
98
99                 static Expression ImplicitTypeParameterConversion (EmitContext ec, Expression expr,
100                                                                    Type target_type)
101                 {
102                         Type expr_type = expr.Type;
103
104                         GenericConstraints gc = TypeManager.GetTypeParameterConstraints (expr_type);
105
106                         if (gc == null) {
107                                 if (target_type == TypeManager.object_type)
108                                         return new BoxedCast (expr);
109
110                                 return null;
111                         }
112
113                         // We're converting from a type parameter which is known to be a reference type.
114                         bool is_reference = gc.IsReferenceType;
115                         Type base_type = TypeParam_EffectiveBaseType (ec, gc);
116
117                         if (TypeManager.IsSubclassOf (base_type, target_type))
118                                 return TypeParameterConversion (expr, is_reference, target_type);
119
120                         if (target_type.IsInterface) {
121                                 if (TypeManager.ImplementsInterface (base_type, target_type))
122                                         return TypeParameterConversion (expr, is_reference, target_type);
123
124                                 foreach (Type t in gc.InterfaceConstraints) {
125                                         if (TypeManager.IsSubclassOf (t, target_type))
126                                                 return TypeParameterConversion (expr, is_reference, target_type);
127                                 }
128                         }
129
130                         foreach (Type t in gc.InterfaceConstraints) {
131                                 if (!t.IsGenericParameter)
132                                         continue;
133                                 if (TypeManager.IsSubclassOf (t, target_type))
134                                         return TypeParameterConversion (expr, is_reference, target_type);
135                         }
136
137                         return null;
138                 }
139
140                 static EmptyExpression MyEmptyExpr;
141                 static public Expression WideningReferenceConversion (EmitContext ec, Expression expr, Type target_type)
142                 {
143                         Type expr_type = expr.Type;
144
145                         if (expr_type == null && expr.eclass == ExprClass.MethodGroup){
146                                 // if we are a method group, emit a warning
147
148                                 expr.Emit (null);
149                         }
150
151                         if (expr_type == TypeManager.void_type)
152                                 return null;
153
154                         if (expr_type.IsGenericParameter)
155                                 return ImplicitTypeParameterConversion (ec, expr, target_type);
156                                 
157                         //
158                         // notice that it is possible to write "ValueType v = 1", the ValueType here
159                         // is an abstract class, and not really a value type, so we apply the same rules.
160                         //
161                         if (target_type == TypeManager.object_type) {
162                                 //
163                                 // A pointer type cannot be converted to object
164                                 // 
165                                 if (expr_type.IsPointer)
166                                         return null;
167
168                                 if (TypeManager.IsValueType (expr_type))
169                                         return new BoxedCast (expr);
170                                 if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type){
171                                         if (expr_type == TypeManager.anonymous_method_type)
172                                                 return null;
173                                         return new EmptyCast (expr, target_type);
174                                 }
175
176                                 return null;
177                         } else if (target_type == TypeManager.value_type) {
178                                 if (TypeManager.IsValueType (expr_type))
179                                         return new BoxedCast (expr);
180                                 if (expr_type == TypeManager.null_type)
181                                         return new NullCast (expr, target_type);
182
183                                 return null;
184                         } else if (TypeManager.IsSubclassOf (expr_type, target_type)) {
185                                 //
186                                 // Special case: enumeration to System.Enum.
187                                 // System.Enum is not a value type, it is a class, so we need
188                                 // a boxing conversion
189                                 //
190                                 if (expr_type.IsEnum || expr_type.IsGenericParameter)
191                                         return new BoxedCast (expr);
192
193                                 return new EmptyCast (expr, target_type);
194                         }
195
196                         // This code is kind of mirrored inside WideningStandardConversionExists
197                         // with the small distinction that we only probe there
198                         //
199                         // Always ensure that the code here and there is in sync
200
201                         // from the null type to any reference-type.
202                         if (expr_type == TypeManager.null_type){
203                                 if (target_type.IsPointer)
204                                         return new EmptyCast (expr, target_type);
205                                         
206                                 if (!target_type.IsValueType)
207                                         return new NullCast (expr, target_type);
208
209                                 // VB.NET specific: Convert Nothing to value types
210
211                                 Expression e = NothingToPrimitiveConstants (expr, target_type);
212                                 if (e != null)
213                                         return e;
214
215                                 return new NullCast (expr, target_type);
216                         }
217
218                         // from any class-type S to any interface-type T.
219                         if (target_type.IsInterface) {
220                                 if (target_type != TypeManager.iconvertible_type &&
221                                     expr_type.IsValueType && (expr is Constant) &&
222                                     !(expr is IntLiteral || expr is BoolLiteral ||
223                                       expr is FloatLiteral || expr is DoubleLiteral ||
224                                       expr is LongLiteral || expr is CharLiteral ||
225                                       expr is StringLiteral || expr is DecimalLiteral ||
226                                       expr is UIntLiteral || expr is ULongLiteral)) {
227                                         return null;
228                                 }
229
230                                 if (TypeManager.ImplementsInterface (expr_type, target_type)){
231                                         if (expr_type.IsGenericParameter || TypeManager.IsValueType (expr_type))
232                                                 return new BoxedCast (expr, target_type);
233                                         else
234                                                 return new EmptyCast (expr, target_type);
235                                 }
236                         }
237
238                         // from any interface type S to interface-type T.
239                         if (expr_type.IsInterface && target_type.IsInterface) {
240                                 if (TypeManager.ImplementsInterface (expr_type, target_type))
241                                         return new EmptyCast (expr, target_type);
242                                 else
243                                         return null;
244                         }
245
246                         // from an array-type S to an array-type of type T
247                         if (expr_type.IsArray && target_type.IsArray) {
248                                 if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
249
250                                         Type expr_element_type = TypeManager.GetElementType (expr_type);
251
252                                         if (MyEmptyExpr == null)
253                                                 MyEmptyExpr = new EmptyExpression ();
254                                                 
255                                         MyEmptyExpr.SetType (expr_element_type);
256                                         Type target_element_type = TypeManager.GetElementType (target_type);
257
258                                         if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
259                                                 if (WideningStandardConversionExists (ConstantEC, MyEmptyExpr,
260                                                                                       target_element_type))
261                                                         return new EmptyCast (expr, target_type);
262                                 }
263                         }
264                                 
265                         // from an array-type to System.Array
266                         if (expr_type.IsArray && target_type == TypeManager.array_type)
267                                 return new EmptyCast (expr, target_type);
268
269                         // from an array-type of type T to IEnumerable<T>
270                         if (expr_type.IsArray && TypeManager.IsIEnumerable (expr_type, target_type))
271                                 return new EmptyCast (expr, target_type);
272
273                         // from any delegate type to System.Delegate
274                         if ((expr_type == TypeManager.delegate_type || TypeManager.IsDelegateType (expr_type)) &&
275                             target_type == TypeManager.delegate_type)
276                                 return new EmptyCast (expr, target_type);
277                                         
278                         // from any array-type or delegate type into System.ICloneable.
279                         if (expr_type.IsArray ||
280                             expr_type == TypeManager.delegate_type || TypeManager.IsDelegateType (expr_type))
281                                 if (target_type == TypeManager.icloneable_type)
282                                         return new EmptyCast (expr, target_type);
283
284                         // from a generic type definition to a generic instance.
285                         if (TypeManager.IsEqual (expr_type, target_type))
286                                 return new EmptyCast (expr, target_type);
287
288                         return null;
289                 }
290
291                 //
292                 // Tests whether an implicit reference conversion exists between expr_type
293                 // and target_type
294                 //
295                 public static bool WideningReferenceConversionExists (EmitContext ec, Expression expr, Type target_type)
296                 {
297                         Type expr_type = expr.Type;
298
299                         if (expr_type.IsGenericParameter)
300                                 return ImplicitTypeParameterConversion (ec, expr, target_type) != null;
301
302                         //
303                         // This is the boxed case.
304                         //
305                         if (target_type == TypeManager.object_type) {
306                                 if (expr_type.IsClass || TypeManager.IsValueType (expr_type) ||
307                                     expr_type.IsInterface || expr_type == TypeManager.enum_type)
308                                         if (target_type != TypeManager.anonymous_method_type)
309                                         return true;
310
311                                 return false;
312                         } else if (TypeManager.IsSubclassOf (expr_type, target_type))
313                                 return true;
314
315                         // Please remember that all code below actually comes
316                         // from WideningReferenceConversion so make sure code remains in sync
317                                 
318                         // from any class-type S to any interface-type T.
319                         if (target_type.IsInterface) {
320                                 if (target_type != TypeManager.iconvertible_type &&
321                                     expr_type.IsValueType && (expr is Constant) &&
322                                     !(expr is IntLiteral || expr is BoolLiteral ||
323                                       expr is FloatLiteral || expr is DoubleLiteral ||
324                                       expr is LongLiteral || expr is CharLiteral ||
325                                       expr is StringLiteral || expr is DecimalLiteral ||
326                                       expr is UIntLiteral || expr is ULongLiteral)) {
327                                         return false;
328                                 }
329                                 
330                                 if (TypeManager.ImplementsInterface (expr_type, target_type))
331                                         return true;
332                         }
333                                 
334                         // from any interface type S to interface-type T.
335                         if (expr_type.IsInterface && target_type.IsInterface)
336                                 if (TypeManager.ImplementsInterface (expr_type, target_type))
337                                         return true;
338                                 
339                         // from an array-type S to an array-type of type T
340                         if (expr_type.IsArray && target_type.IsArray) {
341                                 if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
342                                                 
343                                         Type expr_element_type = expr_type.GetElementType ();
344
345                                         if (MyEmptyExpr == null)
346                                                 MyEmptyExpr = new EmptyExpression ();
347                                                 
348                                         MyEmptyExpr.SetType (expr_element_type);
349                                         Type target_element_type = TypeManager.GetElementType (target_type);
350                                                 
351                                         if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
352                                                 if (WideningStandardConversionExists (ConstantEC, MyEmptyExpr,
353                                                                                       target_element_type))
354                                                         return true;
355                                 }
356                         }
357                                 
358                         // from an array-type to System.Array
359                         if (expr_type.IsArray && (target_type == TypeManager.array_type))
360                                 return true;
361
362                         // from an array-type of type T to IEnumerable<T>
363                         if (expr_type.IsArray && TypeManager.IsIEnumerable (expr_type, target_type))
364                                 return true;
365
366                         // from any delegate type to System.Delegate
367                         if ((expr_type == TypeManager.delegate_type || TypeManager.IsDelegateType (expr_type)) &&
368                             target_type == TypeManager.delegate_type)
369                                 if (target_type.IsAssignableFrom (expr_type))
370                                         return true;
371                                         
372                         // from any array-type or delegate type into System.ICloneable.
373                         if (expr_type.IsArray ||
374                             expr_type == TypeManager.delegate_type || TypeManager.IsDelegateType (expr_type))
375                                 if (target_type == TypeManager.icloneable_type)
376                                         return true;
377                                 
378                         // from the null type to any reference-type.
379                         if (expr_type == TypeManager.null_type){
380                                 if (target_type.IsPointer)
381                                         return true;
382                         
383                                 if (!target_type.IsValueType)
384                                         return true;
385                         }
386
387                         // from a generic type definition to a generic instance.
388                         if (TypeManager.IsEqual (expr_type, target_type))
389                                 return true;
390
391                         return false;
392                 }
393
394                 /// <summary>
395                 ///   Implicit Numeric Conversions.
396                 ///
397                 ///   expr is the expression to convert, returns a new expression of type
398                 ///   target_type or null if an implicit conversion is not possible.
399                 /// </summary>
400                 static public Expression WideningNumericConversion (EmitContext ec, Expression expr,
401                                                                     Type target_type, Location loc)
402                 {
403                         Type expr_type = expr.Type;
404
405                         //
406                         // Attempt to do the implicit constant expression conversions
407
408                         if (expr is Constant){
409                                 Expression e;
410
411                                 e = WideningConstantConversions (target_type, (Constant) expr);
412                                 if (e != null)
413                                         return e;
414                                 
415                                 if (expr is IntConstant){
416                                         e = TryWideningIntConversion (target_type, (IntConstant) expr);
417                                         
418                                         if (e != null)
419                                                 return e;
420                                 } 
421                         }
422                         
423                         Type real_target_type = target_type;
424
425                         // VB.NET specific: Convert an enum to it's
426                         // underlying numeric type or any type that
427                         // it's underlyinmg type has widening
428                         // conversion to.
429
430                         if (expr_type.IsSubclassOf (TypeManager.enum_type)){
431                                 if (target_type == TypeManager.enum_type ||
432                                     target_type == TypeManager.object_type) {
433                                         if (expr is EnumConstant)
434                                                 expr = ((EnumConstant) expr).Child;
435                                         // We really need all these casts here .... :-(
436                                         expr = new BoxedCast (new EmptyCast (expr, expr_type));
437                                         return new EmptyCast (expr, target_type);
438                                 } 
439
440                                 //
441                                 // Notice that we have kept the expr_type unmodified, which is only
442                                 // used later on to 
443                                 if (expr is EnumConstant)
444                                         expr = ((EnumConstant) expr).Child;
445                                 else
446                                         expr = new EmptyCast (expr, TypeManager.EnumToUnderlying (expr_type));
447                                 expr_type = expr.Type;
448
449                                 if (expr_type == target_type)
450                                         return expr;
451                         }
452
453                         if (expr_type == TypeManager.sbyte_type){
454                                 //
455                                 // From sbyte to short, int, long, float, double.
456                                 //
457                                 if (real_target_type == TypeManager.int32_type)
458                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
459                                 if (real_target_type == TypeManager.int64_type)
460                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
461                                 if (real_target_type == TypeManager.double_type)
462                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
463                                 if (real_target_type == TypeManager.float_type)
464                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
465                                 if (real_target_type == TypeManager.short_type)
466                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
467                         } else if (expr_type == TypeManager.byte_type){
468                                 //
469                                 // From byte to short, ushort, int, uint, long, ulong, float, double
470                                 // 
471                                 if ((real_target_type == TypeManager.short_type) ||
472                                     (real_target_type == TypeManager.ushort_type) ||
473                                     (real_target_type == TypeManager.int32_type) ||
474                                     (real_target_type == TypeManager.uint32_type))
475                                         return new EmptyCast (expr, target_type);
476
477                                 if (real_target_type == TypeManager.uint64_type)
478                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
479                                 if (real_target_type == TypeManager.int64_type)
480                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
481                                 if (real_target_type == TypeManager.float_type)
482                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
483                                 if (real_target_type == TypeManager.double_type)
484                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
485                                 if (real_target_type == TypeManager.decimal_type)
486                                         return new ImplicitNew (ec, "System", "Decimal", loc, expr);
487                         } else if (expr_type == TypeManager.short_type){
488                                 //
489                                 // From short to int, long, float, double
490                                 // 
491                                 if (real_target_type == TypeManager.int32_type)
492                                         return new EmptyCast (expr, target_type);
493                                 if (real_target_type == TypeManager.int64_type)
494                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
495                                 if (real_target_type == TypeManager.double_type)
496                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
497                                 if (real_target_type == TypeManager.float_type)
498                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
499                                 if (real_target_type == TypeManager.decimal_type)
500                                         return new ImplicitNew (ec, "System", "Decimal", loc, expr);
501                         } else if (expr_type == TypeManager.ushort_type){
502                                 //
503                                 // From ushort to int, uint, long, ulong, float, double
504                                 //
505                                 if (real_target_type == TypeManager.uint32_type)
506                                         return new EmptyCast (expr, target_type);
507
508                                 if (real_target_type == TypeManager.uint64_type)
509                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
510                                 if (real_target_type == TypeManager.int32_type)
511                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
512                                 if (real_target_type == TypeManager.int64_type)
513                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
514                                 if (real_target_type == TypeManager.double_type)
515                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
516                                 if (real_target_type == TypeManager.float_type)
517                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
518                         } else if (expr_type == TypeManager.int32_type){
519                                 //
520                                 // From int to long, float, double
521                                 //
522                                 if (real_target_type == TypeManager.int64_type)
523                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
524                                 if (real_target_type == TypeManager.double_type)
525                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
526                                 if (real_target_type == TypeManager.float_type)
527                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
528                                 if (real_target_type == TypeManager.decimal_type)
529                                         return new ImplicitNew (ec, "System", "Decimal", loc, expr);
530                         } else if (expr_type == TypeManager.uint32_type){
531                                 //
532                                 // From uint to long, ulong, float, double
533                                 //
534                                 if (real_target_type == TypeManager.int64_type)
535                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
536                                 if (real_target_type == TypeManager.uint64_type)
537                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
538                                 if (real_target_type == TypeManager.double_type)
539                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
540                                                                OpCodes.Conv_R8);
541                                 if (real_target_type == TypeManager.float_type)
542                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
543                                                                OpCodes.Conv_R4);
544                         } else if (expr_type == TypeManager.uint64_type){
545                                 //
546                                 // From ulong to float, double
547                                 //
548                                 if (real_target_type == TypeManager.double_type)
549                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
550                                                                OpCodes.Conv_R8);
551                                 if (real_target_type == TypeManager.float_type)
552                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
553                                                                OpCodes.Conv_R4);        
554                         } else if (expr_type == TypeManager.int64_type){
555                                 //
556                                 // From long/ulong to float, double
557                                 //
558                                 if (real_target_type == TypeManager.double_type)
559                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
560                                 if (real_target_type == TypeManager.float_type)
561                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);     
562                                 if (real_target_type == TypeManager.decimal_type)
563                                         return new ImplicitNew (ec, "System", "Decimal", loc, expr);    
564                         } else if (expr_type == TypeManager.float_type){
565                                 //
566                                 // float to double
567                                 //
568                                 if (real_target_type == TypeManager.double_type)
569                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
570                         } else if (expr_type == TypeManager.decimal_type){
571                                 //
572                                 // From decimal to float, double
573                                 //
574                                 if (real_target_type == TypeManager.double_type)
575                                         return new HelperMethodInvocation (ec, loc, TypeManager.double_type, TypeManager.convert_to_double_decimal, expr);      
576                                 if (real_target_type == TypeManager.float_type)
577                                         return new HelperMethodInvocation (ec, loc, TypeManager.float_type, TypeManager.convert_to_single_decimal, expr);       
578                         }
579
580                         return null;
581                 }
582
583
584                 /// <summary>
585                 ///  Same as WideningStandardConversionExists except that it also looks at
586                 ///  implicit user defined conversions - needed for overload resolution
587                 /// </summary>
588                 public static bool WideningConversionExists (EmitContext ec, Expression expr, Type target_type)
589                 {
590                         if (expr is NullLiteral) {
591                                 if (target_type.IsGenericParameter)
592                                         return TypeParameter_to_Null (target_type);
593
594                                 if (TypeManager.IsNullableType (target_type))
595                                         return true;
596                         }
597
598                         if (WideningStandardConversionExists (ec, expr, target_type))
599                                 return true;
600
601                         //
602                         // VB.NET has no notion of User defined conversions
603                         //
604
605 //                      Expression dummy = ImplicitUserConversion (ec, expr, target_type, Location.Null);
606
607 //                      if (dummy != null)
608 //                              return true;
609
610                         return false;
611                 }
612
613                 //
614                 // VB.NET has no notion of User defined conversions
615                 //
616
617 //              public static bool ImplicitUserConversionExists (EmitContext ec, Type source, Type target)
618 //              {
619 //                      Expression dummy = ImplicitUserConversion (
620 //                              ec, new EmptyExpression (source), target, Location.Null);
621 //                      return dummy != null;
622 //              }
623
624                 /// <summary>
625                 ///  Determines if a standard implicit conversion exists from
626                 ///  expr_type to target_type
627                 ///
628                 ///  ec should point to a real EmitContext if expr.Type is TypeManager.anonymous_method_type.
629                 /// </summary>
630                 public static bool WideningStandardConversionExists (EmitContext ec, Expression expr, Type target_type)
631                 {
632                         Type expr_type = expr.Type;
633
634                         if (expr_type == TypeManager.void_type)
635                                 return false;
636
637                         //Console.WriteLine ("Expr is {0}", expr);
638                         //Console.WriteLine ("{0} -> {1} ?", expr_type, target_type);
639                         if (expr_type.Equals (target_type))
640                                 return true;
641
642
643                         // First numeric conversions 
644
645                         if (expr_type == TypeManager.sbyte_type){
646                                 //
647                                 // From sbyte to short, int, long, float, double.
648                                 //
649                                 if ((target_type == TypeManager.int32_type) || 
650                                     (target_type == TypeManager.int64_type) ||
651                                     (target_type == TypeManager.double_type) ||
652                                     (target_type == TypeManager.float_type)  ||
653                                     (target_type == TypeManager.short_type) ||
654                                     (target_type == TypeManager.decimal_type))
655                                         return true;
656                                 
657                         } else if (expr_type == TypeManager.byte_type){
658                                 //
659                                 // From byte to short, ushort, int, uint, long, ulong, float, double
660                                 // 
661                                 if ((target_type == TypeManager.short_type) ||
662                                     (target_type == TypeManager.ushort_type) ||
663                                     (target_type == TypeManager.int32_type) ||
664                                     (target_type == TypeManager.uint32_type) ||
665                                     (target_type == TypeManager.uint64_type) ||
666                                     (target_type == TypeManager.int64_type) ||
667                                     (target_type == TypeManager.float_type) ||
668                                     (target_type == TypeManager.double_type) ||
669                                     (target_type == TypeManager.decimal_type))
670                                         return true;
671         
672                         } else if (expr_type == TypeManager.short_type){
673                                 //
674                                 // From short to int, long, float, double
675                                 // 
676                                 if ((target_type == TypeManager.int32_type) ||
677                                     (target_type == TypeManager.int64_type) ||
678                                     (target_type == TypeManager.double_type) ||
679                                     (target_type == TypeManager.float_type) ||
680                                     (target_type == TypeManager.decimal_type))
681                                         return true;
682                                         
683                         } else if (expr_type == TypeManager.ushort_type){
684                                 //
685                                 // From ushort to int, uint, long, ulong, float, double
686                                 //
687                                 if ((target_type == TypeManager.uint32_type) ||
688                                     (target_type == TypeManager.uint64_type) ||
689                                     (target_type == TypeManager.int32_type) ||
690                                     (target_type == TypeManager.int64_type) ||
691                                     (target_type == TypeManager.double_type) ||
692                                     (target_type == TypeManager.float_type) ||
693                                     (target_type == TypeManager.decimal_type))
694                                         return true;
695                                     
696                         } else if (expr_type == TypeManager.int32_type){
697                                 //
698                                 // From int to long, float, double
699                                 //
700                                 if ((target_type == TypeManager.int64_type) ||
701                                     (target_type == TypeManager.double_type) ||
702                                     (target_type == TypeManager.float_type) ||
703                                     (target_type == TypeManager.decimal_type))
704                                         return true;
705                                         
706                         } else if (expr_type == TypeManager.uint32_type){
707                                 //
708                                 // From uint to long, ulong, float, double
709                                 //
710                                 if ((target_type == TypeManager.int64_type) ||
711                                     (target_type == TypeManager.uint64_type) ||
712                                     (target_type == TypeManager.double_type) ||
713                                     (target_type == TypeManager.float_type) ||
714                                     (target_type == TypeManager.decimal_type))
715                                         return true;
716                                         
717                         } else if ((expr_type == TypeManager.uint64_type) ||
718                                    (expr_type == TypeManager.int64_type)) {
719                                 //
720                                 // From long/ulong to float, double
721                                 //
722                                 if ((target_type == TypeManager.double_type) ||
723                                     (target_type == TypeManager.float_type) ||
724                                     (target_type == TypeManager.decimal_type))
725                                         return true;
726                                     
727                         } else if (expr_type == TypeManager.char_type){
728                                 //
729                                 // From char to ushort, int, uint, long, ulong, float, double
730                                 // 
731                                 if ((target_type == TypeManager.ushort_type) ||
732                                     (target_type == TypeManager.int32_type) ||
733                                     (target_type == TypeManager.uint32_type) ||
734                                     (target_type == TypeManager.uint64_type) ||
735                                     (target_type == TypeManager.int64_type) ||
736                                     (target_type == TypeManager.float_type) ||
737                                     (target_type == TypeManager.double_type) ||
738                                     (target_type == TypeManager.decimal_type))
739                                         return true;
740
741                         } else if (expr_type == TypeManager.float_type){
742                                 //
743                                 // float to double
744                                 //
745                                 if (target_type == TypeManager.double_type)
746                                         return true;
747                         }       
748                         
749                         if (expr.eclass == ExprClass.MethodGroup){
750                                 if (TypeManager.IsDelegateType (target_type) && RootContext.Version != LanguageVersion.ISO_1){
751                                         MethodGroupExpr mg = expr as MethodGroupExpr;
752                                         if (mg != null){
753                                                 //
754                                                 // This should not happen frequently, so we can create an object
755                                                 // to test compatibility
756                                                 //
757                                                 Expression c = ImplicitDelegateCreation.Create (ec, mg, target_type, Location.Null);
758                                                 return c != null;
759                                         }
760                                 }
761                         }
762                         
763                         if (WideningReferenceConversionExists (ec, expr, target_type))
764                                 return true;
765
766                         //
767                         // Implicit Constant Expression Conversions
768                         //
769                         if (expr is IntConstant){
770                                 int value = ((IntConstant) expr).Value;
771
772                                 if (target_type == TypeManager.sbyte_type){
773                                         if (value >= SByte.MinValue && value <= SByte.MaxValue)
774                                                 return true;
775                                 } else if (target_type == TypeManager.byte_type){
776                                         if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
777                                                 return true;
778                                 } else if (target_type == TypeManager.short_type){
779                                         if (value >= Int16.MinValue && value <= Int16.MaxValue)
780                                                 return true;
781                                 } else if (target_type == TypeManager.ushort_type){
782                                         if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
783                                                 return true;
784                                 } else if (target_type == TypeManager.uint32_type){
785                                         if (value >= 0)
786                                                 return true;
787                                 } else if (target_type == TypeManager.uint64_type){
788                                          //
789                                          // we can optimize this case: a positive int32
790                                          // always fits on a uint64.  But we need an opcode
791                                          // to do it.
792                                          //
793                                         if (value >= 0)
794                                                 return true;
795                                 }
796                                 
797                                 if (value == 0 && expr is IntLiteral && TypeManager.IsEnumType (target_type))
798                                         return true;
799                         }
800
801                         if (expr is LongConstant && target_type == TypeManager.uint64_type){
802                                 //
803                                 // Try the implicit constant expression conversion
804                                 // from long to ulong, instead of a nice routine,
805                                 // we just inline it
806                                 //
807                                 long v = ((LongConstant) expr).Value;
808                                 if (v > 0)
809                                         return true;
810                         }
811                         
812                         if ((target_type == TypeManager.enum_type ||
813                              target_type.IsSubclassOf (TypeManager.enum_type)) &&
814                              expr is IntLiteral){
815                                 IntLiteral i = (IntLiteral) expr;
816
817                                 if (i.Value == 0)
818                                         return true;
819                         }
820
821                         //
822                         // If `expr_type' implements `target_type' (which is an iface)
823                         // see TryWideningIntConversion
824                         // 
825                         if (target_type.IsInterface && target_type.IsAssignableFrom (expr_type))
826                                 return true;
827
828                         if (target_type == TypeManager.void_ptr_type && expr_type.IsPointer)
829                                 return true;
830
831                         if (TypeManager.IsNullableType (expr_type) && TypeManager.IsNullableType (target_type))
832                                 return true;
833
834                         if (expr_type == TypeManager.anonymous_method_type){
835                                 if (!TypeManager.IsDelegateType (target_type))
836                                         return false;
837
838                                 AnonymousMethod am = (AnonymousMethod) expr;
839
840                                 Expression conv = am.Compatible (ec, target_type, true);
841                                 if (conv != null)
842                                         return true;
843                         }
844
845                         return false;
846                 }
847
848                 //
849                 // Used internally by FindMostEncompassedType, this is used
850                 // to avoid creating lots of objects in the tight loop inside
851                 // FindMostEncompassedType
852                 //
853                 static EmptyExpression priv_fmet_param;
854                 
855                 /// <summary>
856                 ///  Finds "most encompassed type" according to the spec (13.4.2)
857                 ///  amongst the methods in the MethodGroupExpr
858                 /// </summary>
859                 static Type FindMostEncompassedType (EmitContext ec, ArrayList types)
860                 {
861                         Type best = null;
862
863                         if (priv_fmet_param == null)
864                                 priv_fmet_param = new EmptyExpression ();
865
866                         foreach (Type t in types){
867                                 priv_fmet_param.SetType (t);
868                                 
869                                 if (best == null) {
870                                         best = t;
871                                         continue;
872                                 }
873                                 
874                                 if (WideningStandardConversionExists (ec, priv_fmet_param, best))
875                                         best = t;
876                         }
877
878                         return best;
879                 }
880
881                 //
882                 // Used internally by FindMostEncompassingType, this is used
883                 // to avoid creating lots of objects in the tight loop inside
884                 // FindMostEncompassingType
885                 //
886                 static EmptyExpression priv_fmee_ret;
887                 
888                 /// <summary>
889                 ///  Finds "most encompassing type" according to the spec (13.4.2)
890                 ///  amongst the types in the given set
891                 /// </summary>
892                 static Type FindMostEncompassingType (EmitContext ec, ArrayList types)
893                 {
894                         Type best = null;
895
896                         if (priv_fmee_ret == null)
897                                 priv_fmee_ret = new EmptyExpression ();
898
899                         foreach (Type t in types){
900                                 priv_fmee_ret.SetType (best);
901
902                                 if (best == null) {
903                                         best = t;
904                                         continue;
905                                 }
906
907                                 if (WideningStandardConversionExists (ec, priv_fmee_ret, t))
908                                         best = t;
909                         }
910                         
911                         return best;
912                 }
913
914                 //
915                 // Used to avoid creating too many objects
916                 //
917                 static EmptyExpression priv_fms_expr;
918                 
919                 /// <summary>
920                 ///   Finds the most specific source Sx according to the rules of the spec (13.4.4)
921                 ///   by making use of FindMostEncomp* methods. Applies the correct rules separately
922                 ///   for explicit and implicit conversion operators.
923                 /// </summary>
924                 static public Type FindMostSpecificSource (EmitContext ec, MethodGroupExpr me,
925                                                            Expression source, bool apply_explicit_conv_rules,
926                                                            Location loc)
927                 {
928                         ArrayList src_types_set = new ArrayList ();
929                         
930                         if (priv_fms_expr == null)
931                                 priv_fms_expr = new EmptyExpression ();
932
933                         //
934                         // If any operator converts from S then Sx = S
935                         //
936                         Type source_type = source.Type;
937                         foreach (MethodBase mb in me.Methods){
938                                 ParameterData pd = Invocation.GetParameterData (mb);
939                                 Type param_type = pd.ParameterType (0);
940
941                                 if (param_type == source_type)
942                                         return param_type;
943
944                                 if (apply_explicit_conv_rules) {
945                                         //
946                                         // From the spec :
947                                         // Find the set of applicable user-defined conversion operators, U.  This set
948                                         // consists of the
949                                         // user-defined implicit or explicit conversion operators declared by
950                                         // the classes or structs in D that convert from a type encompassing
951                                         // or encompassed by S to a type encompassing or encompassed by T
952                                         //
953                                         priv_fms_expr.SetType (param_type);
954                                         if (WideningStandardConversionExists (ec, priv_fms_expr, source_type))
955                                                 src_types_set.Add (param_type);
956                                         else {
957                                                 if (WideningStandardConversionExists (ec, source, param_type))
958                                                         src_types_set.Add (param_type);
959                                         }
960                                 } else {
961                                         //
962                                         // Only if S is encompassed by param_type
963                                         //
964                                         if (WideningStandardConversionExists (ec, source, param_type))
965                                                 src_types_set.Add (param_type);
966                                 }
967                         }
968                         
969                         //
970                         // Explicit Conv rules
971                         //
972                         if (apply_explicit_conv_rules) {
973                                 ArrayList candidate_set = new ArrayList ();
974
975                                 foreach (Type param_type in src_types_set){
976                                         if (WideningStandardConversionExists (ec, source, param_type))
977                                                 candidate_set.Add (param_type);
978                                 }
979
980                                 if (candidate_set.Count != 0)
981                                         return FindMostEncompassedType (ec, candidate_set);
982                         }
983
984                         //
985                         // Final case
986                         //
987                         if (apply_explicit_conv_rules)
988                                 return FindMostEncompassingType (ec, src_types_set);
989                         else
990                                 return FindMostEncompassedType (ec, src_types_set);
991                 }
992
993                 //
994                 // Useful in avoiding proliferation of objects
995                 //
996                 static EmptyExpression priv_fmt_expr;
997                 
998                 /// <summary>
999                 ///  Finds the most specific target Tx according to section 13.4.4
1000                 /// </summary>
1001                 static public Type FindMostSpecificTarget (EmitContext ec, MethodGroupExpr me,
1002                                                            Type target, bool apply_explicit_conv_rules,
1003                                                            Location loc)
1004                 {
1005                         ArrayList tgt_types_set = new ArrayList ();
1006                         
1007                         if (priv_fmt_expr == null)
1008                                 priv_fmt_expr = new EmptyExpression ();
1009                         
1010                         //
1011                         // If any operator converts to T then Tx = T
1012                         //
1013                         foreach (MethodInfo mi in me.Methods){
1014                                 Type ret_type = mi.ReturnType;
1015
1016                                 if (ret_type == target)
1017                                         return ret_type;
1018
1019                                 if (apply_explicit_conv_rules) {
1020                                         //
1021                                         // From the spec :
1022                                         // Find the set of applicable user-defined conversion operators, U.
1023                                         //
1024                                         // This set consists of the
1025                                         // user-defined implicit or explicit conversion operators declared by
1026                                         // the classes or structs in D that convert from a type encompassing
1027                                         // or encompassed by S to a type encompassing or encompassed by T
1028                                         //
1029                                         priv_fms_expr.SetType (ret_type);
1030                                         if (WideningStandardConversionExists (ec, priv_fms_expr, target))
1031                                                 tgt_types_set.Add (ret_type);
1032                                         else {
1033                                                 priv_fms_expr.SetType (target);
1034                                                 if (WideningStandardConversionExists (ec, priv_fms_expr, ret_type))
1035                                                         tgt_types_set.Add (ret_type);
1036                                         }
1037                                 } else {
1038                                         //
1039                                         // Only if T is encompassed by param_type
1040                                         //
1041                                         priv_fms_expr.SetType (ret_type);
1042                                         if (WideningStandardConversionExists (ec, priv_fms_expr, target))
1043                                                 tgt_types_set.Add (ret_type);
1044                                 }
1045                         }
1046
1047                         //
1048                         // Explicit conv rules
1049                         //
1050                         if (apply_explicit_conv_rules) {
1051                                 ArrayList candidate_set = new ArrayList ();
1052
1053                                 foreach (Type ret_type in tgt_types_set){
1054                                         priv_fmt_expr.SetType (ret_type);
1055                                         
1056                                         if (WideningStandardConversionExists (ec, priv_fmt_expr, target))
1057                                                 candidate_set.Add (ret_type);
1058                                 }
1059
1060                                 if (candidate_set.Count != 0)
1061                                         return FindMostEncompassingType (ec, candidate_set);
1062                         }
1063                         
1064                         //
1065                         // Okay, final case !
1066                         //
1067                         if (apply_explicit_conv_rules)
1068                                 return FindMostEncompassedType (ec, tgt_types_set);
1069                         else 
1070                                 return FindMostEncompassingType (ec, tgt_types_set);
1071                 }
1072                 
1073                 /// <summary>
1074                 ///  User-defined Implicit conversions
1075                 /// </summary>
1076
1077                 //
1078                 // VB.NET has no notion of User defined conversions
1079                 //
1080
1081 //              static public Expression ImplicitUserConversion (EmitContext ec, Expression source,
1082 //                                                               Type target, Location loc)
1083 //              {
1084 //                      return UserDefinedConversion (ec, source, target, loc, false);
1085 //              }
1086
1087                 /// <summary>
1088                 ///  User-defined Explicit conversions
1089                 /// </summary>
1090
1091                 //
1092                 // VB.NET has no notion of User defined conversions
1093                 //
1094
1095 //              static public Expression ExplicitUserConversion (EmitContext ec, Expression source,
1096 //                                                               Type target, Location loc)
1097 //              {
1098 //                      return UserDefinedConversion (ec, source, target, loc, true);
1099 //              }
1100
1101                 static DoubleHash explicit_conv = new DoubleHash (100);
1102                 static DoubleHash implicit_conv = new DoubleHash (100);
1103                 /// <summary>
1104                 ///   Computes the MethodGroup for the user-defined conversion
1105                 ///   operators from source_type to target_type.  `look_for_explicit'
1106                 ///   controls whether we should also include the list of explicit
1107                 ///   operators
1108                 /// </summary>
1109                 static MethodGroupExpr GetConversionOperators (EmitContext ec,
1110                                                                Type source_type, Type target_type,
1111                                                                Location loc, bool look_for_explicit)
1112                 {
1113                         Expression mg1 = null, mg2 = null;
1114                         Expression mg5 = null, mg6 = null, mg7 = null, mg8 = null;
1115                         string op_name;
1116
1117                         op_name = "op_Implicit";
1118
1119                         MethodGroupExpr union3;
1120                         object r;
1121                         if ((look_for_explicit ? explicit_conv : implicit_conv).Lookup (source_type, target_type, out r))
1122                                 return (MethodGroupExpr) r;
1123
1124                         mg1 = Expression.MethodLookup (ec, source_type, op_name, loc);
1125                         if (source_type.BaseType != null)
1126                                 mg2 = Expression.MethodLookup (ec, source_type.BaseType, op_name, loc);
1127
1128                         if (mg1 == null)
1129                                 union3 = (MethodGroupExpr) mg2;
1130                         else if (mg2 == null)
1131                                 union3 = (MethodGroupExpr) mg1;
1132                         else
1133                                 union3 = Invocation.MakeUnionSet (mg1, mg2, loc);
1134
1135                         mg1 = Expression.MethodLookup (ec, target_type, op_name, loc);
1136                         if (mg1 != null){
1137                                 if (union3 != null)
1138                                         union3 = Invocation.MakeUnionSet (union3, mg1, loc);
1139                                 else
1140                                         union3 = (MethodGroupExpr) mg1;
1141                         }
1142
1143                         if (target_type.BaseType != null)
1144                                 mg1 = Expression.MethodLookup (ec, target_type.BaseType, op_name, loc);
1145                         
1146                         if (mg1 != null){
1147                                 if (union3 != null)
1148                                         union3 = Invocation.MakeUnionSet (union3, mg1, loc);
1149                                 else
1150                                         union3 = (MethodGroupExpr) mg1;
1151                         }
1152
1153                         MethodGroupExpr union4 = null;
1154
1155                         if (look_for_explicit) {
1156                                 op_name = "op_Explicit";
1157
1158                                 mg5 = Expression.MemberLookup (ec, source_type, op_name, loc);
1159                                 if (source_type.BaseType != null)
1160                                         mg6 = Expression.MethodLookup (ec, source_type.BaseType, op_name, loc);
1161                                 
1162                                 mg7 = Expression.MemberLookup (ec, target_type, op_name, loc);
1163                                 if (target_type.BaseType != null)
1164                                         mg8 = Expression.MethodLookup (ec, target_type.BaseType, op_name, loc);
1165                                 
1166                                 MethodGroupExpr union5 = Invocation.MakeUnionSet (mg5, mg6, loc);
1167                                 MethodGroupExpr union6 = Invocation.MakeUnionSet (mg7, mg8, loc);
1168
1169                                 union4 = Invocation.MakeUnionSet (union5, union6, loc);
1170                         }
1171                         
1172                         MethodGroupExpr ret = Invocation.MakeUnionSet (union3, union4, loc);
1173                         (look_for_explicit ? explicit_conv : implicit_conv).Insert (source_type, target_type, ret);
1174                         return ret;
1175                 }
1176                 
1177                 /// <summary>
1178                 ///   User-defined conversions
1179                 /// </summary>
1180
1181                 //
1182                 // VB.NET has no notion of User defined conversions. This method is not used.
1183                 //
1184                 static public Expression UserDefinedConversion (EmitContext ec, Expression source,
1185                                                                 Type target, Location loc,
1186                                                                 bool look_for_explicit)
1187                 {
1188                         MethodGroupExpr union;
1189                         Type source_type = source.Type;
1190                         MethodBase method = null;
1191
1192                         if (TypeManager.IsNullableType (source_type) && TypeManager.IsNullableType (target))
1193                                 return new Nullable.LiftedConversion (
1194                                         source, target, true, look_for_explicit, loc).Resolve (ec);
1195
1196                         union = GetConversionOperators (ec, source_type, target, loc, look_for_explicit);
1197                         if (union == null)
1198                                 return null;
1199                         
1200                         Type most_specific_source, most_specific_target;
1201
1202                         most_specific_source = FindMostSpecificSource (ec, union, source, look_for_explicit, loc);
1203                         if (most_specific_source == null)
1204                                 return null;
1205
1206                         most_specific_target = FindMostSpecificTarget (ec, union, target, look_for_explicit, loc);
1207                         if (most_specific_target == null) 
1208                                 return null;
1209
1210                         int count = 0;
1211
1212                         
1213                         foreach (MethodBase mb in union.Methods){
1214                                 ParameterData pd = Invocation.GetParameterData (mb);
1215                                 MethodInfo mi = (MethodInfo) mb;
1216                                 
1217                                 if (pd.ParameterType (0) == most_specific_source &&
1218                                     mi.ReturnType == most_specific_target) {
1219                                         method = mb;
1220                                         count++;
1221                                 }
1222                         }
1223                         
1224                         if (method == null || count > 1)
1225                                 return null;
1226                         
1227                         
1228                         //
1229                         // This will do the conversion to the best match that we
1230                         // found.  Now we need to perform an implict standard conversion
1231                         // if the best match was not the type that we were requested
1232                         // by target.
1233                         //
1234                         if (look_for_explicit)
1235                                 source = WideningAndNarrowingConversionStandard (ec, source, most_specific_source, loc);
1236                         else
1237                                 source = WideningConversionStandard (ec, source, most_specific_source, loc);
1238
1239                         if (source == null)
1240                                 return null;
1241
1242                         Expression e;
1243                         e =  new UserCast ((MethodInfo) method, source, loc);
1244                         if (e.Type != target){
1245                                 if (!look_for_explicit)
1246                                         e = WideningConversionStandard (ec, e, target, loc);
1247                                 else
1248                                         e = WideningAndNarrowingConversionStandard (ec, e, target, loc);
1249                         }
1250
1251                         return e;
1252                 }
1253                 
1254                 /// <summary>
1255                 ///   Converts implicitly the resolved expression `expr' into the
1256                 ///   `target_type'.  It returns a new expression that can be used
1257                 ///   in a context that expects a `target_type'. 
1258                 /// </summary>
1259                 static public Expression WideningConversion (EmitContext ec, Expression expr,
1260                                                              Type target_type, Location loc)
1261                 {
1262                         Expression e;
1263
1264                         if (target_type == null)
1265                                 throw new Exception ("Target type is null");
1266
1267                         e = WideningConversionStandard (ec, expr, target_type, loc);
1268                         if (e != null)
1269                                 return e;
1270
1271                         //
1272                         // VB.NET has no notion of User defined conversions
1273                         //
1274
1275 //                      e = ImplicitUserConversion (ec, expr, target_type, loc);
1276 //                      if (e != null)
1277 //                              return e;
1278
1279                         return null;
1280                 }
1281
1282                 
1283                 /// <summary>
1284                 ///   Attempts to apply the `Standard Implicit
1285                 ///   Conversion' rules to the expression `expr' into
1286                 ///   the `target_type'.  It returns a new expression
1287                 ///   that can be used in a context that expects a
1288                 ///   `target_type'.
1289                 ///
1290                 ///   This is different from `WideningConversion' in that the
1291                 ///   user defined implicit conversions are excluded. 
1292                 /// </summary>
1293                 static public Expression WideningConversionStandard (EmitContext ec, Expression expr,
1294                                                                      Type target_type, Location loc)
1295                 {
1296                         Type expr_type = expr.Type;
1297                         Expression e;
1298
1299                         if (expr is NullLiteral) {
1300                                 if (target_type.IsGenericParameter)
1301                                         return TypeParameter_to_Null (expr, target_type, loc);
1302
1303                                 if (TypeManager.IsNullableType (target_type))
1304                                         return new Nullable.NullableLiteral (target_type, loc);
1305                         }
1306
1307                         if (TypeManager.IsNullableType (expr_type) && TypeManager.IsNullableType (target_type))
1308                                 return new Nullable.LiftedConversion (
1309                                         expr, target_type, false, false, loc).Resolve (ec);
1310
1311                         if (expr.eclass == ExprClass.MethodGroup){
1312                                 if (!TypeManager.IsDelegateType (target_type)){
1313                                         return null;
1314                                 }
1315
1316                                 //
1317                                 // Only allow anonymous method conversions on post ISO_1
1318                                 //
1319                                 if (RootContext.Version != LanguageVersion.ISO_1){
1320                                         MethodGroupExpr mg = expr as MethodGroupExpr;
1321                                         if (mg != null)
1322                                                 return ImplicitDelegateCreation.Create (ec, mg, target_type, loc);
1323                                 }
1324                         }
1325
1326                         if (expr_type.Equals (target_type) && !TypeManager.IsNullType (expr_type))
1327                                 return expr;
1328
1329                         e = WideningNumericConversion (ec, expr, target_type, loc);
1330                         if (e != null)
1331                                 return e;
1332
1333                         e = WideningReferenceConversion (ec, expr, target_type);
1334                         if (e != null)
1335                                 return e;
1336                         
1337                         if ((target_type == TypeManager.enum_type ||
1338                              target_type.IsSubclassOf (TypeManager.enum_type)) &&
1339                             expr is IntLiteral){
1340                                 IntLiteral i = (IntLiteral) expr;
1341
1342                                 if (i.Value == 0)
1343                                         return new EnumConstant ((Constant) expr, target_type);
1344                         }
1345
1346                         if (ec.InUnsafe) {
1347                                 if (expr_type.IsPointer){
1348                                         if (target_type == TypeManager.void_ptr_type)
1349                                                 return new EmptyCast (expr, target_type);
1350
1351                                         //
1352                                         // yep, comparing pointer types cant be done with
1353                                         // t1 == t2, we have to compare their element types.
1354                                         //
1355                                         if (target_type.IsPointer){
1356                                                 if (TypeManager.GetElementType(target_type) == TypeManager.GetElementType(expr_type))
1357                                                         return expr;
1358                                         }
1359                                 }
1360                                 
1361                                 if (target_type.IsPointer) {
1362                                         if (expr_type == TypeManager.null_type)
1363                                                 return new EmptyCast (expr, target_type);
1364
1365                                         if (expr_type == TypeManager.void_ptr_type)
1366                                                 return new EmptyCast (expr, target_type);
1367                                 }
1368                         }
1369
1370                         if (expr_type == TypeManager.anonymous_method_type){
1371                                 if (!TypeManager.IsDelegateType (target_type)){
1372                                         Report.Error (1660, loc,
1373                                                               "Cannot convert anonymous method to `{0}', since it is not a delegate",
1374                                                               TypeManager.CSharpName (target_type));
1375                                         return null;
1376                                 }
1377
1378                                 AnonymousMethod am = (AnonymousMethod) expr;
1379                                 int errors = Report.Errors;
1380
1381                                 Expression conv = am.Compatible (ec, target_type, false);
1382                                 if (conv != null)
1383                                         return conv;
1384                                 
1385                                 //
1386                                 // We return something instead of null, to avoid
1387                                 // the duplicate error, since am.Compatible would have
1388                                 // reported that already
1389                                 //
1390                                 if (errors != Report.Errors)
1391                                         return new EmptyCast (expr, target_type);
1392                         }
1393
1394                         //
1395                         // VB.NET specific conversions
1396                         //
1397
1398                         e = WideningStringConversions (ec, expr, target_type, loc);
1399                         if (e != null)
1400                                 return e;
1401
1402                         
1403                         return null;
1404                 }
1405
1406                 /// <summary>
1407                 ///   Attempts to perform an implicit constant conversion of the IntConstant
1408                 ///   into a different data type using casts (See Implicit Constant
1409                 ///   Expression Conversions)
1410                 /// </summary>
1411                 static public Expression TryWideningIntConversion (Type target_type, IntConstant ic)
1412                 {
1413                         int value = ic.Value;
1414
1415                         if (value == 0 && ic is IntLiteral && TypeManager.IsEnumType (target_type)){
1416                                 Type underlying = TypeManager.EnumToUnderlying (target_type);
1417                                 Constant e = (Constant) ic;
1418                                 
1419                                 //
1420                                 // Possibly, we need to create a different 0 literal before passing
1421                                 // to EnumConstant
1422                                 //
1423                                 if (underlying == TypeManager.int64_type)
1424                                         e = new LongLiteral (0);
1425                                 else if (underlying == TypeManager.uint64_type)
1426                                         e = new ULongLiteral (0);
1427
1428                                 return new EnumConstant (e, target_type);
1429                         }
1430
1431                         //
1432                         // If `target_type' is an interface and the type of `ic' implements the interface
1433                         // e.g. target_type is IComparable, IConvertible, IFormattable
1434                         //
1435                         if (target_type.IsInterface && target_type.IsAssignableFrom (ic.Type))
1436                                 return new BoxedCast (ic);
1437
1438                         return null;
1439                 }
1440
1441                 /// <summary>
1442                 ///   Attempts to perform an implicit constant conversion of the IntConstant
1443                 ///   into a different data type using casts (See Implicit Constant
1444                 ///   Expression Conversions)
1445                 /// </summary>
1446                 static public Expression WideningConstantConversions (Type target_type, Constant const_expr)
1447                 {
1448                         Constant ret_expr;
1449                         
1450                         Type const_expr_type = const_expr.Type;
1451                         Location loc = const_expr.Location;
1452
1453                         if (target_type == TypeManager.byte_type){
1454                                 if (const_expr_type == TypeManager.short_type ||
1455                                         const_expr_type == TypeManager.int32_type ||
1456                                         const_expr_type == TypeManager.int64_type)
1457                                                 return const_expr.ToByte (loc);
1458                         }
1459
1460                         if (target_type == TypeManager.short_type){
1461                                 if (const_expr_type == TypeManager.int32_type ||
1462                                         const_expr_type == TypeManager.int64_type)
1463                                                 return const_expr.ToShort (loc);
1464                         }
1465
1466                         if (target_type == TypeManager.int32_type){
1467                                 if (const_expr_type == TypeManager.int64_type)
1468                                         return const_expr.ToInt (loc);
1469                         } 
1470
1471                         if (target_type == TypeManager.float_type) {
1472                                 if (const_expr_type == TypeManager.double_type)
1473                                         return const_expr.ToDouble (loc);
1474                         }
1475                         
1476                         return null;
1477                 }
1478
1479                 static public Constant NothingToPrimitiveConstants (Expression expr, Type target_type)
1480                 {
1481                         NullLiteral null_literal = (NullLiteral) expr;
1482                         Location loc = null_literal.Location;
1483                         Type real_target_type = target_type ;
1484                         Constant retval = null;
1485                         
1486                         if (null_literal == null) 
1487                                 throw new Exception ("FIXME: I was expecting that I would always get only NullLiterals");
1488
1489                         if (target_type.IsSubclassOf(TypeManager.enum_type))
1490                                 real_target_type = TypeManager.EnumToUnderlying (target_type);
1491
1492                         if (real_target_type == TypeManager.bool_type)
1493                                 retval = null_literal.ToBoolean (loc);
1494                         else if (real_target_type == TypeManager.byte_type)
1495                                 retval = null_literal.ToByte (loc);
1496                         else if (real_target_type == TypeManager.short_type)
1497                                 retval = null_literal.ToShort (loc);
1498                         else if (real_target_type == TypeManager.int32_type)
1499                                 retval = null_literal.ToInt (loc);
1500                         else if (real_target_type == TypeManager.int64_type)
1501                                 null_literal.ToLong (loc);
1502                         else if (real_target_type == TypeManager.decimal_type)
1503                                 retval = null_literal.ToDecimal (loc);
1504                         else if (real_target_type == TypeManager.float_type)
1505                                 retval = null_literal.ToLong (loc);
1506                         else if (real_target_type == TypeManager.double_type)
1507                                 retval = null_literal.ToDouble (loc);
1508                         else if (real_target_type == TypeManager.char_type)
1509                                 retval = null_literal.ToChar (loc);
1510                         else if (real_target_type == TypeManager.string_type)
1511                                 retval = new StringConstant (null);
1512                         
1513                         if (real_target_type != target_type && retval != null)
1514                                 retval = new EnumConstant (retval, target_type);
1515
1516                         return retval;
1517                 }
1518
1519                 static public void Error_CannotWideningConversion (Location loc, Type source, Type target)
1520                 {
1521                         if (source.Name == target.Name){
1522                                 Report.ExtraInformation (loc,
1523                                          String.Format (
1524                                                 "The type {0} has two conflicting definitons, one comes from {0} and the other from {1}",
1525                                                 source.Assembly.FullName, target.Assembly.FullName));
1526                                                          
1527                         }
1528                         Report.Error (29, loc, "Cannot convert implicitly from {0} to `{1}'",
1529                                       source == TypeManager.anonymous_method_type ?
1530                                       "anonymous method" : "`" + TypeManager.CSharpName (source) + "'",
1531                                       TypeManager.CSharpName (target));
1532                 }
1533
1534                 /// <summary>
1535                 ///   Attempts to implicitly convert `source' into `target_type', using
1536                 ///   WideningConversion.  If there is no implicit conversion, then
1537                 ///   an error is signaled
1538                 /// </summary>
1539                 static public Expression WideningConversionRequired (EmitContext ec, Expression source,
1540                                                                      Type target_type, Location loc)
1541                 {
1542                         Expression e;
1543
1544                         int errors = Report.Errors;
1545                         e = WideningConversion (ec, source, target_type, loc);
1546                         if (Report.Errors > errors)
1547                                 return null;
1548                         if (e != null)
1549                                 return e;
1550
1551                         if (source is DoubleLiteral) {
1552                                 if (target_type == TypeManager.float_type) {
1553                                         Error_664 (loc, "float", "f");
1554                                         return null;
1555                                 }
1556                                 if (target_type == TypeManager.decimal_type) {
1557                                         Error_664 (loc, "decimal", "m");
1558                                         return null;
1559                                 }
1560                         }
1561
1562                         if (source is Constant){
1563                                 Constant c = (Constant) source;
1564
1565                                 Expression.Error_ConstantValueCannotBeConverted (loc, c.AsString (), target_type);
1566                                 return null;
1567                         }
1568                         
1569                         Error_CannotWideningConversion (loc, source.Type, target_type);
1570
1571                         return null;
1572                 }
1573
1574                 static void Error_664 (Location loc, string type, string suffix) {
1575                         Report.Error (664, loc,
1576                                 "Literal of type double cannot be implicitly converted to type '{0}'. Add suffix '{1}' to create a literal of this type",
1577                                 type, suffix);
1578                 }
1579
1580                 /// <summary>
1581                 ///   Performs the explicit numeric conversions
1582                 /// </summary>
1583
1584                 /// <summary>
1585                 ///   Performs the explicit numeric conversions
1586                 /// </summary>
1587                 static Expression NarrowingNumericConversion (EmitContext ec, Expression expr, Type target_type, Location loc)
1588                 {
1589                         Type expr_type = expr.Type;
1590
1591                         //
1592                         // If we have an enumeration, extract the underlying type,
1593                         // use this during the comparison, but wrap around the original
1594                         // target_type
1595                         //
1596                         Type real_target_type = target_type;
1597
1598                         if (TypeManager.IsEnumType (real_target_type))
1599                                 real_target_type = TypeManager.EnumToUnderlying (real_target_type);
1600
1601                         if (WideningStandardConversionExists (ec, expr, real_target_type)){
1602                                 Expression ce = WideningConversionStandard (ec, expr, real_target_type, loc);
1603
1604                                 if (real_target_type != target_type)
1605                                         return new EmptyCast (ce, target_type);
1606                                 return ce;
1607                         }
1608                         
1609                         if (expr_type == TypeManager.sbyte_type){
1610                                 //
1611                                 // From sbyte to byte, ushort, uint, ulong, char
1612                                 //
1613                                 if (real_target_type == TypeManager.byte_type)
1614                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U1);
1615                                 if (real_target_type == TypeManager.ushort_type)
1616                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U2);
1617                                 if (real_target_type == TypeManager.uint32_type)
1618                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U4);
1619                                 if (real_target_type == TypeManager.uint64_type)
1620                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U8);
1621                                 if (real_target_type == TypeManager.char_type)
1622                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_CH);
1623                         } else if (expr_type == TypeManager.byte_type){
1624                                 //
1625                                 // From byte to sbyte and char
1626                                 //
1627                                 if (real_target_type == TypeManager.sbyte_type)
1628                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U1_I1);
1629                         } else if (expr_type == TypeManager.short_type){
1630                                 //
1631                                 // From short to byte
1632                                 //
1633                                 if (real_target_type == TypeManager.sbyte_type)
1634                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_I1);
1635                                 if (real_target_type == TypeManager.byte_type)
1636                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U1);
1637                                 if (real_target_type == TypeManager.ushort_type)
1638                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U2);
1639                                 if (real_target_type == TypeManager.uint32_type)
1640                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U4);
1641                                 if (real_target_type == TypeManager.uint64_type)
1642                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U8);
1643                         } else if (expr_type == TypeManager.ushort_type){
1644                                 //
1645                                 // From ushort to sbyte, byte, short, char
1646                                 //
1647                                 if (real_target_type == TypeManager.sbyte_type)
1648                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_I1);
1649                                 if (real_target_type == TypeManager.byte_type)
1650                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_U1);
1651                                 if (real_target_type == TypeManager.short_type)
1652                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_I2);
1653                                 if (real_target_type == TypeManager.char_type)
1654                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_CH);
1655                         } else if (expr_type == TypeManager.int32_type){
1656                                 //
1657                                 // From int to byte, short
1658                                 //
1659                                 if (real_target_type == TypeManager.sbyte_type)
1660                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I1);
1661                                 if (real_target_type == TypeManager.byte_type)
1662                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U1);
1663                                 if (real_target_type == TypeManager.short_type)
1664                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I2);
1665                                 if (real_target_type == TypeManager.ushort_type)
1666                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U2);
1667                                 if (real_target_type == TypeManager.uint32_type)
1668                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U4);
1669                                 if (real_target_type == TypeManager.uint64_type)
1670                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U8);
1671                         } else if (expr_type == TypeManager.uint32_type){
1672                                 //
1673                                 // From uint to sbyte, byte, short, ushort, int, char
1674                                 //
1675                                 if (real_target_type == TypeManager.sbyte_type)
1676                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I1);
1677                                 if (real_target_type == TypeManager.byte_type)
1678                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U1);
1679                                 if (real_target_type == TypeManager.short_type)
1680                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I2);
1681                                 if (real_target_type == TypeManager.ushort_type)
1682                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U2);
1683                                 if (real_target_type == TypeManager.int32_type)
1684                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I4);
1685                                 if (real_target_type == TypeManager.char_type)
1686                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_CH);
1687                         } else if (expr_type == TypeManager.int64_type){
1688                                 //
1689                                 // From long to byte, short, int
1690                                 //
1691                                 if (real_target_type == TypeManager.sbyte_type)
1692                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I1);
1693                                 if (real_target_type == TypeManager.byte_type)
1694                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U1);
1695                                 if (real_target_type == TypeManager.short_type)
1696                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I2);
1697                                 if (real_target_type == TypeManager.ushort_type)
1698                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U2);
1699                                 if (real_target_type == TypeManager.int32_type)
1700                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I4);
1701                                 if (real_target_type == TypeManager.uint32_type)
1702                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U4);
1703                                 if (real_target_type == TypeManager.uint64_type)
1704                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U8);
1705                         } else if (expr_type == TypeManager.uint64_type){
1706                                 //
1707                                 // From ulong to sbyte, byte, short, ushort, int, uint, long, char
1708                                 //
1709                                 if (real_target_type == TypeManager.sbyte_type)
1710                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I1);
1711                                 if (real_target_type == TypeManager.byte_type)
1712                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U1);
1713                                 if (real_target_type == TypeManager.short_type)
1714                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I2);
1715                                 if (real_target_type == TypeManager.ushort_type)
1716                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U2);
1717                                 if (real_target_type == TypeManager.int32_type)
1718                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I4);
1719                                 if (real_target_type == TypeManager.uint32_type)
1720                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U4);
1721                                 if (real_target_type == TypeManager.int64_type)
1722                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I8);
1723                                 if (real_target_type == TypeManager.char_type)
1724                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_CH);
1725                         } else if (expr_type == TypeManager.float_type){
1726                                 //
1727                                 // From float to byte, short, int, long, decimal
1728                                 //
1729                                 if (real_target_type == TypeManager.sbyte_type)
1730                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I1);
1731                                 if (real_target_type == TypeManager.byte_type)
1732                                         return new FloatingToFixedCast (ec, expr, target_type, ConvCast.Mode.R8_U1);
1733                                 if (real_target_type == TypeManager.short_type)
1734                                         return new FloatingToFixedCast (ec, expr, target_type, ConvCast.Mode.R8_I2);
1735                                 if (real_target_type == TypeManager.ushort_type)
1736                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U2);
1737                                 if (real_target_type == TypeManager.int32_type)
1738                                         return new FloatingToFixedCast (ec, expr, target_type, ConvCast.Mode.R8_I4);
1739                                 if (real_target_type == TypeManager.uint32_type)
1740                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U4);
1741                                 if (real_target_type == TypeManager.int64_type)
1742                                         return new FloatingToFixedCast (ec, expr, target_type, ConvCast.Mode.R8_I8);
1743                                 if (real_target_type == TypeManager.uint64_type)
1744                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U8);
1745                                 if (real_target_type == TypeManager.decimal_type)
1746                                         return new ImplicitNew (ec, "System", "Decimal", loc, expr);    
1747                         } else if (expr_type == TypeManager.double_type){
1748                                 //
1749                                 // From double to byte, short, int, long, float, decimal
1750                                 //
1751                                 if (real_target_type == TypeManager.sbyte_type)
1752                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I1);
1753                                 if (real_target_type == TypeManager.byte_type)
1754                                         return new FloatingToFixedCast (ec, expr, target_type, ConvCast.Mode.R8_U1);
1755                                 if (real_target_type == TypeManager.short_type)
1756                                         return new FloatingToFixedCast (ec, expr, target_type, ConvCast.Mode.R8_I2);
1757                                 if (real_target_type == TypeManager.ushort_type)
1758                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U2);
1759                                 if (real_target_type == TypeManager.int32_type)
1760                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I4);
1761                                 if (real_target_type == TypeManager.uint32_type)
1762                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U4);
1763                                 if (real_target_type == TypeManager.int64_type)
1764                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I8);
1765                                 if (real_target_type == TypeManager.uint64_type)
1766                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U8);
1767
1768                                 if (real_target_type == TypeManager.float_type)
1769                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4);
1770                                 if (real_target_type == TypeManager.decimal_type)
1771                                         return new ImplicitNew (ec, "System", "Decimal", loc, expr);
1772                         } else if (expr_type == TypeManager.decimal_type){
1773                                 //
1774                                 // From decimal to byte, short, int, long
1775                                 //
1776                                 if (real_target_type == TypeManager.byte_type)
1777                                         return new HelperMethodInvocation (ec, loc, TypeManager.byte_type, TypeManager.convert_to_byte_decimal, expr);  
1778                                 if (real_target_type == TypeManager.short_type)
1779                                         return new HelperMethodInvocation (ec, loc, TypeManager.short_type, TypeManager.convert_to_int16_decimal, expr);        
1780                                 if (real_target_type == TypeManager.int32_type)
1781                                         return new HelperMethodInvocation (ec, loc, TypeManager.int32_type, TypeManager.convert_to_int32_decimal, expr);        
1782                                 if (real_target_type == TypeManager.int64_type)
1783                                         return new HelperMethodInvocation (ec, loc, TypeManager.int64_type, TypeManager.convert_to_int64_decimal, expr);        
1784                         } 
1785
1786                         return null;
1787                 }
1788
1789                 /// <summary> 
1790                 /// VB.NET specific: Convert to and from boolean
1791                 /// </summary>
1792
1793                 static public Expression BooleanConversions (EmitContext ec, Expression expr,
1794                                                                     Type target_type, Location loc)
1795                 {
1796                         Type expr_type = expr.Type;
1797                         Type real_target_type = target_type;
1798
1799                         if (expr_type == TypeManager.bool_type) {
1800
1801                                 //
1802                                 // From boolean to byte, short, int,
1803                                 // long, float, double, decimal
1804                                 //
1805
1806                                 if (real_target_type == TypeManager.byte_type)
1807                                         return new BooleanToNumericCast (expr, target_type, OpCodes.Conv_U1);
1808                                 if (real_target_type == TypeManager.short_type)
1809                                         return new BooleanToNumericCast (expr, target_type, OpCodes.Conv_I2);
1810                                 if (real_target_type == TypeManager.int32_type)
1811                                         return new BooleanToNumericCast (expr, target_type, OpCodes.Conv_I4);
1812                                 if (real_target_type == TypeManager.int64_type)
1813                                         return new BooleanToNumericCast (expr, target_type, OpCodes.Conv_I8);
1814                                 if (real_target_type == TypeManager.float_type)
1815                                         return new BooleanToNumericCast (expr, target_type, OpCodes.Conv_R4);
1816                                 if (real_target_type == TypeManager.double_type)
1817                                         return new BooleanToNumericCast (expr, target_type, OpCodes.Conv_R8);
1818                                 if (real_target_type == TypeManager.decimal_type) {
1819                                         return new HelperMethodInvocation (ec, expr.Location, TypeManager.decimal_type, TypeManager.msvbcs_decimaltype_from_boolean, expr);
1820                                 }
1821                         } if (real_target_type == TypeManager.bool_type) {
1822
1823                                 //
1824                                 // From byte, short, int, long, float,
1825                                 // double, decimal to boolean
1826                                 //
1827
1828                                 if (expr_type == TypeManager.byte_type ||
1829                                         expr_type == TypeManager.short_type ||
1830                                         expr_type == TypeManager.int32_type ||
1831                                         expr_type == TypeManager.int64_type || 
1832                                         expr_type == TypeManager.float_type || 
1833                                         expr_type == TypeManager.double_type)
1834                                                 return new NumericToBooleanCast (expr, expr_type);
1835                                 if (expr_type == TypeManager.decimal_type) {
1836                                         return new HelperMethodInvocation (ec, expr.Location, TypeManager.bool_type, TypeManager.convert_to_boolean_decimal, expr);
1837                                 }
1838                         }
1839
1840                         return null;
1841                 }
1842
1843                 /// <summary> 
1844                 /// VB.NET specific: Widening conversions to string
1845                 /// </summary>
1846
1847                 static public Expression WideningStringConversions (EmitContext ec, Expression expr,
1848                                                                     Type target_type, Location loc)
1849
1850                 {
1851                         Type expr_type = expr.Type;
1852                         Type real_target_type = target_type;
1853
1854                         if (real_target_type == TypeManager.string_type) {
1855                                 //
1856                                 // From char to string
1857                                 //
1858                                 if (expr_type == TypeManager.char_type)
1859                                         return new HelperMethodInvocation (ec, expr.Location, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_char, expr);
1860                         }
1861
1862                         if(expr_type.IsArray && (expr_type.GetElementType() == TypeManager.char_type)) {
1863                                 //
1864                                 // From char array to string
1865                                 //
1866                                 return new ImplicitNew (ec, "System", "String", loc, expr);
1867                         }
1868
1869                         return null;
1870                 }
1871                 
1872                 /// <summary> 
1873                 /// VB.NET specific: Narrowing conversions involving strings
1874                 /// </summary>
1875
1876                 static public Expression NarrowingStringConversions (EmitContext ec, Expression expr,
1877                                                                     Type target_type, Location loc)
1878                 {
1879                         Type expr_type = expr.Type;
1880                         Type real_target_type = target_type;
1881
1882                         // FIXME: Need to take care of Constants
1883
1884                         if (expr_type == TypeManager.string_type) {
1885
1886                                 //
1887                                 // From string to chararray, bool,
1888                                 // byte, short, char, int, long,
1889                                 // float, double, decimal and date 
1890                                 //
1891
1892 //                              if (real_target_type.IsArray && (real_target_type.GetElementType() == TypeManager.char_type))
1893 //                                      return new HelperMethodInvocation (ec, loc, TypeManager.char_array_type, TypeManager.msvbcs_char_array_type_from_string, loc, expr);
1894                                 if (real_target_type == TypeManager.bool_type)
1895                                         return new HelperMethodInvocation (ec, loc, TypeManager.bool_type, TypeManager.msvbcs_booleantype_from_string, expr);
1896                                 if (real_target_type == TypeManager.byte_type)
1897                                         return new HelperMethodInvocation (ec, loc, TypeManager.byte_type, TypeManager.msvbcs_bytetype_from_string, expr);
1898                                 if (real_target_type == TypeManager.short_type)
1899                                         return new HelperMethodInvocation (ec, loc, TypeManager.short_type, TypeManager.msvbcs_shorttype_from_string, expr);
1900                                 if (real_target_type == TypeManager.char_type)
1901                                         return new HelperMethodInvocation (ec, loc, TypeManager.char_type, TypeManager.msvbcs_chartype_from_string, expr);
1902                                 if (real_target_type == TypeManager.int32_type)
1903                                         return new HelperMethodInvocation (ec, loc, TypeManager.int32_type, TypeManager.msvbcs_integertype_from_string, expr);
1904                                 if (real_target_type == TypeManager.int64_type)
1905                                         return new HelperMethodInvocation (ec, loc, TypeManager.int64_type, TypeManager.msvbcs_longtype_from_string, expr);
1906                                 if (real_target_type == TypeManager.float_type)
1907                                         return new HelperMethodInvocation (ec, loc, TypeManager.float_type, TypeManager.msvbcs_singletype_from_string, expr);
1908                                 if (real_target_type == TypeManager.double_type)
1909                                         return new HelperMethodInvocation (ec, loc, TypeManager.double_type, TypeManager.msvbcs_doubletype_from_string, expr);
1910                                 if (real_target_type == TypeManager.decimal_type)
1911                                         return new HelperMethodInvocation (ec, loc, TypeManager.decimal_type, TypeManager.msvbcs_decimaltype_from_string, expr);
1912                                 if (real_target_type == TypeManager.date_type)
1913                                         return new HelperMethodInvocation (ec, loc, TypeManager.date_type, TypeManager.msvbcs_datetype_from_string, expr);
1914                         } if (real_target_type == TypeManager.string_type) {
1915
1916                                 //
1917                                 // From bool, byte, short, char, int,
1918                                 // long, float, double, decimal and
1919                                 // date to string
1920                                 //
1921
1922                                 if (expr_type == TypeManager.bool_type)
1923                                         return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_boolean, expr);
1924                                 if (expr_type == TypeManager.byte_type)
1925                                         return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_byte, expr);
1926                                 if (expr_type == TypeManager.short_type)
1927                                         return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_short, expr);
1928                                 if (expr_type == TypeManager.int32_type)
1929                                         return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_integer, expr);
1930                                 if (expr_type == TypeManager.int64_type)
1931                                         return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_long, expr);
1932                                 if (expr_type == TypeManager.float_type)
1933                                         return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_single, expr);
1934                                 if (expr_type == TypeManager.double_type)
1935                                         return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_double, expr);
1936                                 if (expr_type == TypeManager.decimal_type)
1937                                         return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_decimal, expr);
1938                                 if (expr_type == TypeManager.date_type)
1939                                         return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_date, expr);
1940                         }
1941
1942                         return null;
1943                 }
1944
1945
1946                 /// <summary> 
1947                 /// VB.NET specific: Conversions from Object to Primitive Types
1948                 /// </summary>
1949
1950                 static public Expression ObjectTypeToPrimitiveTypes (EmitContext ec, Expression expr,
1951                                                                     Type target_type, Location loc)
1952                 {
1953                         Type expr_type = expr.Type;
1954                         Type real_target_type = target_type;
1955                         MethodInfo helper_method = null;
1956                         Expression retexpr;
1957
1958                         if (expr_type != TypeManager.object_type)
1959                                 return null;
1960
1961                         if (target_type.IsSubclassOf (TypeManager.enum_type))
1962                                 real_target_type = TypeManager.EnumToUnderlying (target_type);
1963                         
1964
1965                         if (real_target_type == TypeManager.bool_type)
1966                                 helper_method = TypeManager.msvbcs_booleantype_fromobject_object;
1967                         if (real_target_type == TypeManager.byte_type)
1968                                 helper_method = TypeManager.msvbcs_bytetype_fromobject_object;
1969                         if (real_target_type == TypeManager.short_type)
1970                                 helper_method = TypeManager.msvbcs_shorttype_fromobject_object;
1971                         if (real_target_type == TypeManager.char_type)
1972                                 helper_method = TypeManager.msvbcs_chartype_fromobject_object;
1973                         if (real_target_type == TypeManager.int32_type)
1974                                 helper_method = TypeManager.msvbcs_integertype_fromobject_object;
1975                         if (real_target_type == TypeManager.int64_type)
1976                                 helper_method = TypeManager.msvbcs_longtype_fromobject_object;
1977                         if (real_target_type == TypeManager.float_type)
1978                                 helper_method = TypeManager.msvbcs_singletype_fromobject_object;
1979                         if (real_target_type == TypeManager.double_type)
1980                                 helper_method = TypeManager.msvbcs_doubletype_fromobject_object;
1981                         if (real_target_type == TypeManager.decimal_type)
1982                                 helper_method = TypeManager.msvbcs_decimaltype_fromobject_object;
1983                         if (real_target_type == TypeManager.date_type)
1984                                 helper_method = TypeManager.msvbcs_datetype_fromobject_object;
1985                         if (real_target_type == TypeManager.string_type)
1986                                 helper_method = TypeManager.msvbcs_stringtype_fromobject_object;
1987
1988                         if (helper_method !=  null) {
1989                                 retexpr = new HelperMethodInvocation (ec, loc, real_target_type, helper_method, expr);
1990                                 if (target_type != real_target_type)
1991                                         retexpr = new EmptyCast (retexpr, target_type);
1992
1993                                 return retexpr;
1994                         }
1995
1996                         return null;
1997                 }
1998                 
1999
2000                 /// <summary>
2001                 ///  Returns whether an explicit reference conversion can be performed
2002                 ///  from source_type to target_type
2003                 /// </summary>
2004                 public static bool NarrowingReferenceConversionExists (Type source_type, Type target_type)
2005                 {
2006                         bool target_is_type_param = target_type.IsGenericParameter;
2007                         bool target_is_value_type = target_type.IsValueType;
2008                         
2009                         if (source_type == target_type)
2010                                 return true;
2011                         
2012                         //
2013                         // From generic parameter to any type
2014                         //
2015                         if (source_type.IsGenericParameter)
2016                                 return true;
2017
2018                         //
2019                         // From object to a generic parameter
2020                         //
2021                         if (source_type == TypeManager.object_type && target_is_type_param)
2022                                 return true;
2023
2024                         //
2025                         // From object to any reference type
2026                         //
2027                         if (source_type == TypeManager.object_type && !target_is_value_type)
2028                                 return true;
2029                                         
2030                         //
2031                         // From any class S to any class-type T, provided S is a base class of T
2032                         //
2033                         if (TypeManager.IsSubclassOf (target_type, source_type))
2034                                 return true;
2035
2036                         //
2037                         // From any interface type S to any interface T provided S is not derived from T
2038                         //
2039                         if (source_type.IsInterface && target_type.IsInterface){
2040                                 if (!TypeManager.IsSubclassOf (target_type, source_type))
2041                                         return true;
2042                         }
2043                             
2044                         //
2045                         // From any class type S to any interface T, provided S is not sealed
2046                         // and provided S does not implement T.
2047                         //
2048                         if (target_type.IsInterface && !source_type.IsSealed &&
2049                             !TypeManager.ImplementsInterface (source_type, target_type))
2050                                 return true;
2051
2052                         //
2053                         // From any interface-type S to to any class type T, provided T is not
2054                         // sealed, or provided T implements S.
2055                         //
2056                         if (source_type.IsInterface &&
2057                             (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type)))
2058                                 return true;
2059                         
2060                         
2061                         // From an array type S with an element type Se to an array type T with an 
2062                         // element type Te provided all the following are true:
2063                         //     * S and T differe only in element type, in other words, S and T
2064                         //       have the same number of dimensions.
2065                         //     * Both Se and Te are reference types
2066                         //     * An explicit referenc conversions exist from Se to Te
2067                         //
2068                         if (source_type.IsArray && target_type.IsArray) {
2069                                 if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
2070                                         
2071                                         Type source_element_type = TypeManager.GetElementType (source_type);
2072                                         Type target_element_type = TypeManager.GetElementType (target_type);
2073
2074                                         if (source_element_type.IsGenericParameter ||
2075                                             (!source_element_type.IsValueType && !target_element_type.IsValueType))
2076                                                 if (NarrowingReferenceConversionExists (source_element_type,
2077                                                                                        target_element_type))
2078                                                         return true;
2079                                 }
2080                         }
2081                         
2082
2083                         // From System.Array to any array-type
2084                         if (source_type == TypeManager.array_type &&
2085                             target_type.IsArray){
2086                                 return true;
2087                         }
2088
2089                         //
2090                         // From System delegate to any delegate-type
2091                         //
2092                         if (source_type == TypeManager.delegate_type &&
2093                             TypeManager.IsDelegateType (target_type))
2094                                 return true;
2095
2096                         //
2097                         // From ICloneable to Array or Delegate types
2098                         //
2099                         if (source_type == TypeManager.icloneable_type &&
2100                             (target_type == TypeManager.array_type ||
2101                              target_type == TypeManager.delegate_type))
2102                                 return true;
2103                         
2104                         return false;
2105                 }
2106
2107                 /// <summary>
2108                 ///   Implements Explicit Reference conversions
2109                 /// </summary>
2110                 static Expression NarrowingReferenceConversion (Expression source, Type target_type)
2111                 {
2112                         Type source_type = source.Type;
2113                         bool target_is_type_param = target_type.IsGenericParameter;
2114                         bool target_is_value_type = target_type.IsValueType;
2115
2116                         //
2117                         // From object to a generic parameter
2118                         //
2119                         if (source_type == TypeManager.object_type && target_is_type_param)
2120                                 return new UnboxCast (source, target_type);
2121
2122                         //
2123                         // From object to any reference type
2124                         //
2125                         if (source_type == TypeManager.object_type && !target_is_value_type)
2126                                 return new ClassCast (source, target_type);
2127
2128                         //
2129                         // Unboxing conversion.
2130                         //
2131                         if (((source_type == TypeManager.enum_type &&
2132                                 !(source is EmptyCast)) ||
2133                                 source_type == TypeManager.value_type) && target_is_value_type)
2134                                 return new UnboxCast (source, target_type);
2135
2136                         //
2137                         // From any class S to any class-type T, provided S is a base class of T
2138                         //
2139                         if (TypeManager.IsSubclassOf (target_type, source_type))
2140                                 return new ClassCast (source, target_type);
2141
2142                         //
2143                         // From any interface type S to any interface T provided S is not derived from T
2144                         //
2145                         if (source_type.IsInterface && target_type.IsInterface){
2146                                 if (TypeManager.ImplementsInterface (source_type, target_type))
2147                                         return null;
2148                                 else
2149                                         return new ClassCast (source, target_type);
2150                         }
2151
2152                         //
2153                         // From any class type S to any interface T, provides S is not sealed
2154                         // and provided S does not implement T.
2155                         //
2156                         if (target_type.IsInterface && !source_type.IsSealed) {
2157                                 if (TypeManager.ImplementsInterface (source_type, target_type))
2158                                         return null;
2159                                 else
2160                                         return new ClassCast (source, target_type);
2161                                 
2162                         }
2163
2164                         //
2165                         // From any interface-type S to to any class type T, provided T is not
2166                         // sealed, or provided T implements S.
2167                         //
2168                         if (source_type.IsInterface) {
2169                                 if (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type)) {
2170                                         if (target_type.IsClass)
2171                                                 return new ClassCast (source, target_type);
2172                                         else
2173                                                 return new UnboxCast (source, target_type);
2174                                 }
2175
2176                                 return null;
2177                         }
2178                         
2179                         // From an array type S with an element type Se to an array type T with an 
2180                         // element type Te provided all the following are true:
2181                         //     * S and T differe only in element type, in other words, S and T
2182                         //       have the same number of dimensions.
2183                         //     * Both Se and Te are reference types
2184                         //     * An explicit referenc conversions exist from Se to Te
2185                         //
2186                         if (source_type.IsArray && target_type.IsArray) {
2187                                 if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
2188                                         
2189                                         Type source_element_type = TypeManager.GetElementType (source_type);
2190                                         Type target_element_type = TypeManager.GetElementType (target_type);
2191                                         
2192                                         if (!source_element_type.IsValueType && !target_element_type.IsValueType)
2193                                                 if (NarrowingReferenceConversionExists (source_element_type,
2194                                                                                        target_element_type))
2195                                                         return new ClassCast (source, target_type);
2196                                 }
2197                         }
2198                         
2199
2200                         // From System.Array to any array-type
2201                         if (source_type == TypeManager.array_type &&
2202                             target_type.IsArray) {
2203                                 return new ClassCast (source, target_type);
2204                         }
2205
2206                         //
2207                         // From System delegate to any delegate-type
2208                         //
2209                         if (source_type == TypeManager.delegate_type &&
2210                             TypeManager.IsDelegateType (target_type))
2211                                 return new ClassCast (source, target_type);
2212
2213                         //
2214                         // From ICloneable to Array or Delegate types
2215                         //
2216                         if (source_type == TypeManager.icloneable_type &&
2217                             (target_type == TypeManager.array_type ||
2218                              target_type == TypeManager.delegate_type))
2219                                 return new ClassCast (source, target_type);
2220                         
2221                         return null;
2222                 }
2223                 
2224                 /// <summary>
2225                 ///   Performs an explicit conversion of the expression `expr' whose
2226                 ///   type is expr.Type to `target_type'.
2227                 /// </summary>
2228                 static public Expression WideningAndNarrowingConversion (EmitContext ec, Expression expr,
2229                                                              Type target_type, Location loc)
2230                 {
2231                         Type expr_type = expr.Type;
2232                         Type original_expr_type = expr_type;
2233
2234                         if (expr_type.IsSubclassOf (TypeManager.enum_type)){
2235                                 if (target_type == TypeManager.enum_type ||
2236                                     target_type == TypeManager.object_type) {
2237                                         if (expr is EnumConstant)
2238                                                 expr = ((EnumConstant) expr).Child;
2239                                         // We really need all these casts here .... :-(
2240                                         expr = new BoxedCast (new EmptyCast (expr, expr_type));
2241                                         return new EmptyCast (expr, target_type);
2242                                 } else if ((expr_type == TypeManager.enum_type) && target_type.IsValueType &&
2243                                            target_type.IsSubclassOf (TypeManager.enum_type))
2244                                         return new UnboxCast (expr, target_type);
2245
2246                                 //
2247                                 // Notice that we have kept the expr_type unmodified, which is only
2248                                 // used later on to 
2249                                 if (expr is EnumConstant)
2250                                         expr = ((EnumConstant) expr).Child;
2251                                 else
2252                                         expr = new EmptyCast (expr, TypeManager.EnumToUnderlying (expr_type));
2253                                 expr_type = expr.Type;
2254                         }
2255
2256                         int errors = Report.Errors;
2257                         Expression ne = WideningConversionStandard (ec, expr, target_type, loc);
2258                         if (Report.Errors > errors)
2259                                 return null;
2260
2261                         if (ne != null)
2262                                 return ne;
2263
2264                         if (TypeManager.IsNullableType (expr.Type) && TypeManager.IsNullableType (target_type))
2265                                 return new Nullable.LiftedConversion (
2266                                         expr, target_type, false, true, loc).Resolve (ec);
2267
2268                         ne = NarrowingNumericConversion (ec, expr, target_type, loc);
2269                         if (ne != null)
2270                                 return ne;
2271
2272                         //
2273                         // Unboxing conversion.
2274                         //
2275
2276                         //
2277                         // VB.NET treats conversions from object to
2278                         // the primitive types using the helper
2279                         // routines in Microsoft.VisualBasic.dll
2280                         //
2281
2282                         ne = ObjectTypeToPrimitiveTypes(ec, expr, target_type, loc);
2283                         if (ne != null)
2284                                 return ne;
2285                         
2286                         if (expr_type == TypeManager.object_type && target_type.IsValueType)
2287                                 return new UnboxCast (expr, target_type);
2288
2289                         //
2290                         // Skip the NarrowingReferenceConversion because we can not convert
2291                         // from Null to a ValueType, and ExplicitReference wont check against
2292                         // null literal explicitly
2293                         //
2294                         if (expr_type != TypeManager.null_type){
2295                                 ne = NarrowingReferenceConversion (expr, target_type);
2296                                 if (ne != null)
2297                                         return ne;
2298                         }
2299
2300                 skip_explicit:
2301                         if (ec.InUnsafe){
2302                                 if (target_type.IsPointer){
2303                                         if (expr_type.IsPointer)
2304                                                 return new EmptyCast (expr, target_type);
2305                                         
2306                                         if (expr_type == TypeManager.sbyte_type ||
2307                                             expr_type == TypeManager.byte_type ||
2308                                             expr_type == TypeManager.short_type ||
2309                                             expr_type == TypeManager.ushort_type ||
2310                                             expr_type == TypeManager.int32_type ||
2311                                             expr_type == TypeManager.uint32_type ||
2312                                             expr_type == TypeManager.uint64_type ||
2313                                             expr_type == TypeManager.int64_type)
2314                                                 return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
2315                                 }
2316                                 if (expr_type.IsPointer){
2317                                         Expression e = null;
2318                                         
2319                                         if (target_type == TypeManager.sbyte_type)
2320                                                 e = new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
2321                                         else if (target_type == TypeManager.byte_type)
2322                                                 e = new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
2323                                         else if (target_type == TypeManager.short_type)
2324                                                 e = new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
2325                                         else if (target_type == TypeManager.ushort_type)
2326                                                 e = new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
2327                                         else if (target_type == TypeManager.int32_type)
2328                                                 e = new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
2329                                         else if (target_type == TypeManager.uint32_type)
2330                                                 e = new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
2331                                         else if (target_type == TypeManager.uint64_type)
2332                                                 e = new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
2333                                         else if (target_type == TypeManager.int64_type){
2334                                                 e = new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
2335                                         }
2336
2337                                         if (e != null){
2338                                                 Expression ci, ce;
2339
2340                                                 ci = WideningConversionStandard (ec, e, target_type, loc);
2341
2342                                                 if (ci != null)
2343                                                         return ci;
2344
2345                                                 ce = NarrowingNumericConversion (ec, e, target_type, loc);
2346                                                 if (ce != null)
2347                                                         return ce;
2348                                                 //
2349                                                 // We should always be able to go from an uint32
2350                                                 // implicitly or explicitly to the other integral
2351                                                 // types
2352                                                 //
2353                                                 throw new Exception ("Internal compiler error");
2354                                         }
2355                                 }
2356                         }
2357
2358                         //
2359                         // VB.NET specific conversions
2360                         //
2361
2362                         ne = BooleanConversions (ec, expr, target_type, loc);
2363                         if (ne != null)
2364                                 return ne;
2365
2366                         ne = NarrowingStringConversions (ec, expr, target_type, loc);
2367                         if (ne != null)
2368                                 return ne;
2369                         
2370                         
2371                         //
2372                         // VB.NET has no notion of User defined conversions
2373                         //
2374
2375 //                      ne = ExplicitUserConversion (ec, expr, target_type, loc);
2376 //                      if (ne != null)
2377 //                              return ne;
2378
2379                         if (expr is NullLiteral){
2380                                 Report.Error (37, loc, "Cannot convert null to value type `" +
2381                                               TypeManager.CSharpName (target_type) + "'");
2382                                 return null;
2383                         }
2384                                 
2385                         Error_CannotConvertType (loc, original_expr_type, target_type);
2386                         return null;
2387                 }
2388
2389                 /// <summary>
2390                 ///   Same as WideningAndNarrowingConversion, only it doesn't include user defined conversions
2391                 /// </summary>
2392                 static public Expression WideningAndNarrowingConversionStandard (EmitContext ec, Expression expr,
2393                                                                      Type target_type, Location l)
2394                 {
2395                         int errors = Report.Errors;
2396                         Expression ne = WideningConversionStandard (ec, expr, target_type, l);
2397                         if (Report.Errors > errors)
2398                                 return null;
2399
2400                         if (ne != null)
2401                                 return ne;
2402
2403                         if (TypeManager.IsNullableType (expr.Type) && TypeManager.IsNullableType (target_type))
2404                                 return new Nullable.LiftedConversion (
2405                                         expr, target_type, false, true, l).Resolve (ec);
2406
2407                         ne = NarrowingNumericConversion (ec, expr, target_type, l);
2408                         if (ne != null)
2409                                 return ne;
2410
2411                         ne = NarrowingReferenceConversion (expr, target_type);
2412                         if (ne != null)
2413                                 return ne;
2414
2415                         Error_CannotConvertType (l, expr.Type, target_type);
2416                         return null;
2417                 }
2418
2419                 /// <summary>
2420                 ///   Entry point for VB.NET specific implicit conversions
2421                 /// </summary>
2422                 static public Expression ImplicitVBConversion (EmitContext ec, Expression expr,
2423                                                              Type target_type, Location loc)
2424                 {
2425                         if (RootContext.StricterTypeChecking)
2426                                 return WideningConversion (ec, expr, target_type, loc);
2427                         else
2428                                 return WideningAndNarrowingConversion(ec, expr, target_type, loc);
2429                 }
2430
2431                 /// <summary>
2432                 ///   Mandates VB.NET specific implicit conversions
2433                 /// </summary>
2434                 static public Expression ImplicitVBConversionRequired (EmitContext ec, Expression source,
2435                                                                      Type target_type, Location loc)
2436                 {
2437                         Expression e;
2438
2439
2440                         int errors = Report.Errors;
2441                         e = ImplicitVBConversion (ec, source, target_type, loc);
2442                         if (Report.Errors > errors)
2443                                 return null;
2444                         if (e != null)
2445                                 return e;
2446
2447                         if (source is DoubleLiteral) {
2448                                 if (target_type == TypeManager.float_type) {
2449                                         Error_664 (loc, "float", "f");
2450                                         return null;
2451                                 }
2452                                 if (target_type == TypeManager.decimal_type) {
2453                                         Error_664 (loc, "decimal", "m");
2454                                         return null;
2455                                 }
2456                         }
2457
2458                         if (source is Constant){
2459                                 Constant c = (Constant) source;
2460
2461                                 Expression.Error_ConstantValueCannotBeConverted (loc, c.AsString (), target_type);
2462                                 return null;
2463                         }
2464                         
2465                         Error_CannotWideningConversion (loc, source.Type, target_type);
2466
2467                         return null;
2468                 }
2469
2470                 /// <summary>
2471                 ///   Entry point for VB.NET specific explicit conversions
2472                 /// </summary>
2473                 static public Expression ExplicitVBConversion (EmitContext ec, Expression expr,
2474                                                              Type target_type, Location loc)
2475                 {
2476                                 return WideningAndNarrowingConversion(ec, expr, target_type, loc);
2477                 }
2478
2479         }
2480 }