~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/convert.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

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