Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2817-BinPackingSpeedup/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/convert.cs

Last change on this file was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 74.5 KB
Line 
1//
2// conversion.cs: various routines for implementing conversions.
3//
4// Authors:
5//   Miguel de Icaza (miguel@ximian.com)
6//   Ravi Pratap (ravi@ximian.com)
7//   Marek Safar (marek.safar@gmail.com)
8//
9// Copyright 2001, 2002, 2003 Ximian, Inc.
10// Copyright 2003-2008 Novell, Inc.
11// Copyright 2011 Xamarin Inc (http://www.xamarin.com)
12//
13
14using System;
15using System.Collections.Generic;
16
17#if STATIC
18using IKVM.Reflection.Emit;
19#else
20using System.Reflection.Emit;
21#endif
22
23namespace Mono.CSharp {
24
25  //
26  // A container class for all the conversion operations
27  //
28  static class Convert
29  {
30    [Flags]
31    public enum UserConversionRestriction
32    {
33      None = 0,
34      ImplicitOnly = 1,
35      ProbingOnly = 1 << 1,
36      NullableSourceOnly = 1 << 2
37
38    }
39    //
40    // From a one-dimensional array-type S[] to System.Collections.IList<T> and base
41    // interfaces of this interface, provided there is an implicit reference conversion
42    // from S to T.
43    //
44    static bool ArrayToIList (ArrayContainer array, TypeSpec list, bool isExplicit)
45    {
46      if (array.Rank != 1 || !list.IsArrayGenericInterface)
47        return false;
48
49      var arg_type = list.TypeArguments[0];
50      if (array.Element == arg_type)
51        return true;
52
53      //
54      // Reject conversion from T[] to IList<U> even if T has U dependency
55      //
56      if (arg_type.IsGenericParameter)
57        return false;
58
59      if (isExplicit)
60        return ExplicitReferenceConversionExists (array.Element, arg_type);
61
62      return ImplicitReferenceConversionExists (array.Element, arg_type);
63    }
64   
65    static bool IList_To_Array(TypeSpec list, ArrayContainer array)
66    {
67      if (array.Rank != 1 || !list.IsArrayGenericInterface)
68        return false;
69
70      var arg_type = list.TypeArguments[0];
71      if (array.Element == arg_type)
72        return true;
73     
74      return ImplicitReferenceConversionExists (array.Element, arg_type) || ExplicitReferenceConversionExists (array.Element, arg_type);
75    }
76
77    public static Expression ImplicitTypeParameterConversion (Expression expr, TypeParameterSpec expr_type, TypeSpec target_type)
78    {
79      //
80      // From T to a type parameter U, provided T depends on U
81      //
82      if (target_type.IsGenericParameter) {
83        if (expr_type.TypeArguments != null && expr_type.HasDependencyOn (target_type)) {
84          if (expr == null)
85            return EmptyExpression.Null;
86
87          if (expr_type.IsReferenceType && !((TypeParameterSpec) target_type).IsReferenceType)
88            return new BoxedCast (expr, target_type);
89
90          return new ClassCast (expr, target_type);
91        }
92
93        return null;
94      }
95
96      //
97      // LAMESPEC: From T to dynamic type because it's like T to object
98      //
99      if (target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
100        if (expr == null)
101          return EmptyExpression.Null;
102
103        if (expr_type.IsReferenceType)
104          return new ClassCast (expr, target_type);
105
106        return new BoxedCast (expr, target_type);
107      }
108
109      //
110      // From T to its effective base class C
111      // From T to any base class of C (it cannot contain dynamic or be of dynamic type)
112      // From T to any interface implemented by C
113      //
114      var base_type = expr_type.GetEffectiveBase ();
115      if (base_type == target_type || TypeSpec.IsBaseClass (base_type, target_type, false) || base_type.ImplementsInterface (target_type, true)) {
116        if (expr == null)
117          return EmptyExpression.Null;
118
119        if (expr_type.IsReferenceType)
120          return new ClassCast (expr, target_type);
121
122        return new BoxedCast (expr, target_type);
123      }
124
125      if (target_type.IsInterface && expr_type.IsConvertibleToInterface (target_type)) {
126        if (expr == null)
127          return EmptyExpression.Null;
128
129        if (expr_type.IsReferenceType)
130          return new ClassCast (expr, target_type);
131
132        return new BoxedCast (expr, target_type);
133      }
134
135      return null;
136    }
137
138    static Expression ExplicitTypeParameterConversionFromT (Expression source, TypeSpec source_type, TypeSpec target_type)
139    {
140      var target_tp = target_type as TypeParameterSpec;
141      if (target_tp != null) {
142        //
143        // From a type parameter U to T, provided T depends on U
144        //
145        if (target_tp.TypeArguments != null && target_tp.HasDependencyOn (source_type)) {
146          return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
147        }
148      }
149
150      //
151      // From T to any interface-type I provided there is not already an implicit conversion from T to I
152      //
153      if (target_type.IsInterface)
154        return source == null ? EmptyExpression.Null : new ClassCast (source, target_type, true);
155
156      return null;
157    }
158
159    static Expression ExplicitTypeParameterConversionToT (Expression source, TypeSpec source_type, TypeParameterSpec target_type)
160    {
161      //
162      // From the effective base class C of T to T and from any base class of C to T
163      //
164      var effective = target_type.GetEffectiveBase ();
165      if (TypeSpecComparer.IsEqual (effective, source_type) || TypeSpec.IsBaseClass (effective, source_type, false))
166        return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
167
168      return null;
169    }
170
171    public static Expression ImplicitReferenceConversion (Expression expr, TypeSpec target_type, bool explicit_cast)
172    {
173      TypeSpec expr_type = expr.Type;
174
175      if (expr_type.Kind == MemberKind.TypeParameter)
176        return ImplicitTypeParameterConversion (expr, (TypeParameterSpec) expr.Type, target_type);
177
178      //
179      // from the null type to any reference-type.
180      //
181      NullLiteral nl = expr as NullLiteral;
182      if (nl != null) {
183        return nl.ConvertImplicitly (target_type);
184      }
185
186      if (ImplicitReferenceConversionExists (expr_type, target_type)) {
187        //
188        // Avoid wrapping implicitly convertible reference type
189        //
190        if (!explicit_cast)
191          return expr;
192
193        return EmptyCast.Create (expr, target_type);
194      }
195
196      return null;
197    }
198
199    //
200    // Implicit reference conversions
201    //
202    public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type)
203    {
204      return ImplicitReferenceConversionExists (expr_type, target_type, true);
205    }
206
207    public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type, bool refOnlyTypeParameter)
208    {
209      // It's here only to speed things up
210      if (target_type.IsStruct)
211        return false;
212
213      switch (expr_type.Kind) {
214      case MemberKind.TypeParameter:
215        return ImplicitTypeParameterConversion (null, (TypeParameterSpec) expr_type, target_type) != null &&
216          (!refOnlyTypeParameter || TypeSpec.IsReferenceType (expr_type));
217
218      case MemberKind.Class:
219        //
220        // From any class-type to dynamic (+object to speed up common path)
221        //
222        if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
223          return true;
224
225        if (target_type.IsClass) {
226          //
227          // Identity conversion, including dynamic erasure
228          //
229          if (TypeSpecComparer.IsEqual (expr_type, target_type))
230            return true;
231
232          //
233          // From any class-type S to any class-type T, provided S is derived from T
234          //
235          return TypeSpec.IsBaseClass (expr_type, target_type, true);
236        }
237
238        //
239        // From any class-type S to any interface-type T, provided S implements T
240        //
241        if (target_type.IsInterface)
242          return expr_type.ImplementsInterface (target_type, true);
243
244        return false;
245
246      case MemberKind.ArrayType:
247        //
248        // Identity array conversion
249        //
250        if (expr_type == target_type)
251          return true;
252
253        //
254        // From any array-type to System.Array
255        //
256        switch (target_type.BuiltinType) {
257        case BuiltinTypeSpec.Type.Array:
258        case BuiltinTypeSpec.Type.Object:
259        case BuiltinTypeSpec.Type.Dynamic:
260          return true;
261        }
262
263        var expr_type_array = (ArrayContainer) expr_type;
264        var target_type_array = target_type as ArrayContainer;
265
266        //
267        // From an array-type S to an array-type of type T
268        //
269        if (target_type_array != null && expr_type_array.Rank == target_type_array.Rank) {
270
271          //
272          // Both SE and TE are reference-types. TE check is defered
273          // to ImplicitReferenceConversionExists
274          //
275          TypeSpec expr_element_type = expr_type_array.Element;
276          if (!TypeSpec.IsReferenceType (expr_element_type))
277            return false;
278
279          //
280          // An implicit reference conversion exists from SE to TE
281          //
282          return ImplicitReferenceConversionExists (expr_element_type, target_type_array.Element);
283        }
284
285        //
286        // From any array-type to the interfaces it implements
287        //
288        if (target_type.IsInterface) {
289          if (expr_type.ImplementsInterface (target_type, false))
290            return true;
291
292          // from an array-type of type T to IList<T>
293          if (ArrayToIList (expr_type_array, target_type, false))
294            return true;
295        }
296
297        return false;
298
299      case MemberKind.Delegate:
300        //
301        // From any delegate-type to System.Delegate (and its base types)
302        //
303        switch (target_type.BuiltinType) {
304        case BuiltinTypeSpec.Type.Delegate:
305        case BuiltinTypeSpec.Type.MulticastDelegate:
306        case BuiltinTypeSpec.Type.Object:
307        case BuiltinTypeSpec.Type.Dynamic:
308          return true;
309        }
310
311        //
312        // Identity conversion, including dynamic erasure
313        //
314        if (TypeSpecComparer.IsEqual (expr_type, target_type))
315          return true;
316
317        //
318        // From any delegate-type to the interfaces it implements
319        // From any reference-type to an delegate type if is variance-convertible
320        //
321        return expr_type.ImplementsInterface (target_type, false) || TypeSpecComparer.Variant.IsEqual (expr_type, target_type);
322
323      case MemberKind.Interface:
324        //
325        // Identity conversion, including dynamic erasure
326        //
327        if (TypeSpecComparer.IsEqual (expr_type, target_type))
328          return true;
329
330        //
331        // From any interface type S to interface-type T
332        // From any reference-type to an interface if is variance-convertible
333        //
334        if (target_type.IsInterface)
335          return TypeSpecComparer.Variant.IsEqual (expr_type, target_type) || expr_type.ImplementsInterface (target_type, true);
336
337        return target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
338
339      case MemberKind.InternalCompilerType:
340        //
341        // from the null literal to any reference-type.
342        //
343        if (expr_type == InternalType.NullLiteral) {
344          // Exlude internal compiler types
345          if (target_type.Kind == MemberKind.InternalCompilerType)
346            return target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
347
348          return TypeSpec.IsReferenceType (target_type) || target_type.Kind == MemberKind.PointerType;
349        }
350
351        //
352        // Implicit dynamic conversion
353        //
354        if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
355          switch (target_type.Kind) {
356          case MemberKind.ArrayType:
357          case MemberKind.Class:
358          case MemberKind.Delegate:
359          case MemberKind.Interface:
360          case MemberKind.TypeParameter:
361            return true;
362          }
363
364          // dynamic to __arglist
365          if (target_type == InternalType.Arglist)
366            return true;
367
368          return false;
369        }
370
371        break;
372      }
373
374      return false;
375    }
376
377    public static Expression ImplicitBoxingConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
378    {
379      switch (target_type.BuiltinType) {
380      //
381      // From any non-nullable-value-type to the type object and dynamic
382      //
383      case BuiltinTypeSpec.Type.Object:
384      case BuiltinTypeSpec.Type.Dynamic:
385      //
386      // From any non-nullable-value-type to the type System.ValueType
387      //
388      case BuiltinTypeSpec.Type.ValueType:
389        //
390        // No ned to check for nullable type as underlying type is always convertible
391        //
392        if (!TypeSpec.IsValueType (expr_type))
393          return null;
394
395        return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
396
397      case BuiltinTypeSpec.Type.Enum:
398        //
399        // From any enum-type to the type System.Enum.
400        //
401        if (expr_type.IsEnum)
402          return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
403
404        break;
405      }
406
407      //
408      // From a nullable-type to a reference type, if a boxing conversion exists from
409      // the underlying type to the reference type
410      //
411      if (expr_type.IsNullableType) {
412        if (!TypeSpec.IsReferenceType (target_type))
413          return null;
414
415        var res = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);
416
417        // "cast" underlying type to target type to emit correct InvalidCastException when
418        // underlying hierarchy changes without recompilation
419        if (res != null && expr != null)
420          res = new UnboxCast (res, target_type);
421
422        return res;
423      }
424
425      //
426      // A value type has a boxing conversion to an interface type I if it has a boxing conversion
427      // to an interface or delegate type I0 and I0 is variance-convertible to I
428      //
429      if (target_type.IsInterface && TypeSpec.IsValueType (expr_type) && expr_type.ImplementsInterface (target_type, true)) {
430        return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
431      }
432
433      return null;
434    }
435
436    public static Expression ImplicitNulableConversion (ResolveContext ec, Expression expr, TypeSpec target_type)
437    {
438      TypeSpec expr_type = expr.Type;
439
440      //
441      // From null to any nullable type
442      //
443      if (expr_type == InternalType.NullLiteral)
444        return ec == null ? EmptyExpression.Null : Nullable.LiftedNull.Create (target_type, expr.Location);
445
446      // S -> T?
447      TypeSpec t_el = Nullable.NullableInfo.GetUnderlyingType (target_type);
448
449      // S? -> T?
450      if (expr_type.IsNullableType)
451        expr_type = Nullable.NullableInfo.GetUnderlyingType (expr_type);
452
453      //
454      // Predefined implicit identity or implicit numeric conversion
455      // has to exist between underlying type S and underlying type T
456      //
457
458      // conversion exists only mode
459      if (ec == null) {
460        if (TypeSpecComparer.IsEqual (expr_type, t_el))
461          return EmptyExpression.Null;
462
463        if (expr is Constant)
464          return ((Constant) expr).ConvertImplicitly (t_el);
465
466        return ImplicitNumericConversion (null, expr_type, t_el);
467      }
468
469      Expression unwrap;
470      if (expr_type != expr.Type)
471        unwrap = Nullable.Unwrap.Create (expr);
472      else
473        unwrap = expr;
474
475      Expression conv = unwrap;
476      if (!TypeSpecComparer.IsEqual (expr_type, t_el)) {
477        if (conv is Constant)
478          conv = ((Constant)conv).ConvertImplicitly (t_el);
479        else
480          conv = ImplicitNumericConversion (conv, expr_type, t_el);
481
482        if (conv == null)
483          return null;
484      }
485     
486      if (expr_type != expr.Type)
487        return new Nullable.LiftedConversion (conv, unwrap, target_type).Resolve (ec);
488
489      return Nullable.Wrap.Create (conv, target_type);
490    }
491
492    /// <summary>
493    ///   Implicit Numeric Conversions.
494    ///
495    ///   expr is the expression to convert, returns a new expression of type
496    ///   target_type or null if an implicit conversion is not possible.
497    /// </summary>
498    public static Expression ImplicitNumericConversion (Expression expr, TypeSpec target_type)
499    {
500      return ImplicitNumericConversion (expr, expr.Type, target_type);
501    }
502
503    public static bool ImplicitNumericConversionExists (TypeSpec expr_type, TypeSpec target_type)
504    {
505      return ImplicitNumericConversion (null, expr_type, target_type) != null;
506    }
507
508    static Expression ImplicitNumericConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
509    {
510      switch (expr_type.BuiltinType) {
511      case BuiltinTypeSpec.Type.SByte:
512        //
513        // From sbyte to short, int, long, float, double, decimal
514        //
515        switch (target_type.BuiltinType) {
516        case BuiltinTypeSpec.Type.Int:
517          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
518        case BuiltinTypeSpec.Type.Long:
519          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
520        case BuiltinTypeSpec.Type.Double:
521          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
522        case BuiltinTypeSpec.Type.Float:
523          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
524        case BuiltinTypeSpec.Type.Short:
525          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
526        case BuiltinTypeSpec.Type.Decimal:
527          return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
528
529        }
530
531        break;
532      case BuiltinTypeSpec.Type.Byte:
533        //
534        // From byte to short, ushort, int, uint, long, ulong, float, double, decimal
535        //
536        switch (target_type.BuiltinType) {
537        case BuiltinTypeSpec.Type.Int:
538        case BuiltinTypeSpec.Type.UInt:
539        case BuiltinTypeSpec.Type.Short:
540        case BuiltinTypeSpec.Type.UShort:
541          return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
542        case BuiltinTypeSpec.Type.ULong:
543          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
544        case BuiltinTypeSpec.Type.Long:
545          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
546        case BuiltinTypeSpec.Type.Float:
547          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
548        case BuiltinTypeSpec.Type.Double:
549          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
550        case BuiltinTypeSpec.Type.Decimal:
551          return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
552        }
553        break;
554      case BuiltinTypeSpec.Type.Short:
555        //
556        // From short to int, long, float, double, decimal
557        //
558        switch (target_type.BuiltinType) {
559        case BuiltinTypeSpec.Type.Int:
560          return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
561        case BuiltinTypeSpec.Type.Long:
562          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
563        case BuiltinTypeSpec.Type.Double:
564          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
565        case BuiltinTypeSpec.Type.Float:
566          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
567        case BuiltinTypeSpec.Type.Decimal:
568          return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
569        }
570        break;
571      case BuiltinTypeSpec.Type.UShort:
572        //
573        // From ushort to int, uint, long, ulong, float, double, decimal
574        //
575        switch (target_type.BuiltinType) {
576        case BuiltinTypeSpec.Type.Int:
577        case BuiltinTypeSpec.Type.UInt:
578          return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
579        case BuiltinTypeSpec.Type.ULong:
580          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
581        case BuiltinTypeSpec.Type.Long:
582          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
583        case BuiltinTypeSpec.Type.Double:
584          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
585        case BuiltinTypeSpec.Type.Float:
586          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
587        case BuiltinTypeSpec.Type.Decimal:
588          return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
589        }
590        break;
591      case BuiltinTypeSpec.Type.Int:
592        //
593        // From int to long, float, double, decimal
594        //
595        switch (target_type.BuiltinType) {
596        case BuiltinTypeSpec.Type.Long:
597          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
598        case BuiltinTypeSpec.Type.Double:
599          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
600        case BuiltinTypeSpec.Type.Float:
601          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
602        case BuiltinTypeSpec.Type.Decimal:
603          return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
604        }
605        break;
606      case BuiltinTypeSpec.Type.UInt:
607        //
608        // From uint to long, ulong, float, double, decimal
609        //
610        switch (target_type.BuiltinType) {
611        case BuiltinTypeSpec.Type.Long:
612          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
613        case BuiltinTypeSpec.Type.ULong:
614          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
615        case BuiltinTypeSpec.Type.Double:
616          return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8);
617        case BuiltinTypeSpec.Type.Float:
618          return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4);
619        case BuiltinTypeSpec.Type.Decimal:
620          return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
621        }
622        break;
623      case BuiltinTypeSpec.Type.Long:
624        //
625        // From long to float, double, decimal
626        //
627        switch (target_type.BuiltinType) {
628        case BuiltinTypeSpec.Type.Double:
629          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
630        case BuiltinTypeSpec.Type.Float:
631          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
632        case BuiltinTypeSpec.Type.Decimal:
633          return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
634        }
635        break;
636      case BuiltinTypeSpec.Type.ULong:
637        //
638        // From ulong to float, double, decimal
639        //
640        switch (target_type.BuiltinType) {
641        case BuiltinTypeSpec.Type.Double:
642          return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8);
643        case BuiltinTypeSpec.Type.Float:
644          return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4);
645        case BuiltinTypeSpec.Type.Decimal:
646          return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
647        }
648        break;
649      case BuiltinTypeSpec.Type.Char:
650        //
651        // From char to ushort, int, uint, long, ulong, float, double, decimal
652        //
653        switch (target_type.BuiltinType) {
654        case BuiltinTypeSpec.Type.UShort:
655        case BuiltinTypeSpec.Type.Int:
656        case BuiltinTypeSpec.Type.UInt:
657          return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
658        case BuiltinTypeSpec.Type.ULong:
659          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
660        case BuiltinTypeSpec.Type.Long:
661          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
662        case BuiltinTypeSpec.Type.Float:
663          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
664        case BuiltinTypeSpec.Type.Double:
665          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
666        case BuiltinTypeSpec.Type.Decimal:
667          return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
668        }
669        break;
670      case BuiltinTypeSpec.Type.Float:
671        //
672        // float to double
673        //
674        if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double)
675          return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
676        break;
677      }
678
679      return null;
680    }
681
682    //
683    // Full version of implicit conversion
684    //
685    public static bool ImplicitConversionExists (ResolveContext ec, Expression expr, TypeSpec target_type)
686    {
687      if (ImplicitStandardConversionExists (ec, expr, target_type))
688        return true;
689
690      if (expr.Type == InternalType.AnonymousMethod) {
691        if (!target_type.IsDelegate && !target_type.IsExpressionTreeType)
692          return false;
693
694        AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
695        return ame.ImplicitStandardConversionExists (ec, target_type);
696      }
697     
698      // Conversion from __arglist to System.ArgIterator
699      if (expr.Type == InternalType.Arglist)
700        return target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec;
701
702      return UserDefinedConversion (ec, expr, target_type,
703        UserConversionRestriction.ImplicitOnly | UserConversionRestriction.ProbingOnly, Location.Null) != null;
704    }
705
706    public static bool ImplicitStandardConversionExists (ResolveContext rc, Expression expr, TypeSpec target_type)
707    {
708      if (expr.eclass == ExprClass.MethodGroup) {
709        if (target_type.IsDelegate && rc.Module.Compiler.Settings.Version != LanguageVersion.ISO_1) {
710          MethodGroupExpr mg = expr as MethodGroupExpr;
711          if (mg != null)
712            return DelegateCreation.ImplicitStandardConversionExists (rc, mg, target_type);
713        }
714
715        return false;
716      }
717
718      return ImplicitStandardConversionExists (expr, target_type);
719    }
720
721    //
722    // Implicit standard conversion (only core conversions are used here)
723    //
724    public static bool ImplicitStandardConversionExists (Expression expr, TypeSpec target_type)
725    {
726      //
727      // Identity conversions
728      // Implicit numeric conversions
729      // Implicit nullable conversions
730      // Implicit reference conversions
731      // Boxing conversions
732      // Implicit constant expression conversions
733      // Implicit conversions involving type parameters
734      //
735
736      TypeSpec expr_type = expr.Type;
737
738      if (expr_type == target_type)
739        return true;
740
741      if (target_type.IsNullableType)
742        return ImplicitNulableConversion (null, expr, target_type) != null;
743
744      if (ImplicitNumericConversion (null, expr_type, target_type) != null)
745        return true;
746
747      if (ImplicitReferenceConversionExists (expr_type, target_type, false))
748        return true;
749
750      if (ImplicitBoxingConversion (null, expr_type, target_type) != null)
751        return true;
752     
753      //
754      // Implicit Constant Expression Conversions
755      //
756      if (expr is IntConstant){
757        int value = ((IntConstant) expr).Value;
758        switch (target_type.BuiltinType) {
759        case BuiltinTypeSpec.Type.SByte:
760          if (value >= SByte.MinValue && value <= SByte.MaxValue)
761            return true;
762          break;
763        case BuiltinTypeSpec.Type.Byte:
764          if (value >= 0 && value <= Byte.MaxValue)
765            return true;
766          break;
767        case BuiltinTypeSpec.Type.Short:
768          if (value >= Int16.MinValue && value <= Int16.MaxValue)
769            return true;
770          break;
771        case BuiltinTypeSpec.Type.UShort:
772          if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
773            return true;
774          break;
775        case BuiltinTypeSpec.Type.UInt:
776          if (value >= 0)
777            return true;
778          break;
779        case BuiltinTypeSpec.Type.ULong:
780           //
781           // we can optimize this case: a positive int32
782           // always fits on a uint64.  But we need an opcode
783           // to do it.
784           //
785          if (value >= 0)
786            return true;
787
788          break;
789        }
790      }
791
792      if (expr is LongConstant && target_type.BuiltinType == BuiltinTypeSpec.Type.ULong){
793        //
794        // Try the implicit constant expression conversion
795        // from long to ulong, instead of a nice routine,
796        // we just inline it
797        //
798        long v = ((LongConstant) expr).Value;
799        if (v >= 0)
800          return true;
801      }
802
803      if (expr is IntegralConstant && target_type.IsEnum) {
804        var i = (IntegralConstant) expr;
805        //
806        // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
807        //
808        // An implicit enumeration conversion permits the decimal-integer-literal 0
809        // to be converted to any enum-type and to any nullable-type whose underlying
810        // type is an enum-type
811        //
812        return i.IsZeroInteger;
813      }
814
815      //
816      // Implicit dynamic conversion for remaining value types. It should probably
817      // go somewhere else
818      //
819      if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
820        switch (target_type.Kind) {
821        case MemberKind.Struct:
822        case MemberKind.Enum:
823          return true;
824        }
825
826        return false;
827      }
828
829      //
830      // In an unsafe context implicit conversions is extended to include
831      //
832      // From any pointer-type to the type void*
833      // From the null literal to any pointer-type.
834      //
835      // LAMESPEC: The specification claims this conversion is allowed in implicit conversion but
836      // in reality implicit standard conversion uses it
837      //
838      if (target_type.IsPointer && expr.Type.IsPointer && ((PointerContainer) target_type).Element.Kind == MemberKind.Void)
839        return true;
840
841      //
842      // Struct identity conversion, including dynamic erasure
843      //
844      if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type))
845        return true;
846
847      return false;
848    }
849
850    /// <summary>
851    ///  Finds "most encompassed type" according to the spec (13.4.2)
852    ///  amongst the methods in the MethodGroupExpr
853    /// </summary>
854    public static TypeSpec FindMostEncompassedType (IList<TypeSpec> types)
855    {
856      TypeSpec best = null;
857      EmptyExpression expr;
858
859      foreach (TypeSpec t in types) {
860        if (best == null) {
861          best = t;
862          continue;
863        }
864
865        expr = new EmptyExpression (t);
866        if (ImplicitStandardConversionExists (expr, best))
867          best = t;
868      }
869
870      expr = new EmptyExpression (best);
871      foreach (TypeSpec t in types) {
872        if (best == t)
873          continue;
874        if (!ImplicitStandardConversionExists (expr, t)) {
875          best = null;
876          break;
877        }
878      }
879
880      return best;
881    }
882
883    //
884    // Finds the most encompassing type (type into which all other
885    // types can convert to) amongst the types in the given set
886    //
887    static TypeSpec FindMostEncompassingType (IList<TypeSpec> types)
888    {
889      if (types.Count == 0)
890        return null;
891
892      if (types.Count == 1)
893        return types [0];
894
895      TypeSpec best = null;
896      for (int i = 0; i < types.Count; ++i) {
897        int ii = 0;
898        for (; ii < types.Count; ++ii) {
899          if (ii == i)
900            continue;
901
902          var expr = new EmptyExpression (types[ii]);
903          if (!ImplicitStandardConversionExists (expr, types [i])) {
904            ii = 0;
905            break;
906          }
907        }
908
909        if (ii == 0)
910          continue;
911
912        if (best == null) {
913          best = types[i];
914          continue;
915        }
916
917        // Indicates multiple best types
918        return InternalType.FakeInternalType;
919      }
920
921      return best;
922    }
923
924    //
925    // Finds the most specific source Sx according to the rules of the spec (13.4.4)
926    // by making use of FindMostEncomp* methods. Applies the correct rules separately
927    // for explicit and implicit conversion operators.
928    //
929    static TypeSpec FindMostSpecificSource (ResolveContext rc, List<MethodSpec> list, TypeSpec sourceType, Expression source, bool apply_explicit_conv_rules)
930    {
931      TypeSpec[] src_types_set = null;
932
933      //
934      // Try exact match first, if any operator converts from S then Sx = S
935      //
936      for (int i = 0; i < list.Count; ++i) {
937        TypeSpec param_type = list [i].Parameters.Types [0];
938
939        if (param_type == sourceType)
940          return param_type;
941
942        if (src_types_set == null)
943          src_types_set = new TypeSpec [list.Count];
944
945        src_types_set [i] = param_type;
946      }
947
948      //
949      // Explicit Conv rules
950      //
951      if (apply_explicit_conv_rules) {
952        var candidate_set = new List<TypeSpec> ();
953
954        foreach (TypeSpec param_type in src_types_set){
955          if (ImplicitStandardConversionExists (rc, source, param_type))
956            candidate_set.Add (param_type);
957        }
958
959        if (candidate_set.Count != 0) {
960          if (source.eclass == ExprClass.MethodGroup)
961            return InternalType.FakeInternalType;
962
963          return FindMostEncompassedType (candidate_set);
964        }
965      }
966
967      //
968      // Final case
969      //
970      if (apply_explicit_conv_rules)
971        return FindMostEncompassingType (src_types_set);
972      else
973        return FindMostEncompassedType (src_types_set);
974    }
975
976    /// <summary>
977    ///  Finds the most specific target Tx according to section 13.4.4
978    /// </summary>
979    static public TypeSpec FindMostSpecificTarget (IList<MethodSpec> list,
980                 TypeSpec target, bool apply_explicit_conv_rules)
981    {
982      List<TypeSpec> tgt_types_set = null;
983
984      //
985      // If any operator converts to T then Tx = T
986      //
987      foreach (var mi in list){
988        TypeSpec ret_type = mi.ReturnType;
989        if (ret_type == target)
990          return ret_type;
991
992        if (tgt_types_set == null) {
993          tgt_types_set = new List<TypeSpec> (list.Count);
994        } else if (tgt_types_set.Contains (ret_type)) {
995          continue;
996        }
997
998        tgt_types_set.Add (ret_type);
999      }
1000
1001      //
1002      // Explicit conv rules
1003      //
1004      if (apply_explicit_conv_rules) {
1005        var candidate_set = new List<TypeSpec> ();
1006
1007        foreach (TypeSpec ret_type in tgt_types_set) {
1008          var expr = new EmptyExpression (ret_type);
1009
1010          if (ImplicitStandardConversionExists (expr, target))
1011            candidate_set.Add (ret_type);
1012        }
1013
1014        if (candidate_set.Count != 0)
1015          return FindMostEncompassingType (candidate_set);
1016      }
1017
1018      //
1019      // Okay, final case !
1020      //
1021      if (apply_explicit_conv_rules)
1022        return FindMostEncompassedType (tgt_types_set);
1023      else
1024        return FindMostEncompassingType (tgt_types_set);
1025    }
1026
1027    /// <summary>
1028    ///  User-defined Implicit conversions
1029    /// </summary>
1030    static public Expression ImplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc)
1031    {
1032      return UserDefinedConversion (ec, source, target, UserConversionRestriction.ImplicitOnly, loc);
1033    }
1034
1035    /// <summary>
1036    ///  User-defined Explicit conversions
1037    /// </summary>
1038    static Expression ExplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc)
1039    {
1040      return UserDefinedConversion (ec, source, target, 0, loc);
1041    }
1042
1043    static void FindApplicableUserDefinedConversionOperators (ResolveContext rc, IList<MemberSpec> operators, Expression source, TypeSpec target, UserConversionRestriction restr, ref List<MethodSpec> candidates)
1044    {
1045      if (source.Type.IsInterface) {
1046        // Neither A nor B are interface-types
1047        return;
1048      }
1049
1050      // For a conversion operator to be applicable, it must be possible
1051      // to perform a standard conversion from the source type to
1052      // the operand type of the operator, and it must be possible
1053      // to perform a standard conversion from the result type of
1054      // the operator to the target type.
1055
1056      Expression texpr = null;
1057
1058      foreach (MethodSpec op in operators) {
1059       
1060        // Can be null because MemberCache.GetUserOperator does not resize the array
1061        if (op == null)
1062          continue;
1063
1064        var t = op.Parameters.Types[0];
1065        if (source.Type != t && !ImplicitStandardConversionExists (rc, source, t)) {
1066          if ((restr & UserConversionRestriction.ImplicitOnly) != 0)
1067            continue;
1068
1069          if (!ImplicitStandardConversionExists (new EmptyExpression (t), source.Type))
1070              continue;
1071        }
1072
1073        if ((restr & UserConversionRestriction.NullableSourceOnly) != 0 && !t.IsNullableType)
1074          continue;
1075
1076        t = op.ReturnType;
1077
1078        if (t.IsInterface)
1079          continue;
1080
1081        if (target != t) {
1082          if (t.IsNullableType)
1083            t = Nullable.NullableInfo.GetUnderlyingType (t);
1084
1085          if (!ImplicitStandardConversionExists (new EmptyExpression (t), target)) {
1086            if ((restr & UserConversionRestriction.ImplicitOnly) != 0)
1087              continue;
1088
1089            if (texpr == null)
1090              texpr = new EmptyExpression (target);
1091
1092            if (!ImplicitStandardConversionExists (texpr, t))
1093              continue;
1094          }
1095        }
1096
1097        if (candidates == null)
1098          candidates = new List<MethodSpec> ();
1099
1100        candidates.Add (op);
1101      }
1102    }
1103
1104    //
1105    // User-defined conversions
1106    //
1107    public static Expression UserDefinedConversion (ResolveContext rc, Expression source, TypeSpec target, UserConversionRestriction restr, Location loc)
1108    {
1109      List<MethodSpec> candidates = null;
1110
1111      //
1112      // If S or T are nullable types, source_type and target_type are their underlying types
1113      // otherwise source_type and target_type are equal to S and T respectively.
1114      //
1115      TypeSpec source_type = source.Type;
1116      TypeSpec target_type = target;
1117      Expression source_type_expr;
1118      bool nullable_source = false;
1119      var implicitOnly = (restr & UserConversionRestriction.ImplicitOnly) != 0;
1120
1121      if (source_type.IsNullableType) {
1122        // No unwrapping conversion S? -> T for non-reference types
1123        if (implicitOnly && !TypeSpec.IsReferenceType (target_type) && !target_type.IsNullableType) {
1124          source_type_expr = source;
1125        } else {
1126          source_type_expr = Nullable.Unwrap.CreateUnwrapped (source);
1127          source_type = source_type_expr.Type;
1128          nullable_source = true;
1129        }
1130      } else {
1131        source_type_expr = source;
1132      }
1133
1134      if (target_type.IsNullableType)
1135        target_type = Nullable.NullableInfo.GetUnderlyingType (target_type);
1136
1137      // Only these containers can contain a user defined implicit or explicit operators
1138      const MemberKind user_conversion_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.TypeParameter;
1139
1140      if ((source_type.Kind & user_conversion_kinds) != 0 && source_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
1141        bool declared_only = source_type.IsStruct;
1142
1143        var operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Implicit, declared_only);
1144        if (operators != null) {
1145          FindApplicableUserDefinedConversionOperators (rc, operators, source_type_expr, target_type, restr, ref candidates);
1146        }
1147
1148        if (!implicitOnly) {
1149          operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Explicit, declared_only);
1150          if (operators != null) {
1151            FindApplicableUserDefinedConversionOperators (rc, operators, source_type_expr, target_type, restr, ref candidates);
1152          }
1153        }
1154      }
1155
1156      if ((target.Kind & user_conversion_kinds) != 0 && target_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
1157        bool declared_only = target.IsStruct || implicitOnly;
1158
1159        var operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Implicit, declared_only);
1160        if (operators != null) {
1161          FindApplicableUserDefinedConversionOperators (rc, operators, source_type_expr, target_type, restr, ref candidates);
1162        }
1163
1164        if (!implicitOnly) {
1165          operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Explicit, declared_only);
1166          if (operators != null) {
1167            FindApplicableUserDefinedConversionOperators (rc, operators, source_type_expr, target_type, restr, ref candidates);
1168          }
1169        }
1170      }
1171
1172      if (candidates == null)
1173        return null;
1174
1175      //
1176      // Find the most specific conversion operator
1177      //
1178      MethodSpec most_specific_operator;
1179      TypeSpec s_x, t_x;
1180      if (candidates.Count == 1) {
1181        most_specific_operator = candidates[0];
1182        s_x = most_specific_operator.Parameters.Types[0];
1183        t_x = most_specific_operator.ReturnType;
1184      } else {
1185        //
1186        // Pass original source type to find the best match against input type and
1187        // not the unwrapped expression
1188        //
1189        s_x = FindMostSpecificSource (rc, candidates, source.Type, source_type_expr, !implicitOnly);
1190        if (s_x == null)
1191          return null;
1192
1193        t_x = FindMostSpecificTarget (candidates, target, !implicitOnly);
1194        if (t_x == null)
1195          return null;
1196
1197        most_specific_operator = null;
1198        for (int i = 0; i < candidates.Count; ++i) {
1199          if (candidates[i].ReturnType == t_x && candidates[i].Parameters.Types[0] == s_x) {
1200            most_specific_operator = candidates[i];
1201            break;
1202          }
1203        }
1204
1205        if (most_specific_operator == null) {
1206          //
1207          // Unless running in probing more
1208          //
1209          if ((restr & UserConversionRestriction.ProbingOnly) == 0) {
1210            MethodSpec ambig_arg = candidates [0];
1211            most_specific_operator = candidates [1];
1212            /*
1213            foreach (var candidate in candidates) {
1214              if (candidate.ReturnType == t_x)
1215                most_specific_operator = candidate;
1216              else if (candidate.Parameters.Types[0] == s_x)
1217                ambig_arg = candidate;
1218            }
1219            */
1220            rc.Report.Error (457, loc,
1221              "Ambiguous user defined operators `{0}' and `{1}' when converting from `{2}' to `{3}'",
1222              ambig_arg.GetSignatureForError (), most_specific_operator.GetSignatureForError (),
1223              source.Type.GetSignatureForError (), target.GetSignatureForError ());
1224          }
1225
1226          return ErrorExpression.Instance;
1227        }
1228      }
1229
1230      //
1231      // Convert input type when it's different to best operator argument
1232      //
1233      if (s_x != source_type) {
1234        var c = source as Constant;
1235        if (c != null) {
1236          source = c.Reduce (rc, s_x);
1237          if (source == null)
1238            c = null;
1239        }
1240
1241        if (c == null) {
1242          source = implicitOnly ?
1243            ImplicitConversionStandard (rc, source_type_expr, s_x, loc) :
1244            ExplicitConversionStandard (rc, source_type_expr, s_x, loc);
1245        }
1246      } else {
1247        source = source_type_expr;
1248      }
1249
1250      source = new UserCast (most_specific_operator, source, loc).Resolve (rc);
1251
1252      //
1253      // Convert result type when it's different to best operator return type
1254      //
1255      if (t_x != target_type) {
1256        //
1257        // User operator is of T?
1258        //
1259        if (t_x.IsNullableType && (target.IsNullableType || !implicitOnly)) {
1260          //
1261          // User operator return type does not match target type we need
1262          // yet another conversion. This should happen for promoted numeric
1263          // types only
1264          //
1265          if (t_x != target) {
1266            var unwrap = Nullable.Unwrap.CreateUnwrapped (source);
1267
1268            source = implicitOnly ?
1269              ImplicitConversionStandard (rc, unwrap, target_type, loc) :
1270              ExplicitConversionStandard (rc, unwrap, target_type, loc);
1271
1272            if (source == null)
1273              return null;
1274
1275            if (target.IsNullableType)
1276              source = new Nullable.LiftedConversion (source, unwrap, target).Resolve (rc);
1277          }
1278        } else {
1279          source = implicitOnly ?
1280            ImplicitConversionStandard (rc, source, target_type, loc) :
1281            ExplicitConversionStandard (rc, source, target_type, loc);
1282
1283          if (source == null)
1284            return null;
1285        }
1286      }
1287
1288
1289      //
1290      // Source expression is of nullable type and underlying conversion returns
1291      // only non-nullable type we need to lift it manually
1292      //
1293      if (nullable_source && !s_x.IsNullableType)
1294        return new Nullable.LiftedConversion (source, source_type_expr, target).Resolve (rc);
1295
1296      //
1297      // Target is of nullable type but source type is not, wrap the result expression
1298      //
1299      if (target.IsNullableType && !t_x.IsNullableType)
1300        source = Nullable.Wrap.Create (source, target);
1301
1302      return source;
1303    }
1304
1305    /// <summary>
1306    ///   Converts implicitly the resolved expression `expr' into the
1307    ///   `target_type'.  It returns a new expression that can be used
1308    ///   in a context that expects a `target_type'.
1309    /// </summary>
1310    static public Expression ImplicitConversion (ResolveContext ec, Expression expr,
1311                   TypeSpec target_type, Location loc)
1312    {
1313      Expression e;
1314
1315      if (target_type == null)
1316        throw new Exception ("Target type is null");
1317
1318      e = ImplicitConversionStandard (ec, expr, target_type, loc);
1319      if (e != null)
1320        return e;
1321
1322      e = ImplicitUserConversion (ec, expr, target_type, loc);
1323      if (e != null)
1324        return e;
1325
1326      return null;
1327    }
1328
1329
1330    /// <summary>
1331    ///   Attempts to apply the `Standard Implicit
1332    ///   Conversion' rules to the expression `expr' into
1333    ///   the `target_type'.  It returns a new expression
1334    ///   that can be used in a context that expects a
1335    ///   `target_type'.
1336    ///
1337    ///   This is different from `ImplicitConversion' in that the
1338    ///   user defined implicit conversions are excluded.
1339    /// </summary>
1340    static public Expression ImplicitConversionStandard (ResolveContext ec, Expression expr,
1341                     TypeSpec target_type, Location loc)
1342    {
1343      return ImplicitConversionStandard (ec, expr, target_type, loc, false);
1344    }
1345
1346    static Expression ImplicitConversionStandard (ResolveContext ec, Expression expr, TypeSpec target_type, Location loc, bool explicit_cast)
1347    {
1348      if (expr.eclass == ExprClass.MethodGroup){
1349        if (!target_type.IsDelegate){
1350          return null;
1351        }
1352
1353        //
1354        // Only allow anonymous method conversions on post ISO_1
1355        //
1356        if (ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1){
1357          MethodGroupExpr mg = expr as MethodGroupExpr;
1358          if (mg != null)
1359            return new ImplicitDelegateCreation (target_type, mg, loc).Resolve (ec);
1360        }
1361      }
1362
1363      TypeSpec expr_type = expr.Type;
1364      Expression e;
1365
1366      if (expr_type == target_type) {
1367        if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod)
1368          return expr;
1369        return null;
1370      }
1371
1372      if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1373        switch (target_type.Kind) {
1374        case MemberKind.ArrayType:
1375        case MemberKind.Class:
1376          if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object)
1377            return EmptyCast.Create (expr, target_type);
1378
1379          goto case MemberKind.Struct;
1380        case MemberKind.Struct:
1381        case MemberKind.Delegate:
1382        case MemberKind.Enum:
1383        case MemberKind.Interface:
1384        case MemberKind.TypeParameter:
1385          Arguments args = new Arguments (1);
1386          args.Add (new Argument (expr));
1387          return new DynamicConversion (target_type, explicit_cast ? CSharpBinderFlags.ConvertExplicit : 0, args, loc).Resolve (ec);
1388        }
1389
1390        return null;
1391      }
1392
1393      if (target_type.IsNullableType)
1394        return ImplicitNulableConversion (ec, expr, target_type);
1395
1396      //
1397      // Attempt to do the implicit constant expression conversions
1398      //
1399      Constant c = expr as Constant;
1400      if (c != null) {
1401        try {
1402          c = c.ConvertImplicitly (target_type);
1403        } catch {
1404          throw new InternalErrorException ("Conversion error", loc);
1405        }
1406        if (c != null)
1407          return c;
1408      }
1409
1410      e = ImplicitNumericConversion (expr, expr_type, target_type);
1411      if (e != null)
1412        return e;
1413
1414      e = ImplicitReferenceConversion (expr, target_type, explicit_cast);
1415      if (e != null)
1416        return e;
1417
1418      e = ImplicitBoxingConversion (expr, expr_type, target_type);
1419      if (e != null)
1420        return e;
1421
1422      if (expr is IntegralConstant && target_type.IsEnum){
1423        var i = (IntegralConstant) expr;
1424        //
1425        // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
1426        //
1427        // An implicit enumeration conversion permits the decimal-integer-literal 0
1428        // to be converted to any enum-type and to any nullable-type whose underlying
1429        // type is an enum-type
1430        //
1431        if (i.IsZeroInteger) {
1432          // Recreate 0 literal to remove any collected conversions
1433          return new EnumConstant (new IntLiteral (ec.BuiltinTypes, 0, i.Location), target_type);
1434        }
1435      }
1436
1437      var target_pc = target_type as PointerContainer;
1438      if (target_pc != null) {
1439        if (expr_type.IsPointer) {
1440          //
1441          // Pointer types are same when they have same element types
1442          //
1443          if (expr_type == target_pc)
1444            return expr;
1445
1446          if (target_pc.Element.Kind == MemberKind.Void)
1447            return EmptyCast.Create (expr, target_type);
1448
1449            //return null;
1450        }
1451
1452        if (expr_type == InternalType.NullLiteral)
1453          return new NullPointer (target_type, loc);
1454      }
1455
1456      if (expr_type == InternalType.AnonymousMethod){
1457        AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
1458        Expression am = ame.Compatible (ec, target_type);
1459        if (am != null)
1460          return am.Resolve (ec);
1461
1462        // Avoid CS1503 after CS1661
1463        return ErrorExpression.Instance;
1464      }
1465
1466      if (expr_type == InternalType.Arglist && target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec)
1467        return expr;
1468
1469      //
1470      // dynamic erasure conversion on value types
1471      //
1472      if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type))
1473        return expr_type == target_type ? expr : EmptyCast.Create (expr, target_type);
1474
1475      return null;
1476    }
1477
1478    /// <summary>
1479    ///   Attempts to implicitly convert `source' into `target_type', using
1480    ///   ImplicitConversion.  If there is no implicit conversion, then
1481    ///   an error is signaled
1482    /// </summary>
1483    static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source,
1484                     TypeSpec target_type, Location loc)
1485    {
1486      Expression e = ImplicitConversion (ec, source, target_type, loc);
1487      if (e != null)
1488        return e;
1489
1490      source.Error_ValueCannotBeConverted (ec, target_type, false);
1491
1492      return null;
1493    }
1494
1495    /// <summary>
1496    ///   Performs the explicit numeric conversions
1497    ///
1498    /// There are a few conversions that are not part of the C# standard,
1499    /// they were interim hacks in the C# compiler that were supposed to
1500    /// become explicit operators in the UIntPtr class and IntPtr class,
1501    /// but for historical reasons it did not happen, so the C# compiler
1502    /// ended up with these special hacks.
1503    ///
1504    /// See bug 59800 for details.
1505    ///
1506    /// The conversion are:
1507    ///   UIntPtr->SByte
1508    ///   UIntPtr->Int16
1509    ///   UIntPtr->Int32
1510    ///   IntPtr->UInt64
1511    ///   UInt64->IntPtr
1512    ///   SByte->UIntPtr
1513    ///   Int16->UIntPtr
1514    ///
1515    /// </summary>
1516    public static Expression ExplicitNumericConversion (ResolveContext rc, Expression expr, TypeSpec target_type)
1517    {
1518      // Not all predefined explicit numeric conversion are
1519      // defined here, for some of them (mostly IntPtr/UIntPtr) we
1520      // defer to user-operator handling which is now perfect but
1521      // works for now
1522      //
1523      // LAMESPEC: Undocumented IntPtr/UIntPtr conversions
1524      // IntPtr -> uint uses int
1525      // UIntPtr -> long uses ulong
1526      //
1527
1528      switch (expr.Type.BuiltinType) {
1529      case BuiltinTypeSpec.Type.SByte:
1530        //
1531        // From sbyte to byte, ushort, uint, ulong, char, uintptr
1532        //
1533        switch (target_type.BuiltinType) {
1534        case BuiltinTypeSpec.Type.Byte:
1535          return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1);
1536        case BuiltinTypeSpec.Type.UShort:
1537          return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2);
1538        case BuiltinTypeSpec.Type.UInt:
1539          return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4);
1540        case BuiltinTypeSpec.Type.ULong:
1541          return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8);
1542        case BuiltinTypeSpec.Type.Char:
1543          return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH);
1544
1545        // One of the built-in conversions that belonged in the class library
1546        case BuiltinTypeSpec.Type.UIntPtr:
1547          return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I1_U8), target_type, target_type, true);
1548        }
1549        break;
1550      case BuiltinTypeSpec.Type.Byte:
1551        //
1552        // From byte to sbyte and char
1553        //
1554        switch (target_type.BuiltinType) {
1555        case BuiltinTypeSpec.Type.SByte:
1556          return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1);
1557        case BuiltinTypeSpec.Type.Char:
1558          return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH);
1559        }
1560        break;
1561      case BuiltinTypeSpec.Type.Short:
1562        //
1563        // From short to sbyte, byte, ushort, uint, ulong, char, uintptr
1564        //
1565        switch (target_type.BuiltinType) {
1566        case BuiltinTypeSpec.Type.SByte:
1567          return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1);
1568        case BuiltinTypeSpec.Type.Byte:
1569          return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1);
1570        case BuiltinTypeSpec.Type.UShort:
1571          return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2);
1572        case BuiltinTypeSpec.Type.UInt:
1573          return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4);
1574        case BuiltinTypeSpec.Type.ULong:
1575          return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8);
1576        case BuiltinTypeSpec.Type.Char:
1577          return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH);
1578
1579        // One of the built-in conversions that belonged in the class library
1580        case BuiltinTypeSpec.Type.UIntPtr:
1581          return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true);
1582        }
1583        break;
1584      case BuiltinTypeSpec.Type.UShort:
1585        //
1586        // From ushort to sbyte, byte, short, char
1587        //
1588        switch (target_type.BuiltinType) {
1589        case BuiltinTypeSpec.Type.SByte:
1590          return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1);
1591        case BuiltinTypeSpec.Type.Byte:
1592          return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1);
1593        case BuiltinTypeSpec.Type.Short:
1594          return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2);
1595        case BuiltinTypeSpec.Type.Char:
1596          return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH);
1597        }
1598        break;
1599      case BuiltinTypeSpec.Type.Int:
1600        //
1601        // From int to sbyte, byte, short, ushort, uint, ulong, char, uintptr
1602        //
1603        switch (target_type.BuiltinType) {
1604        case BuiltinTypeSpec.Type.SByte:
1605          return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1);
1606        case BuiltinTypeSpec.Type.Byte:
1607          return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1);
1608        case BuiltinTypeSpec.Type.Short:
1609          return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2);
1610        case BuiltinTypeSpec.Type.UShort:
1611          return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2);
1612        case BuiltinTypeSpec.Type.UInt:
1613          return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4);
1614        case BuiltinTypeSpec.Type.ULong:
1615          return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8);
1616        case BuiltinTypeSpec.Type.Char:
1617          return new ConvCast (expr, target_type, ConvCast.Mode.I4_CH);
1618
1619        // One of the built-in conversions that belonged in the class library
1620        case BuiltinTypeSpec.Type.UIntPtr:
1621          return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true);
1622        }
1623        break;
1624      case BuiltinTypeSpec.Type.UInt:
1625        //
1626        // From uint to sbyte, byte, short, ushort, int, char
1627        //
1628        switch (target_type.BuiltinType) {
1629        case BuiltinTypeSpec.Type.SByte:
1630          return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1);
1631        case BuiltinTypeSpec.Type.Byte:
1632          return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1);
1633        case BuiltinTypeSpec.Type.Short:
1634          return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2);
1635        case BuiltinTypeSpec.Type.UShort:
1636          return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2);
1637        case BuiltinTypeSpec.Type.Int:
1638          return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4);
1639        case BuiltinTypeSpec.Type.Char:
1640          return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH);
1641        }
1642        break;
1643      case BuiltinTypeSpec.Type.Long:
1644        //
1645        // From long to sbyte, byte, short, ushort, int, uint, ulong, char
1646        //
1647        switch (target_type.BuiltinType) {
1648        case BuiltinTypeSpec.Type.SByte:
1649          return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1);
1650        case BuiltinTypeSpec.Type.Byte:
1651          return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1);
1652        case BuiltinTypeSpec.Type.Short:
1653          return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2);
1654        case BuiltinTypeSpec.Type.UShort:
1655          return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2);
1656        case BuiltinTypeSpec.Type.Int:
1657          return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4);
1658        case BuiltinTypeSpec.Type.UInt:
1659          return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4);
1660        case BuiltinTypeSpec.Type.ULong:
1661          return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8);
1662        case BuiltinTypeSpec.Type.Char:
1663          return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH);
1664        }
1665        break;
1666      case BuiltinTypeSpec.Type.ULong:
1667        //
1668        // From ulong to sbyte, byte, short, ushort, int, uint, long, char
1669        //
1670        switch (target_type.BuiltinType) {
1671        case BuiltinTypeSpec.Type.SByte:
1672          return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1);
1673        case BuiltinTypeSpec.Type.Byte:
1674          return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1);
1675        case BuiltinTypeSpec.Type.Short:
1676          return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2);
1677        case BuiltinTypeSpec.Type.UShort:
1678          return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2);
1679        case BuiltinTypeSpec.Type.Int:
1680          return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4);
1681        case BuiltinTypeSpec.Type.UInt:
1682          return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4);
1683        case BuiltinTypeSpec.Type.Long:
1684          return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8);
1685        case BuiltinTypeSpec.Type.Char:
1686          return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH);
1687
1688        // One of the built-in conversions that belonged in the class library
1689        case BuiltinTypeSpec.Type.IntPtr:
1690          return new OperatorCast (EmptyCast.Create (expr, rc.BuiltinTypes.Long), target_type, true);
1691        }
1692        break;
1693      case BuiltinTypeSpec.Type.Char:
1694        //
1695        // From char to sbyte, byte, short
1696        //
1697        switch (target_type.BuiltinType) {
1698        case BuiltinTypeSpec.Type.SByte:
1699          return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1);
1700        case BuiltinTypeSpec.Type.Byte:
1701          return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1);
1702        case BuiltinTypeSpec.Type.Short:
1703          return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2);
1704        }
1705        break;
1706      case BuiltinTypeSpec.Type.Float:
1707        //
1708        // From float to sbyte, byte, short,
1709        // ushort, int, uint, long, ulong, char
1710        // or decimal
1711        //
1712        switch (target_type.BuiltinType) {
1713        case BuiltinTypeSpec.Type.SByte:
1714          return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1);
1715        case BuiltinTypeSpec.Type.Byte:
1716          return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1);
1717        case BuiltinTypeSpec.Type.Short:
1718          return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2);
1719        case BuiltinTypeSpec.Type.UShort:
1720          return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2);
1721        case BuiltinTypeSpec.Type.Int:
1722          return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4);
1723        case BuiltinTypeSpec.Type.UInt:
1724          return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4);
1725        case BuiltinTypeSpec.Type.Long:
1726          return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8);
1727        case BuiltinTypeSpec.Type.ULong:
1728          return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8);
1729        case BuiltinTypeSpec.Type.Char:
1730          return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH);
1731        case BuiltinTypeSpec.Type.Decimal:
1732          return new OperatorCast (expr, target_type, true);
1733        }
1734        break;
1735      case BuiltinTypeSpec.Type.Double:
1736        //
1737        // From double to sbyte, byte, short,
1738        // ushort, int, uint, long, ulong,
1739        // char, float or decimal
1740        //
1741        switch (target_type.BuiltinType) {
1742        case BuiltinTypeSpec.Type.SByte:
1743          return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1);
1744        case BuiltinTypeSpec.Type.Byte:
1745          return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1);
1746        case BuiltinTypeSpec.Type.Short:
1747          return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2);
1748        case BuiltinTypeSpec.Type.UShort:
1749          return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2);
1750        case BuiltinTypeSpec.Type.Int:
1751          return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4);
1752        case BuiltinTypeSpec.Type.UInt:
1753          return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4);
1754        case BuiltinTypeSpec.Type.Long:
1755          return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8);
1756        case BuiltinTypeSpec.Type.ULong:
1757          return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8);
1758        case BuiltinTypeSpec.Type.Char:
1759          return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH);
1760        case BuiltinTypeSpec.Type.Float:
1761          return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4);
1762        case BuiltinTypeSpec.Type.Decimal:
1763          return new OperatorCast (expr, target_type, true);
1764        }
1765        break;
1766      case BuiltinTypeSpec.Type.UIntPtr:
1767        //
1768        // Various built-in conversions that belonged in the class library
1769        //
1770        // from uintptr to sbyte, short, int32
1771        //
1772        switch (target_type.BuiltinType) {
1773        case BuiltinTypeSpec.Type.SByte:
1774          return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I1);
1775        case BuiltinTypeSpec.Type.Short:
1776          return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I2);
1777        case BuiltinTypeSpec.Type.Int:
1778          return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type);
1779        case BuiltinTypeSpec.Type.UInt:
1780          return new OperatorCast (expr, expr.Type, target_type, true);
1781        case BuiltinTypeSpec.Type.Long:
1782          return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.ULong, true), target_type);
1783        }
1784        break;
1785      case BuiltinTypeSpec.Type.IntPtr:
1786        if (target_type.BuiltinType == BuiltinTypeSpec.Type.UInt)
1787          return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Int, true), target_type);
1788        if (target_type.BuiltinType == BuiltinTypeSpec.Type.ULong)
1789          return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Long, true), target_type);
1790       
1791        break;
1792      case BuiltinTypeSpec.Type.Decimal:
1793        // From decimal to sbyte, byte, short,
1794        // ushort, int, uint, long, ulong, char,
1795        // float, or double
1796        switch (target_type.BuiltinType) {
1797        case BuiltinTypeSpec.Type.SByte:
1798        case BuiltinTypeSpec.Type.Byte:
1799        case BuiltinTypeSpec.Type.Short:
1800        case BuiltinTypeSpec.Type.UShort:
1801        case BuiltinTypeSpec.Type.Int:
1802        case BuiltinTypeSpec.Type.UInt:
1803        case BuiltinTypeSpec.Type.Long:
1804        case BuiltinTypeSpec.Type.ULong:
1805        case BuiltinTypeSpec.Type.Char:
1806        case BuiltinTypeSpec.Type.Float:
1807        case BuiltinTypeSpec.Type.Double:
1808          return new OperatorCast (expr, expr.Type, target_type, true);
1809        }
1810
1811        break;
1812      }
1813
1814      return null;
1815    }
1816
1817    /// <summary>
1818    ///  Returns whether an explicit reference conversion can be performed
1819    ///  from source_type to target_type
1820    /// </summary>
1821    public static bool ExplicitReferenceConversionExists (TypeSpec source_type, TypeSpec target_type)
1822    {
1823      Expression e = ExplicitReferenceConversion (null, source_type, target_type);
1824      if (e == null)
1825        return false;
1826
1827      if (e == EmptyExpression.Null)
1828        return true;
1829
1830      throw new InternalErrorException ("Invalid probing conversion result");
1831    }
1832
1833    /// <summary>
1834    ///   Implements Explicit Reference conversions
1835    /// </summary>
1836    static Expression ExplicitReferenceConversion (Expression source, TypeSpec source_type, TypeSpec target_type)
1837    {
1838      //
1839      // From object to a generic parameter
1840      //
1841      if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object && TypeManager.IsGenericParameter (target_type))
1842        return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1843
1844      //
1845      // Explicit type parameter conversion from T
1846      //
1847      if (source_type.Kind == MemberKind.TypeParameter)
1848        return ExplicitTypeParameterConversionFromT (source, source_type, target_type);
1849
1850      bool target_is_value_type = target_type.Kind == MemberKind.Struct || target_type.Kind == MemberKind.Enum;
1851
1852      //
1853      // Unboxing conversion from System.ValueType to any non-nullable-value-type
1854      //
1855      if (source_type.BuiltinType == BuiltinTypeSpec.Type.ValueType && target_is_value_type)
1856        return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type);
1857
1858      //
1859      // From object or dynamic to any reference type or value type (unboxing)
1860      //
1861      if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object || source_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1862        if (target_type.IsPointer)
1863          return null;
1864
1865        return
1866          source == null ? EmptyExpression.Null :
1867          target_is_value_type ? new UnboxCast (source, target_type) :
1868          source is Constant ? (Expression) new EmptyConstantCast ((Constant) source, target_type) :
1869          new ClassCast (source, target_type);
1870      }
1871
1872      //
1873      // From any class S to any class-type T, provided S is a base class of T
1874      //
1875      if (source_type.Kind == MemberKind.Class && TypeSpec.IsBaseClass (target_type, source_type, true))
1876        return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1877
1878      //
1879      // From any interface-type S to to any class type T, provided T is not
1880      // sealed, or provided T implements S.
1881      //
1882      // This also covers Explicit conversions involving type parameters
1883      // section From any interface type to T
1884      //
1885      if (source_type.Kind == MemberKind.Interface) {
1886        if (!target_type.IsSealed || target_type.ImplementsInterface (source_type, true)) {
1887          if (source == null)
1888            return EmptyExpression.Null;
1889
1890          //
1891          // Unboxing conversion from any interface-type to any non-nullable-value-type that
1892          // implements the interface-type
1893          //
1894          return target_is_value_type ? new UnboxCast (source, target_type) : (Expression) new ClassCast (source, target_type);
1895        }
1896
1897        //
1898        // From System.Collections.Generic.IList<T> and its base interfaces to a one-dimensional
1899        // array type S[], provided there is an implicit or explicit reference conversion from S to T.
1900        //
1901        var target_array = target_type as ArrayContainer;
1902        if (target_array != null && IList_To_Array (source_type, target_array))
1903          return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1904
1905        return null;
1906      }
1907
1908      var source_array = source_type as ArrayContainer;
1909      if (source_array != null) {
1910        var target_array = target_type as ArrayContainer;
1911        if (target_array != null) {
1912          //
1913          // From System.Array to any array-type
1914          //
1915          if (source_type.BuiltinType == BuiltinTypeSpec.Type.Array)
1916            return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1917
1918          //
1919          // From an array type S with an element type Se to an array type T with an
1920          // element type Te provided all the following are true:
1921          //     * S and T differe only in element type, in other words, S and T
1922          //       have the same number of dimensions.
1923          //     * Both Se and Te are reference types
1924          //     * An explicit reference conversions exist from Se to Te
1925          //
1926          if (source_array.Rank == target_array.Rank) {
1927
1928            source_type = source_array.Element;
1929            var target_element = target_array.Element;
1930
1931            //
1932            // LAMESPEC: Type parameters are special cased somehow but
1933            // only when both source and target elements are type parameters
1934            //
1935            if ((source_type.Kind & target_element.Kind & MemberKind.TypeParameter) == MemberKind.TypeParameter) {
1936              //
1937              // Conversion is allowed unless source element type has struct constrain
1938              //
1939              if (TypeSpec.IsValueType (source_type))
1940                return null;
1941            } else {
1942              if (!TypeSpec.IsReferenceType (source_type))
1943                return null;
1944            }
1945
1946            if (!TypeSpec.IsReferenceType (target_element))
1947              return null;
1948
1949            if (ExplicitReferenceConversionExists (source_type, target_element))
1950              return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1951             
1952            return null;
1953          }
1954        }
1955
1956        //
1957        // From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces,
1958        // provided that there is an explicit reference conversion from S to T
1959        //
1960        if (ArrayToIList (source_array, target_type, true))
1961          return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1962
1963        return null;
1964      }
1965
1966      //
1967      // From any class type S to any interface T, provides S is not sealed
1968      // and provided S does not implement T.
1969      //
1970      if (target_type.IsInterface && !source_type.IsSealed && !source_type.ImplementsInterface (target_type, true)) {
1971        return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1972      }
1973
1974      //
1975      // From System delegate to any delegate-type
1976      //
1977      if (source_type.BuiltinType == BuiltinTypeSpec.Type.Delegate && target_type.IsDelegate)
1978        return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
1979
1980      //
1981      // From variant generic delegate to same variant generic delegate type
1982      //
1983      if (source_type.IsDelegate && target_type.IsDelegate && source_type.MemberDefinition == target_type.MemberDefinition) {
1984        var tparams = source_type.MemberDefinition.TypeParameters;
1985        var targs_src = source_type.TypeArguments;
1986        var targs_dst = target_type.TypeArguments;
1987        int i;
1988        for (i = 0; i < tparams.Length; ++i) {
1989          //
1990          // If TP is invariant, types have to be identical
1991          //
1992          if (TypeSpecComparer.IsEqual (targs_src[i], targs_dst[i]))
1993            continue;
1994
1995          if (tparams[i].Variance == Variance.Covariant) {
1996            //
1997            //If TP is covariant, an implicit or explicit identity or reference conversion is required
1998            //
1999            if (ImplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
2000              continue;
2001
2002            if (ExplicitReferenceConversionExists (targs_src[i], targs_dst[i]))
2003              continue;
2004
2005          } else if (tparams[i].Variance == Variance.Contravariant) {
2006            //
2007            //If TP is contravariant, both are either identical or reference types
2008            //
2009            if (TypeSpec.IsReferenceType (targs_src[i]) && TypeSpec.IsReferenceType (targs_dst[i]))
2010              continue;
2011          }
2012
2013          break;
2014        }
2015
2016        if (i == tparams.Length)
2017          return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
2018      }
2019
2020      var tps = target_type as TypeParameterSpec;
2021      if (tps != null)
2022        return ExplicitTypeParameterConversionToT (source, source_type, tps);
2023
2024      return null;
2025    }
2026
2027    /// <summary>
2028    ///   Performs an explicit conversion of the expression `expr' whose
2029    ///   type is expr.Type to `target_type'.
2030    /// </summary>
2031    static public Expression ExplicitConversionCore (ResolveContext ec, Expression expr,
2032                 TypeSpec target_type, Location loc)
2033    {
2034      TypeSpec expr_type = expr.Type;
2035
2036      // Explicit conversion includes implicit conversion and it used for enum underlying types too
2037      Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc, true);
2038      if (ne != null)
2039        return ne;
2040
2041      if (expr_type.IsEnum) {
2042        TypeSpec real_target = target_type.IsEnum ? EnumSpec.GetUnderlyingType (target_type) : target_type;
2043        Expression underlying = EmptyCast.Create (expr, EnumSpec.GetUnderlyingType (expr_type));
2044        if (underlying.Type == real_target)
2045          ne = underlying;
2046
2047        if (ne == null)
2048          ne = ImplicitNumericConversion (underlying, real_target);
2049
2050        if (ne == null)
2051          ne = ExplicitNumericConversion (ec, underlying, real_target);
2052
2053        //
2054        // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
2055        //
2056        if (ne == null && (real_target.BuiltinType == BuiltinTypeSpec.Type.IntPtr || real_target.BuiltinType == BuiltinTypeSpec.Type.UIntPtr))
2057          ne = ExplicitUserConversion (ec, underlying, real_target, loc);
2058
2059        return ne != null ? EmptyCast.Create (ne, target_type) : null;
2060      }
2061
2062      if (target_type.IsEnum) {
2063        //
2064        // System.Enum can be unboxed to any enum-type
2065        //
2066        if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Enum)
2067          return new UnboxCast (expr, target_type);
2068
2069        TypeSpec real_target = target_type.IsEnum ? EnumSpec.GetUnderlyingType (target_type) : target_type;
2070
2071        if (expr_type == real_target)
2072          return EmptyCast.Create (expr, target_type);
2073
2074        Constant c = expr as Constant;
2075        if (c != null) {
2076          c = c.TryReduce (ec, real_target);
2077          if (c != null)
2078            return c;
2079        } else {
2080          ne = ImplicitNumericConversion (expr, real_target);
2081          if (ne != null)
2082            return EmptyCast.Create (ne, target_type);
2083
2084          ne = ExplicitNumericConversion (ec, expr, real_target);
2085          if (ne != null)
2086            return EmptyCast.Create (ne, target_type);
2087
2088          //
2089          // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed
2090          //
2091          if (expr_type.BuiltinType == BuiltinTypeSpec.Type.IntPtr || expr_type.BuiltinType == BuiltinTypeSpec.Type.UIntPtr) {
2092            ne = ExplicitUserConversion (ec, expr, real_target, loc);
2093            if (ne != null)
2094              return ExplicitConversionCore (ec, ne, target_type, loc);
2095          }
2096        }
2097      } else {
2098        ne = ExplicitNumericConversion (ec, expr, target_type);
2099        if (ne != null)
2100          return ne;
2101      }
2102
2103      //
2104      // Skip the ExplicitReferenceConversion because we can not convert
2105      // from Null to a ValueType, and ExplicitReference wont check against
2106      // null literal explicitly
2107      //
2108      if (expr_type != InternalType.NullLiteral) {
2109        ne = ExplicitReferenceConversion (expr, expr_type, target_type);
2110        if (ne != null)
2111          return ne;
2112      }
2113
2114      if (ec.IsUnsafe){
2115        ne = ExplicitUnsafe (expr, target_type);
2116        if (ne != null)
2117          return ne;
2118      }
2119     
2120      return null;
2121    }
2122
2123    public static Expression ExplicitUnsafe (Expression expr, TypeSpec target_type)
2124    {
2125      TypeSpec expr_type = expr.Type;
2126
2127      if (target_type.IsPointer){
2128        if (expr_type.IsPointer)
2129          return EmptyCast.Create (expr, target_type);
2130
2131        switch (expr_type.BuiltinType) {
2132        case BuiltinTypeSpec.Type.SByte:
2133        case BuiltinTypeSpec.Type.Short:
2134        case BuiltinTypeSpec.Type.Int:
2135          return new OpcodeCast (expr, target_type, OpCodes.Conv_I);
2136
2137        case BuiltinTypeSpec.Type.UShort:
2138        case BuiltinTypeSpec.Type.UInt:
2139        case BuiltinTypeSpec.Type.Byte:
2140          return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
2141
2142        case BuiltinTypeSpec.Type.Long:
2143          return new ConvCast (expr, target_type, ConvCast.Mode.I8_I);
2144
2145        case BuiltinTypeSpec.Type.ULong:
2146          return new ConvCast (expr, target_type, ConvCast.Mode.U8_I);
2147        }
2148      }
2149
2150      if (expr_type.IsPointer){
2151        switch (target_type.BuiltinType) {
2152        case BuiltinTypeSpec.Type.SByte:
2153          return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
2154        case BuiltinTypeSpec.Type.Byte:
2155          return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
2156        case BuiltinTypeSpec.Type.Short:
2157          return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
2158        case BuiltinTypeSpec.Type.UShort:
2159          return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
2160        case BuiltinTypeSpec.Type.Int:
2161          return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
2162        case BuiltinTypeSpec.Type.UInt:
2163          return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
2164        case BuiltinTypeSpec.Type.Long:
2165          return new ConvCast (expr, target_type, ConvCast.Mode.I_I8);
2166        case BuiltinTypeSpec.Type.ULong:
2167          return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
2168        }
2169      }
2170      return null;
2171    }
2172
2173    /// <summary>
2174    ///   Same as ExplicitConversion, only it doesn't include user defined conversions
2175    /// </summary>
2176    static public Expression ExplicitConversionStandard (ResolveContext ec, Expression expr,
2177                     TypeSpec target_type, Location l)
2178    {
2179      int errors = ec.Report.Errors;
2180      Expression ne = ImplicitConversionStandard (ec, expr, target_type, l);
2181      if (ec.Report.Errors > errors)
2182        return null;
2183
2184      if (ne != null)
2185        return ne;
2186
2187      ne = ExplicitNumericConversion (ec, expr, target_type);
2188      if (ne != null)
2189        return ne;
2190
2191      ne = ExplicitReferenceConversion (expr, expr.Type, target_type);
2192      if (ne != null)
2193        return ne;
2194
2195      if (ec.IsUnsafe && expr.Type.IsPointer && target_type.IsPointer && ((PointerContainer)expr.Type).Element.Kind == MemberKind.Void)
2196        return EmptyCast.Create (expr, target_type);
2197
2198      expr.Error_ValueCannotBeConverted (ec, target_type, true);
2199      return null;
2200    }
2201
2202    /// <summary>
2203    ///   Performs an explicit conversion of the expression `expr' whose
2204    ///   type is expr.Type to `target_type'.
2205    /// </summary>
2206    static public Expression ExplicitConversion (ResolveContext ec, Expression expr,
2207      TypeSpec target_type, Location loc)
2208    {
2209      Expression e = ExplicitConversionCore (ec, expr, target_type, loc);
2210      if (e != null) {
2211        //
2212        // Don't eliminate explicit precission casts
2213        //
2214        if (e == expr) {
2215          if (target_type.BuiltinType == BuiltinTypeSpec.Type.Float)
2216            return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
2217         
2218          if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double)
2219            return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
2220        }
2221         
2222        return e;
2223      }
2224
2225      TypeSpec expr_type = expr.Type;
2226      if (target_type.IsNullableType) {
2227        TypeSpec target;
2228
2229        if (expr_type.IsNullableType) {
2230          target = Nullable.NullableInfo.GetUnderlyingType (target_type);
2231          Expression unwrap = Nullable.Unwrap.Create (expr);
2232          e = ExplicitConversion (ec, unwrap, target, expr.Location);
2233          if (e == null)
2234            return null;
2235
2236          return new Nullable.LiftedConversion (e, unwrap, target_type).Resolve (ec);
2237        }
2238        if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Object) {
2239          return new UnboxCast (expr, target_type);
2240        }
2241
2242        target = TypeManager.GetTypeArguments (target_type) [0];
2243        e = ExplicitConversionCore (ec, expr, target, loc);
2244        if (e != null)
2245          return TypeSpec.IsReferenceType (expr.Type) ? new UnboxCast (expr, target_type) : Nullable.Wrap.Create (e, target_type);
2246      } else if (expr_type.IsNullableType) {
2247        e = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);
2248        if (e != null)
2249          return e;
2250
2251        e = Nullable.Unwrap.Create (expr, false);     
2252        e = ExplicitConversionCore (ec, e, target_type, loc);
2253        if (e != null)
2254          return EmptyCast.Create (e, target_type);
2255      }
2256     
2257      e = ExplicitUserConversion (ec, expr, target_type, loc);
2258
2259      if (e != null)
2260        return e;     
2261
2262      expr.Error_ValueCannotBeConverted (ec, target_type, true);
2263      return null;
2264    }
2265  }
2266}
Note: See TracBrowser for help on using the repository browser.