2 // conversion.cs: various routines for implementing conversions.
5 // Miguel de Icaza (miguel@ximian.com)
6 // Ravi Pratap (ravi@ximian.com)
8 // (C) 2001, 2002, 2003 Ximian, Inc.
11 namespace Mono
.CSharp
{
13 using System
.Collections
;
14 using System
.Diagnostics
;
15 using System
.Reflection
;
16 using System
.Reflection
.Emit
;
19 // A container class for all the conversion operations
21 public class Convert
{
23 static Expression
TypeParameter_to_Null (Type target_type
, Location loc
)
25 if (!TypeParameter_to_Null (target_type
)) {
26 Report
.Error (403, loc
, "Cannot convert null to the type " +
27 "parameter `{0}' becaues it could be a value " +
28 "type. Consider using `default ({0})' instead.",
29 target_type
.ToString ());
33 Constant expr
= new Nullable
.NullableLiteral (target_type
, loc
);
34 return new NullCast (expr
, target_type
);
37 static bool TypeParameter_to_Null (Type target_type
)
39 GenericConstraints gc
= TypeManager
.GetTypeParameterConstraints (target_type
);
43 if (gc
.HasReferenceTypeConstraint
)
45 if (gc
.HasClassConstraint
&& !TypeManager
.IsValueType (gc
.ClassConstraint
))
51 static Type
TypeParam_EffectiveBaseType (GenericConstraints gc
)
53 ArrayList list
= new ArrayList ();
54 list
.Add (gc
.EffectiveBaseClass
);
55 foreach (Type t
in gc
.InterfaceConstraints
) {
56 if (!t
.IsGenericParameter
)
59 GenericConstraints new_gc
= TypeManager
.GetTypeParameterConstraints (t
);
61 list
.Add (TypeParam_EffectiveBaseType (new_gc
));
63 return FindMostEncompassedType (list
);
66 static Expression
ImplicitTypeParameterConversion (Expression expr
,
69 Type expr_type
= expr
.Type
;
71 GenericConstraints gc
= TypeManager
.GetTypeParameterConstraints (expr_type
);
74 if (target_type
== TypeManager
.object_type
)
75 return new BoxedCast (expr
, target_type
);
80 // We're converting from a type parameter which is known to be a reference type.
81 Type base_type
= TypeParam_EffectiveBaseType (gc
);
83 if (TypeManager
.IsSubclassOf (base_type
, target_type
))
84 return new ClassCast (expr
, target_type
);
86 if (target_type
.IsInterface
) {
87 if (TypeManager
.ImplementsInterface (base_type
, target_type
))
88 return new ClassCast (expr
, target_type
);
90 foreach (Type t
in gc
.InterfaceConstraints
) {
91 if (TypeManager
.IsSubclassOf (t
, target_type
))
92 return new ClassCast (expr
, target_type
);
93 if (TypeManager
.ImplementsInterface (t
, target_type
))
94 return new ClassCast (expr
, target_type
);
98 foreach (Type t
in gc
.InterfaceConstraints
) {
99 if (!t
.IsGenericParameter
)
101 if (TypeManager
.IsSubclassOf (t
, target_type
))
102 return new ClassCast (expr
, target_type
);
103 if (TypeManager
.ImplementsInterface (t
, target_type
))
104 return new ClassCast (expr
, target_type
);
110 static bool ExplicitTypeParameterConversionExists (Type source_type
, Type target_type
)
112 if (target_type
.IsInterface
)
115 if (target_type
.IsGenericParameter
) {
116 GenericConstraints gc
= TypeManager
.GetTypeParameterConstraints (target_type
);
120 foreach (Type iface
in gc
.InterfaceConstraints
) {
121 if (!iface
.IsGenericParameter
)
124 if (TypeManager
.IsSubclassOf (source_type
, iface
))
132 static Expression
ExplicitTypeParameterConversion (Expression source
, Type target_type
)
134 Type source_type
= source
.Type
;
136 if (target_type
.IsInterface
)
137 return new ClassCast (source
, target_type
);
139 if (target_type
.IsGenericParameter
) {
140 GenericConstraints gc
= TypeManager
.GetTypeParameterConstraints (target_type
);
144 foreach (Type iface
in gc
.InterfaceConstraints
) {
145 if (!iface
.IsGenericParameter
)
148 if (TypeManager
.IsSubclassOf (source_type
, iface
))
149 return new ClassCast (source
, target_type
);
156 static EmptyExpression MyEmptyExpr
;
157 static public Expression
ImplicitReferenceConversion (Expression expr
, Type target_type
)
159 Type expr_type
= expr
.Type
;
161 if (expr_type
== null && expr
.eclass
== ExprClass
.MethodGroup
){
162 // if we are a method group, emit a warning
167 if (expr_type
== TypeManager
.void_type
)
170 if (expr_type
.IsGenericParameter
)
171 return ImplicitTypeParameterConversion (expr
, target_type
);
174 // notice that it is possible to write "ValueType v = 1", the ValueType here
175 // is an abstract class, and not really a value type, so we apply the same rules.
177 if (target_type
== TypeManager
.object_type
) {
179 // A pointer type cannot be converted to object
181 if (expr_type
.IsPointer
)
184 if (TypeManager
.IsValueType (expr_type
))
185 return new BoxedCast (expr
, target_type
);
186 if (expr_type
.IsClass
|| expr_type
.IsInterface
|| expr_type
== TypeManager
.enum_type
){
187 if (expr_type
== TypeManager
.anonymous_method_type
)
189 return new EmptyCast (expr
, target_type
);
193 } else if (target_type
== TypeManager
.value_type
) {
194 if (TypeManager
.IsValueType (expr_type
))
195 return new BoxedCast (expr
, target_type
);
196 if (expr_type
== TypeManager
.null_type
)
197 return new NullCast ((Constant
)expr
, target_type
);
200 } else if (TypeManager
.IsSubclassOf (expr_type
, target_type
)) {
202 // Special case: enumeration to System.Enum.
203 // System.Enum is not a value type, it is a class, so we need
204 // a boxing conversion
206 if (expr_type
.IsEnum
|| expr_type
.IsGenericParameter
)
207 return new BoxedCast (expr
, target_type
);
209 return new EmptyCast (expr
, target_type
);
212 // This code is kind of mirrored inside ImplicitStandardConversionExists
213 // with the small distinction that we only probe there
215 // Always ensure that the code here and there is in sync
217 // from the null type to any reference-type.
218 if (expr_type
== TypeManager
.null_type
){
219 if (target_type
.IsPointer
)
220 return new EmptyCast (NullPointer
.Null
, target_type
);
222 if (!target_type
.IsValueType
) {
223 if (expr
is Constant
)
224 return new NullCast ((Constant
)expr
, target_type
);
226 // I found only one case when it happens -- Foo () ? null : null;
227 Report
.Warning (-100, 1, expr
.Location
, "The result of the expression is always `null'");
228 return new NullCast (new NullLiteral (expr
.Location
), target_type
);
232 // from any class-type S to any interface-type T.
233 if (target_type
.IsInterface
) {
234 if (target_type
!= TypeManager
.iconvertible_type
&&
235 expr_type
.IsValueType
&& (expr
is Constant
) &&
236 !(expr
is IntLiteral
|| expr
is BoolLiteral
||
237 expr
is FloatLiteral
|| expr
is DoubleLiteral
||
238 expr
is LongLiteral
|| expr
is CharLiteral
||
239 expr
is StringLiteral
|| expr
is DecimalLiteral
||
240 expr
is UIntLiteral
|| expr
is ULongLiteral
)) {
244 if (TypeManager
.ImplementsInterface (expr_type
, target_type
)){
245 if (expr_type
.IsGenericParameter
|| TypeManager
.IsValueType (expr_type
))
246 return new BoxedCast (expr
, target_type
);
248 return new EmptyCast (expr
, target_type
);
252 // from any interface type S to interface-type T.
253 if (expr_type
.IsInterface
&& target_type
.IsInterface
) {
254 if (TypeManager
.ImplementsInterface (expr_type
, target_type
))
255 return new EmptyCast (expr
, target_type
);
260 // from an array-type S to an array-type of type T
261 if (expr_type
.IsArray
&& target_type
.IsArray
) {
262 if (expr_type
.GetArrayRank () == target_type
.GetArrayRank ()) {
264 Type expr_element_type
= TypeManager
.GetElementType (expr_type
);
266 if (MyEmptyExpr
== null)
267 MyEmptyExpr
= new EmptyExpression ();
269 MyEmptyExpr
.SetType (expr_element_type
);
270 Type target_element_type
= TypeManager
.GetElementType (target_type
);
272 if (!expr_element_type
.IsValueType
&& !target_element_type
.IsValueType
)
273 if (ImplicitStandardConversionExists (MyEmptyExpr
,
274 target_element_type
))
275 return new EmptyCast (expr
, target_type
);
279 // from an array-type to System.Array
280 if (expr_type
.IsArray
&& target_type
== TypeManager
.array_type
)
281 return new EmptyCast (expr
, target_type
);
283 // from an array-type of type T to IEnumerable<T>
284 if (expr_type
.IsArray
&& TypeManager
.IsIEnumerable (expr_type
, target_type
))
285 return new EmptyCast (expr
, target_type
);
287 // from any delegate type to System.Delegate
288 if ((expr_type
== TypeManager
.delegate_type
|| TypeManager
.IsDelegateType (expr_type
)) &&
289 target_type
== TypeManager
.delegate_type
)
290 return new EmptyCast (expr
, target_type
);
292 // from any array-type or delegate type into System.ICloneable.
293 if (expr_type
.IsArray
||
294 expr_type
== TypeManager
.delegate_type
|| TypeManager
.IsDelegateType (expr_type
))
295 if (target_type
== TypeManager
.icloneable_type
)
296 return new EmptyCast (expr
, target_type
);
298 // from a generic type definition to a generic instance.
299 if (TypeManager
.IsEqual (expr_type
, target_type
))
300 return new EmptyCast (expr
, target_type
);
306 // Tests whether an implicit reference conversion exists between expr_type
309 public static bool ImplicitReferenceConversionExists (Expression expr
, Type target_type
)
311 if (target_type
.IsValueType
)
314 Type expr_type
= expr
.Type
;
316 if (expr_type
.IsGenericParameter
)
317 return ImplicitTypeParameterConversion (expr
, target_type
) != null;
320 // This is the boxed case.
322 if (target_type
== TypeManager
.object_type
) {
323 if (expr_type
.IsClass
|| TypeManager
.IsValueType (expr_type
) ||
324 expr_type
.IsInterface
|| expr_type
== TypeManager
.enum_type
)
325 if (target_type
!= TypeManager
.anonymous_method_type
)
329 } else if (TypeManager
.IsSubclassOf (expr_type
, target_type
))
332 // Please remember that all code below actually comes
333 // from ImplicitReferenceConversion so make sure code remains in sync
335 // from any class-type S to any interface-type T.
336 if (target_type
.IsInterface
) {
337 if (target_type
!= TypeManager
.iconvertible_type
&&
338 expr_type
.IsValueType
&& (expr
is Constant
) &&
339 !(expr
is IntLiteral
|| expr
is BoolLiteral
||
340 expr
is FloatLiteral
|| expr
is DoubleLiteral
||
341 expr
is LongLiteral
|| expr
is CharLiteral
||
342 expr
is StringLiteral
|| expr
is DecimalLiteral
||
343 expr
is UIntLiteral
|| expr
is ULongLiteral
)) {
347 if (TypeManager
.ImplementsInterface (expr_type
, target_type
))
351 // from any interface type S to interface-type T.
352 if (expr_type
.IsInterface
&& target_type
.IsInterface
)
353 if (TypeManager
.ImplementsInterface (expr_type
, target_type
))
356 // from an array-type S to an array-type of type T
357 if (expr_type
.IsArray
&& target_type
.IsArray
) {
358 if (expr_type
.GetArrayRank () == target_type
.GetArrayRank ()) {
360 Type expr_element_type
= expr_type
.GetElementType ();
362 if (MyEmptyExpr
== null)
363 MyEmptyExpr
= new EmptyExpression ();
365 MyEmptyExpr
.SetType (expr_element_type
);
366 Type target_element_type
= TypeManager
.GetElementType (target_type
);
368 if (!expr_element_type
.IsValueType
&& !target_element_type
.IsValueType
)
369 if (ImplicitStandardConversionExists (MyEmptyExpr
,
370 target_element_type
))
375 // from an array-type to System.Array
376 if (expr_type
.IsArray
&& (target_type
== TypeManager
.array_type
))
379 // from an array-type of type T to IEnumerable<T>
380 if (expr_type
.IsArray
&& TypeManager
.IsIEnumerable (expr_type
, target_type
))
383 // from any delegate type to System.Delegate
384 if ((expr_type
== TypeManager
.delegate_type
|| TypeManager
.IsDelegateType (expr_type
)) &&
385 target_type
== TypeManager
.delegate_type
)
386 if (target_type
.IsAssignableFrom (expr_type
))
389 // from any array-type or delegate type into System.ICloneable.
390 if (expr_type
.IsArray
||
391 expr_type
== TypeManager
.delegate_type
|| TypeManager
.IsDelegateType (expr_type
))
392 if (target_type
== TypeManager
.icloneable_type
)
395 // from the null type to any reference-type.
396 if (expr_type
== TypeManager
.null_type
){
397 if (target_type
.IsPointer
)
400 if (!target_type
.IsValueType
)
404 // from a generic type definition to a generic instance.
405 if (TypeManager
.IsEqual (expr_type
, target_type
))
412 /// Implicit Numeric Conversions.
414 /// expr is the expression to convert, returns a new expression of type
415 /// target_type or null if an implicit conversion is not possible.
417 static public Expression
ImplicitNumericConversion (Expression expr
,
420 Type expr_type
= expr
.Type
;
423 // Attempt to do the implicit constant expression conversions
425 if (expr
is Constant
){
426 if (expr
is IntConstant
){
429 e
= TryImplicitIntConversion (target_type
, (IntConstant
) expr
);
433 } else if (expr
is LongConstant
&& target_type
== TypeManager
.uint64_type
){
435 // Try the implicit constant expression conversion
436 // from long to ulong, instead of a nice routine,
439 long v
= ((LongConstant
) expr
).Value
;
441 return new ULongConstant ((ulong) v
, expr
.Location
);
445 Type real_target_type
= target_type
;
447 if (expr_type
== TypeManager
.sbyte_type
){
449 // From sbyte to short, int, long, float, double, decimal
451 if (real_target_type
== TypeManager
.int32_type
)
452 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I4
);
453 if (real_target_type
== TypeManager
.int64_type
)
454 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I8
);
455 if (real_target_type
== TypeManager
.double_type
)
456 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
457 if (real_target_type
== TypeManager
.float_type
)
458 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R4
);
459 if (real_target_type
== TypeManager
.short_type
)
460 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I2
);
461 if (real_target_type
== TypeManager
.decimal_type
)
462 return new CastToDecimal (expr
);
463 } else if (expr_type
== TypeManager
.byte_type
){
465 // From byte to short, ushort, int, uint, long, ulong, float, double, decimal
467 if ((real_target_type
== TypeManager
.short_type
) ||
468 (real_target_type
== TypeManager
.ushort_type
) ||
469 (real_target_type
== TypeManager
.int32_type
) ||
470 (real_target_type
== TypeManager
.uint32_type
))
471 return new EmptyCast (expr
, target_type
);
473 if (real_target_type
== TypeManager
.uint64_type
)
474 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U8
);
475 if (real_target_type
== TypeManager
.int64_type
)
476 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I8
);
477 if (real_target_type
== TypeManager
.float_type
)
478 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R4
);
479 if (real_target_type
== TypeManager
.double_type
)
480 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
481 if (real_target_type
== TypeManager
.decimal_type
)
482 return new CastToDecimal (expr
);
484 } else if (expr_type
== TypeManager
.short_type
){
486 // From short to int, long, float, double, decimal
488 if (real_target_type
== TypeManager
.int32_type
)
489 return new EmptyCast (expr
, target_type
);
490 if (real_target_type
== TypeManager
.int64_type
)
491 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I8
);
492 if (real_target_type
== TypeManager
.double_type
)
493 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
494 if (real_target_type
== TypeManager
.float_type
)
495 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R4
);
496 if (real_target_type
== TypeManager
.decimal_type
)
497 return new CastToDecimal (expr
);
499 } else if (expr_type
== TypeManager
.ushort_type
){
501 // From ushort to int, uint, long, ulong, float, double, decimal
503 if (real_target_type
== TypeManager
.uint32_type
)
504 return new EmptyCast (expr
, target_type
);
506 if (real_target_type
== TypeManager
.uint64_type
)
507 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U8
);
508 if (real_target_type
== TypeManager
.int32_type
)
509 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I4
);
510 if (real_target_type
== TypeManager
.int64_type
)
511 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I8
);
512 if (real_target_type
== TypeManager
.double_type
)
513 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
514 if (real_target_type
== TypeManager
.float_type
)
515 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R4
);
516 if (real_target_type
== TypeManager
.decimal_type
)
517 return new CastToDecimal (expr
);
518 } else if (expr_type
== TypeManager
.int32_type
){
520 // From int to long, float, double, decimal
522 if (real_target_type
== TypeManager
.int64_type
)
523 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I8
);
524 if (real_target_type
== TypeManager
.double_type
)
525 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
526 if (real_target_type
== TypeManager
.float_type
)
527 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R4
);
528 if (real_target_type
== TypeManager
.decimal_type
)
529 return new CastToDecimal (expr
);
530 } else if (expr_type
== TypeManager
.uint32_type
){
532 // From uint to long, ulong, float, double, decimal
534 if (real_target_type
== TypeManager
.int64_type
)
535 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U8
);
536 if (real_target_type
== TypeManager
.uint64_type
)
537 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U8
);
538 if (real_target_type
== TypeManager
.double_type
)
539 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R_Un
,
541 if (real_target_type
== TypeManager
.float_type
)
542 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R_Un
,
544 if (real_target_type
== TypeManager
.decimal_type
)
545 return new CastToDecimal (expr
);
546 } else if (expr_type
== TypeManager
.int64_type
){
548 // From long/ulong to float, double
550 if (real_target_type
== TypeManager
.double_type
)
551 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
552 if (real_target_type
== TypeManager
.float_type
)
553 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R4
);
554 if (real_target_type
== TypeManager
.decimal_type
)
555 return new CastToDecimal (expr
);
556 } else if (expr_type
== TypeManager
.uint64_type
){
558 // From ulong to float, double
560 if (real_target_type
== TypeManager
.double_type
)
561 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R_Un
,
563 if (real_target_type
== TypeManager
.float_type
)
564 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R_Un
,
566 if (real_target_type
== TypeManager
.decimal_type
)
567 return new CastToDecimal (expr
);
568 } else if (expr_type
== TypeManager
.char_type
){
570 // From char to ushort, int, uint, long, ulong, float, double, decimal
572 if ((real_target_type
== TypeManager
.ushort_type
) ||
573 (real_target_type
== TypeManager
.int32_type
) ||
574 (real_target_type
== TypeManager
.uint32_type
))
575 return new EmptyCast (expr
, target_type
);
576 if (real_target_type
== TypeManager
.uint64_type
)
577 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U8
);
578 if (real_target_type
== TypeManager
.int64_type
)
579 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I8
);
580 if (real_target_type
== TypeManager
.float_type
)
581 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R4
);
582 if (real_target_type
== TypeManager
.double_type
)
583 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
584 if (real_target_type
== TypeManager
.decimal_type
)
585 return new CastToDecimal (expr
);
586 } else if (expr_type
== TypeManager
.float_type
){
590 if (real_target_type
== TypeManager
.double_type
)
591 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
598 /// Same as ImplicitStandardConversionExists except that it also looks at
599 /// implicit user defined conversions - needed for overload resolution
601 public static bool ImplicitConversionExists (EmitContext ec
, Expression expr
, Type target_type
)
603 if (expr
is NullLiteral
) {
604 if (target_type
.IsGenericParameter
)
605 return TypeParameter_to_Null (target_type
);
607 if (TypeManager
.IsNullableType (target_type
))
611 if (ImplicitStandardConversionExists (expr
, target_type
))
614 return ImplicitUserConversion (ec
, expr
, target_type
, Location
.Null
) != null;
617 public static bool ImplicitUserConversionExists (EmitContext ec
, Type source
, Type target
)
619 return ImplicitUserConversion (ec
, new EmptyExpression (source
), target
, Location
.Null
) != null;
623 /// Determines if a standard implicit conversion exists from
624 /// expr_type to target_type
626 /// ec should point to a real EmitContext if expr.Type is TypeManager.anonymous_method_type.
628 public static bool ImplicitStandardConversionExists (Expression expr
, Type target_type
)
630 Type expr_type
= expr
.Type
;
632 if (expr_type
== TypeManager
.void_type
)
635 //Console.WriteLine ("Expr is {0}", expr);
636 //Console.WriteLine ("{0} -> {1} ?", expr_type, target_type);
637 if (expr_type
.Equals (target_type
))
641 // First numeric conversions
643 if (expr_type
== TypeManager
.sbyte_type
){
645 // From sbyte to short, int, long, float, double, decimal
647 if ((target_type
== TypeManager
.int32_type
) ||
648 (target_type
== TypeManager
.int64_type
) ||
649 (target_type
== TypeManager
.double_type
) ||
650 (target_type
== TypeManager
.float_type
) ||
651 (target_type
== TypeManager
.short_type
) ||
652 (target_type
== TypeManager
.decimal_type
))
655 } else if (expr_type
== TypeManager
.byte_type
){
657 // From byte to short, ushort, int, uint, long, ulong, float, double, decimal
659 if ((target_type
== TypeManager
.short_type
) ||
660 (target_type
== TypeManager
.ushort_type
) ||
661 (target_type
== TypeManager
.int32_type
) ||
662 (target_type
== TypeManager
.uint32_type
) ||
663 (target_type
== TypeManager
.uint64_type
) ||
664 (target_type
== TypeManager
.int64_type
) ||
665 (target_type
== TypeManager
.float_type
) ||
666 (target_type
== TypeManager
.double_type
) ||
667 (target_type
== TypeManager
.decimal_type
))
670 } else if (expr_type
== TypeManager
.short_type
){
672 // From short to int, long, double, float, decimal
674 if ((target_type
== TypeManager
.int32_type
) ||
675 (target_type
== TypeManager
.int64_type
) ||
676 (target_type
== TypeManager
.double_type
) ||
677 (target_type
== TypeManager
.float_type
) ||
678 (target_type
== TypeManager
.decimal_type
))
681 } else if (expr_type
== TypeManager
.ushort_type
){
683 // From ushort to int, uint, long, ulong, double, float, decimal
685 if ((target_type
== TypeManager
.uint32_type
) ||
686 (target_type
== TypeManager
.uint64_type
) ||
687 (target_type
== TypeManager
.int32_type
) ||
688 (target_type
== TypeManager
.int64_type
) ||
689 (target_type
== TypeManager
.double_type
) ||
690 (target_type
== TypeManager
.float_type
) ||
691 (target_type
== TypeManager
.decimal_type
))
694 } else if (expr_type
== TypeManager
.int32_type
){
696 // From int to long, double, float, decimal
698 if ((target_type
== TypeManager
.int64_type
) ||
699 (target_type
== TypeManager
.double_type
) ||
700 (target_type
== TypeManager
.float_type
) ||
701 (target_type
== TypeManager
.decimal_type
))
704 } else if (expr_type
== TypeManager
.uint32_type
){
706 // From uint to long, ulong, double, float, decimal
708 if ((target_type
== TypeManager
.int64_type
) ||
709 (target_type
== TypeManager
.uint64_type
) ||
710 (target_type
== TypeManager
.double_type
) ||
711 (target_type
== TypeManager
.float_type
) ||
712 (target_type
== TypeManager
.decimal_type
))
715 } else if ((expr_type
== TypeManager
.uint64_type
) ||
716 (expr_type
== TypeManager
.int64_type
)) {
718 // From long/ulong to double, float, decimal
720 if ((target_type
== TypeManager
.double_type
) ||
721 (target_type
== TypeManager
.float_type
) ||
722 (target_type
== TypeManager
.decimal_type
))
725 } else if (expr_type
== TypeManager
.char_type
){
727 // From char to ushort, int, uint, ulong, long, float, double, decimal
729 if ((target_type
== TypeManager
.ushort_type
) ||
730 (target_type
== TypeManager
.int32_type
) ||
731 (target_type
== TypeManager
.uint32_type
) ||
732 (target_type
== TypeManager
.uint64_type
) ||
733 (target_type
== TypeManager
.int64_type
) ||
734 (target_type
== TypeManager
.float_type
) ||
735 (target_type
== TypeManager
.double_type
) ||
736 (target_type
== TypeManager
.decimal_type
))
739 } else if (expr_type
== TypeManager
.float_type
){
743 if (target_type
== TypeManager
.double_type
)
747 if (expr
.eclass
== ExprClass
.MethodGroup
){
748 if (TypeManager
.IsDelegateType (target_type
) && RootContext
.Version
!= LanguageVersion
.ISO_1
){
749 MethodGroupExpr mg
= expr
as MethodGroupExpr
;
751 return DelegateCreation
.ImplicitStandardConversionExists (mg
, target_type
) != null;
756 if (ImplicitReferenceConversionExists (expr
, target_type
))
760 // Implicit Constant Expression Conversions
762 if (expr
is IntConstant
){
763 int value = ((IntConstant
) expr
).Value
;
765 if (target_type
== TypeManager
.sbyte_type
){
766 if (value >= SByte
.MinValue
&& value <= SByte
.MaxValue
)
768 } else if (target_type
== TypeManager
.byte_type
){
769 if (value >= 0 && value <= Byte
.MaxValue
)
771 } else if (target_type
== TypeManager
.short_type
){
772 if (value >= Int16
.MinValue
&& value <= Int16
.MaxValue
)
774 } else if (target_type
== TypeManager
.ushort_type
){
775 if (value >= UInt16
.MinValue
&& value <= UInt16
.MaxValue
)
777 } else if (target_type
== TypeManager
.uint32_type
){
780 } else if (target_type
== TypeManager
.uint64_type
){
782 // we can optimize this case: a positive int32
783 // always fits on a uint64. But we need an opcode
790 if (value == 0 && expr
is IntLiteral
&& TypeManager
.IsEnumType (target_type
))
794 if (expr
is LongConstant
&& target_type
== TypeManager
.uint64_type
){
796 // Try the implicit constant expression conversion
797 // from long to ulong, instead of a nice routine,
800 long v
= ((LongConstant
) expr
).Value
;
805 if ((target_type
== TypeManager
.enum_type
||
806 target_type
.IsSubclassOf (TypeManager
.enum_type
)) &&
808 IntLiteral i
= (IntLiteral
) expr
;
815 // If `expr_type' implements `target_type' (which is an iface)
816 // see TryImplicitIntConversion
818 if (target_type
.IsInterface
&& target_type
.IsAssignableFrom (expr_type
))
821 if (target_type
== TypeManager
.void_ptr_type
&& expr_type
.IsPointer
)
824 if (TypeManager
.IsNullableType (expr_type
) && TypeManager
.IsNullableType (target_type
))
827 if (expr_type
== TypeManager
.anonymous_method_type
){
828 if (!TypeManager
.IsDelegateType (target_type
))
831 AnonymousMethod am
= (AnonymousMethod
) expr
;
832 return am
.ImplicitStandardConversionExists (target_type
);
839 /// Finds "most encompassed type" according to the spec (13.4.2)
840 /// amongst the methods in the MethodGroupExpr
842 static Type
FindMostEncompassedType (ArrayList types
)
846 if (types
.Count
== 0)
849 if (types
.Count
== 1)
850 return (Type
) types
[0];
852 EmptyExpression expr
= EmptyExpression
.Grab ();
854 foreach (Type t
in types
) {
861 if (ImplicitStandardConversionExists (expr
, best
))
866 foreach (Type t
in types
) {
869 if (!ImplicitStandardConversionExists (expr
, t
)) {
875 EmptyExpression
.Release (expr
);
881 /// Finds "most encompassing type" according to the spec (13.4.2)
882 /// amongst the types in the given set
884 static Type
FindMostEncompassingType (ArrayList types
)
888 if (types
.Count
== 0)
891 if (types
.Count
== 1)
892 return (Type
) types
[0];
894 EmptyExpression expr
= EmptyExpression
.Grab ();
896 foreach (Type t
in types
) {
903 if (ImplicitStandardConversionExists (expr
, t
))
907 foreach (Type t
in types
) {
911 if (!ImplicitStandardConversionExists (expr
, best
)) {
917 EmptyExpression
.Release (expr
);
923 /// Finds the most specific source Sx according to the rules of the spec (13.4.4)
924 /// by making use of FindMostEncomp* methods. Applies the correct rules separately
925 /// for explicit and implicit conversion operators.
927 static public Type
FindMostSpecificSource (IList list
,
928 Expression source
, bool apply_explicit_conv_rules
)
930 ArrayList src_types_set
= new ArrayList ();
933 // If any operator converts from S then Sx = S
935 Type source_type
= source
.Type
;
936 foreach (MethodBase mb
in list
){
937 ParameterData pd
= TypeManager
.GetParameterData (mb
);
938 Type param_type
= pd
.ParameterType (0);
940 if (param_type
== source_type
)
943 src_types_set
.Add (param_type
);
947 // Explicit Conv rules
949 if (apply_explicit_conv_rules
) {
950 ArrayList candidate_set
= new ArrayList ();
952 foreach (Type param_type
in src_types_set
){
953 if (ImplicitStandardConversionExists (source
, param_type
))
954 candidate_set
.Add (param_type
);
957 if (candidate_set
.Count
!= 0)
958 return FindMostEncompassedType (candidate_set
);
964 if (apply_explicit_conv_rules
)
965 return FindMostEncompassingType (src_types_set
);
967 return FindMostEncompassedType (src_types_set
);
971 /// Finds the most specific target Tx according to section 13.4.4
973 static public Type
FindMostSpecificTarget (IList list
,
974 Type target
, bool apply_explicit_conv_rules
)
976 ArrayList tgt_types_set
= new ArrayList ();
979 // If any operator converts to T then Tx = T
981 foreach (MethodInfo mi
in list
){
982 Type ret_type
= mi
.ReturnType
;
983 if (ret_type
== target
)
986 tgt_types_set
.Add (ret_type
);
990 // Explicit conv rules
992 if (apply_explicit_conv_rules
) {
993 ArrayList candidate_set
= new ArrayList ();
995 EmptyExpression expr
= EmptyExpression
.Grab ();
997 foreach (Type ret_type
in tgt_types_set
){
998 expr
.SetType (ret_type
);
1000 if (ImplicitStandardConversionExists (expr
, target
))
1001 candidate_set
.Add (ret_type
);
1004 EmptyExpression
.Release (expr
);
1006 if (candidate_set
.Count
!= 0)
1007 return FindMostEncompassingType (candidate_set
);
1011 // Okay, final case !
1013 if (apply_explicit_conv_rules
)
1014 return FindMostEncompassedType (tgt_types_set
);
1016 return FindMostEncompassingType (tgt_types_set
);
1020 /// User-defined Implicit conversions
1022 static public Expression
ImplicitUserConversion (EmitContext ec
, Expression source
,
1023 Type target
, Location loc
)
1025 return UserDefinedConversion (ec
, source
, target
, loc
, false);
1029 /// User-defined Explicit conversions
1031 static public Expression
ExplicitUserConversion (EmitContext ec
, Expression source
,
1032 Type target
, Location loc
)
1034 return UserDefinedConversion (ec
, source
, target
, loc
, true);
1037 static void AddConversionOperators (ArrayList list
,
1038 Expression source
, Type target_type
,
1039 bool look_for_explicit
,
1045 Type source_type
= source
.Type
;
1046 EmptyExpression expr
= EmptyExpression
.Grab ();
1047 foreach (MethodInfo m
in mg
.Methods
) {
1048 ParameterData pd
= TypeManager
.GetParameterData (m
);
1049 Type return_type
= m
.ReturnType
;
1050 Type arg_type
= pd
.ParameterType (0);
1052 if (source_type
!= arg_type
) {
1053 if (!ImplicitStandardConversionExists (source
, arg_type
)) {
1054 if (!look_for_explicit
)
1056 expr
.SetType (arg_type
);
1057 if (!ImplicitStandardConversionExists (expr
, source_type
))
1062 if (target_type
!= return_type
) {
1063 expr
.SetType (return_type
);
1064 if (!ImplicitStandardConversionExists (expr
, target_type
)) {
1065 if (!look_for_explicit
)
1067 expr
.SetType (target_type
);
1068 if (!ImplicitStandardConversionExists (expr
, return_type
))
1076 EmptyExpression
.Release (expr
);
1080 /// Compute the user-defined conversion operator from source_type to target_type.
1081 /// `look_for_explicit' controls whether we should also include the list of explicit operators
1083 static MethodInfo
GetConversionOperator (EmitContext ec
, Expression source
, Type target_type
, bool look_for_explicit
)
1085 ArrayList ops
= new ArrayList (4);
1087 Type source_type
= source
.Type
;
1089 if (source_type
!= TypeManager
.decimal_type
) {
1090 AddConversionOperators (ops
, source
, target_type
, look_for_explicit
,
1091 Expression
.MethodLookup (ec
, source_type
, "op_Implicit", Location
.Null
) as MethodGroupExpr
);
1092 if (look_for_explicit
) {
1093 AddConversionOperators (ops
, source
, target_type
, look_for_explicit
,
1094 Expression
.MethodLookup (
1095 ec
, source_type
, "op_Explicit", Location
.Null
) as MethodGroupExpr
);
1099 if (target_type
!= TypeManager
.decimal_type
) {
1100 AddConversionOperators (ops
, source
, target_type
, look_for_explicit
,
1101 Expression
.MethodLookup (ec
, target_type
, "op_Implicit", Location
.Null
) as MethodGroupExpr
);
1102 if (look_for_explicit
) {
1103 AddConversionOperators (ops
, source
, target_type
, look_for_explicit
,
1104 Expression
.MethodLookup (
1105 ec
, target_type
, "op_Explicit", Location
.Null
) as MethodGroupExpr
);
1112 Type most_specific_source
= FindMostSpecificSource (ops
, source
, look_for_explicit
);
1113 if (most_specific_source
== null)
1116 Type most_specific_target
= FindMostSpecificTarget (ops
, target_type
, look_for_explicit
);
1117 if (most_specific_target
== null)
1120 MethodInfo method
= null;
1122 foreach (MethodInfo m
in ops
) {
1123 if (m
.ReturnType
!= most_specific_target
)
1125 if (TypeManager
.GetParameterData (m
).ParameterType (0) != most_specific_source
)
1127 // Ambiguous: more than one conversion operator satisfies the signature.
1136 static DoubleHash explicit_conv
= new DoubleHash (100);
1137 static DoubleHash implicit_conv
= new DoubleHash (100);
1140 /// User-defined conversions
1142 static public Expression
UserDefinedConversion (EmitContext ec
, Expression source
,
1143 Type target
, Location loc
,
1144 bool look_for_explicit
)
1146 Type source_type
= source
.Type
;
1147 MethodInfo method
= null;
1149 if (TypeManager
.IsNullableType (source_type
) && TypeManager
.IsNullableType (target
))
1150 return new Nullable
.LiftedConversion (
1151 source
, target
, true, look_for_explicit
, loc
).Resolve (ec
);
1154 DoubleHash hash
= look_for_explicit
? explicit_conv
: implicit_conv
;
1156 if (!(source
is Constant
) && hash
.Lookup (source_type
, target
, out o
)) {
1157 method
= (MethodInfo
) o
;
1159 method
= GetConversionOperator (ec
, source
, target
, look_for_explicit
);
1160 if (!(source
is Constant
))
1161 hash
.Insert (source_type
, target
, method
);
1167 Type most_specific_source
= TypeManager
.GetParameterData (method
).ParameterType (0);
1170 // This will do the conversion to the best match that we
1171 // found. Now we need to perform an implict standard conversion
1172 // if the best match was not the type that we were requested
1175 if (look_for_explicit
)
1176 source
= ExplicitConversionStandard (ec
, source
, most_specific_source
, loc
);
1178 source
= ImplicitConversionStandard (ec
, source
, most_specific_source
, loc
);
1184 e
= new UserCast (method
, source
, loc
);
1185 if (e
.Type
!= target
){
1186 if (!look_for_explicit
)
1187 e
= ImplicitConversionStandard (ec
, e
, target
, loc
);
1189 e
= ExplicitConversionStandard (ec
, e
, target
, loc
);
1196 /// Converts implicitly the resolved expression `expr' into the
1197 /// `target_type'. It returns a new expression that can be used
1198 /// in a context that expects a `target_type'.
1200 static public Expression
ImplicitConversion (EmitContext ec
, Expression expr
,
1201 Type target_type
, Location loc
)
1205 if (target_type
== null)
1206 throw new Exception ("Target type is null");
1208 e
= ImplicitConversionStandard (ec
, expr
, target_type
, loc
);
1212 e
= ImplicitUserConversion (ec
, expr
, target_type
, loc
);
1221 /// Attempts to apply the `Standard Implicit
1222 /// Conversion' rules to the expression `expr' into
1223 /// the `target_type'. It returns a new expression
1224 /// that can be used in a context that expects a
1227 /// This is different from `ImplicitConversion' in that the
1228 /// user defined implicit conversions are excluded.
1230 static public Expression
ImplicitConversionStandard (EmitContext ec
, Expression expr
,
1231 Type target_type
, Location loc
)
1233 Type expr_type
= expr
.Type
;
1236 if (expr
is NullLiteral
) {
1237 if (target_type
.IsGenericParameter
)
1238 return TypeParameter_to_Null (target_type
, loc
);
1240 if (TypeManager
.IsNullableType (target_type
))
1241 return new Nullable
.NullableLiteral (target_type
, loc
);
1244 if (TypeManager
.IsNullableType (expr_type
) && TypeManager
.IsNullableType (target_type
))
1245 return new Nullable
.LiftedConversion (
1246 expr
, target_type
, false, false, loc
).Resolve (ec
);
1248 if (expr
.eclass
== ExprClass
.MethodGroup
){
1249 if (!TypeManager
.IsDelegateType (target_type
)){
1254 // Only allow anonymous method conversions on post ISO_1
1256 if (RootContext
.Version
!= LanguageVersion
.ISO_1
){
1257 MethodGroupExpr mg
= expr
as MethodGroupExpr
;
1259 return ImplicitDelegateCreation
.Create (
1260 ec
, mg
, target_type
, loc
);
1264 if (expr_type
.Equals (target_type
) && !TypeManager
.IsNullType (expr_type
))
1267 e
= ImplicitNumericConversion (expr
, target_type
);
1271 e
= ImplicitReferenceConversion (expr
, target_type
);
1275 if (TypeManager
.IsEnumType (target_type
) && expr
is IntLiteral
){
1276 IntLiteral i
= (IntLiteral
) expr
;
1279 return new EnumConstant ((Constant
) expr
, target_type
);
1283 if (expr_type
.IsPointer
){
1284 if (target_type
== TypeManager
.void_ptr_type
)
1285 return new EmptyCast (expr
, target_type
);
1288 // yep, comparing pointer types cant be done with
1289 // t1 == t2, we have to compare their element types.
1291 if (target_type
.IsPointer
){
1292 if (TypeManager
.GetElementType(target_type
) == TypeManager
.GetElementType(expr_type
))
1299 if (expr_type
== TypeManager
.null_type
&& target_type
.IsPointer
)
1300 return new EmptyCast (NullPointer
.Null
, target_type
);
1303 if (expr_type
== TypeManager
.anonymous_method_type
){
1304 if (!TypeManager
.IsDelegateType (target_type
)){
1305 Report
.Error (1660, loc
,
1306 "Cannot convert anonymous method block to type `{0}' because it is not a delegate type",
1307 TypeManager
.CSharpName (target_type
));
1311 AnonymousMethod am
= (AnonymousMethod
) expr
;
1312 int errors
= Report
.Errors
;
1314 Expression conv
= am
.Compatible (ec
, target_type
);
1319 // We return something instead of null, to avoid
1320 // the duplicate error, since am.Compatible would have
1321 // reported that already
1323 if (errors
!= Report
.Errors
)
1324 return new EmptyCast (expr
, target_type
);
1331 /// Attempts to perform an implicit constant conversion of the IntConstant
1332 /// into a different data type using casts (See Implicit Constant
1333 /// Expression Conversions)
1335 static public Expression
TryImplicitIntConversion (Type target_type
, IntConstant ic
)
1337 int value = ic
.Value
;
1339 if (target_type
== TypeManager
.sbyte_type
){
1340 if (value >= SByte
.MinValue
&& value <= SByte
.MaxValue
)
1341 return new SByteConstant ((sbyte) value, ic
.Location
);
1342 } else if (target_type
== TypeManager
.byte_type
){
1343 if (value >= Byte
.MinValue
&& value <= Byte
.MaxValue
)
1344 return new ByteConstant ((byte) value, ic
.Location
);
1345 } else if (target_type
== TypeManager
.short_type
){
1346 if (value >= Int16
.MinValue
&& value <= Int16
.MaxValue
)
1347 return new ShortConstant ((short) value, ic
.Location
);
1348 } else if (target_type
== TypeManager
.ushort_type
){
1349 if (value >= UInt16
.MinValue
&& value <= UInt16
.MaxValue
)
1350 return new UShortConstant ((ushort) value, ic
.Location
);
1351 } else if (target_type
== TypeManager
.uint32_type
){
1353 return new UIntConstant ((uint) value, ic
.Location
);
1354 } else if (target_type
== TypeManager
.uint64_type
){
1356 // we can optimize this case: a positive int32
1357 // always fits on a uint64. But we need an opcode
1361 return new ULongConstant ((ulong) value, ic
.Location
);
1362 } else if (target_type
== TypeManager
.double_type
)
1363 return new DoubleConstant ((double) value, ic
.Location
);
1364 else if (target_type
== TypeManager
.float_type
)
1365 return new FloatConstant ((float) value, ic
.Location
);
1367 if (value == 0 && ic
is IntLiteral
&& TypeManager
.IsEnumType (target_type
)){
1368 Type underlying
= TypeManager
.EnumToUnderlying (target_type
);
1369 Constant e
= (Constant
) ic
;
1372 // Possibly, we need to create a different 0 literal before passing
1375 if (underlying
== TypeManager
.int64_type
)
1376 e
= new LongLiteral (0, ic
.Location
);
1377 else if (underlying
== TypeManager
.uint64_type
)
1378 e
= new ULongLiteral (0, ic
.Location
);
1380 return new EnumConstant (e
, target_type
);
1384 // If `target_type' is an interface and the type of `ic' implements the interface
1385 // e.g. target_type is IComparable, IConvertible, IFormattable
1387 if (target_type
.IsInterface
&& target_type
.IsAssignableFrom (ic
.Type
))
1388 return new BoxedCast (ic
, target_type
);
1394 /// Attempts to implicitly convert `source' into `target_type', using
1395 /// ImplicitConversion. If there is no implicit conversion, then
1396 /// an error is signaled
1398 static public Expression
ImplicitConversionRequired (EmitContext ec
, Expression source
,
1399 Type target_type
, Location loc
)
1401 Expression e
= ImplicitConversion (ec
, source
, target_type
, loc
);
1405 source
.Error_ValueCannotBeConverted (loc
, target_type
, false);
1410 /// Performs the explicit numeric conversions
1412 public static Expression
ExplicitNumericConversion (Expression expr
, Type target_type
)
1414 Type expr_type
= expr
.Type
;
1415 Type real_target_type
= target_type
;
1417 if (expr_type
== TypeManager
.sbyte_type
){
1419 // From sbyte to byte, ushort, uint, ulong, char
1421 if (real_target_type
== TypeManager
.byte_type
)
1422 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I1_U1
);
1423 if (real_target_type
== TypeManager
.ushort_type
)
1424 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I1_U2
);
1425 if (real_target_type
== TypeManager
.uint32_type
)
1426 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I1_U4
);
1427 if (real_target_type
== TypeManager
.uint64_type
)
1428 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I1_U8
);
1429 if (real_target_type
== TypeManager
.char_type
)
1430 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I1_CH
);
1431 } else if (expr_type
== TypeManager
.byte_type
){
1433 // From byte to sbyte and char
1435 if (real_target_type
== TypeManager
.sbyte_type
)
1436 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U1_I1
);
1437 if (real_target_type
== TypeManager
.char_type
)
1438 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U1_CH
);
1439 } else if (expr_type
== TypeManager
.short_type
){
1441 // From short to sbyte, byte, ushort, uint, ulong, char
1443 if (real_target_type
== TypeManager
.sbyte_type
)
1444 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I2_I1
);
1445 if (real_target_type
== TypeManager
.byte_type
)
1446 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I2_U1
);
1447 if (real_target_type
== TypeManager
.ushort_type
)
1448 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I2_U2
);
1449 if (real_target_type
== TypeManager
.uint32_type
)
1450 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I2_U4
);
1451 if (real_target_type
== TypeManager
.uint64_type
)
1452 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I2_U8
);
1453 if (real_target_type
== TypeManager
.char_type
)
1454 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I2_CH
);
1455 } else if (expr_type
== TypeManager
.ushort_type
){
1457 // From ushort to sbyte, byte, short, char
1459 if (real_target_type
== TypeManager
.sbyte_type
)
1460 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U2_I1
);
1461 if (real_target_type
== TypeManager
.byte_type
)
1462 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U2_U1
);
1463 if (real_target_type
== TypeManager
.short_type
)
1464 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U2_I2
);
1465 if (real_target_type
== TypeManager
.char_type
)
1466 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U2_CH
);
1467 } else if (expr_type
== TypeManager
.int32_type
){
1469 // From int to sbyte, byte, short, ushort, uint, ulong, char
1471 if (real_target_type
== TypeManager
.sbyte_type
)
1472 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I4_I1
);
1473 if (real_target_type
== TypeManager
.byte_type
)
1474 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I4_U1
);
1475 if (real_target_type
== TypeManager
.short_type
)
1476 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I4_I2
);
1477 if (real_target_type
== TypeManager
.ushort_type
)
1478 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I4_U2
);
1479 if (real_target_type
== TypeManager
.uint32_type
)
1480 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I4_U4
);
1481 if (real_target_type
== TypeManager
.uint64_type
)
1482 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I4_U8
);
1483 if (real_target_type
== TypeManager
.char_type
)
1484 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I4_CH
);
1485 } else if (expr_type
== TypeManager
.uint32_type
){
1487 // From uint to sbyte, byte, short, ushort, int, char
1489 if (real_target_type
== TypeManager
.sbyte_type
)
1490 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U4_I1
);
1491 if (real_target_type
== TypeManager
.byte_type
)
1492 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U4_U1
);
1493 if (real_target_type
== TypeManager
.short_type
)
1494 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U4_I2
);
1495 if (real_target_type
== TypeManager
.ushort_type
)
1496 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U4_U2
);
1497 if (real_target_type
== TypeManager
.int32_type
)
1498 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U4_I4
);
1499 if (real_target_type
== TypeManager
.char_type
)
1500 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U4_CH
);
1501 } else if (expr_type
== TypeManager
.int64_type
){
1503 // From long to sbyte, byte, short, ushort, int, uint, ulong, char
1505 if (real_target_type
== TypeManager
.sbyte_type
)
1506 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I8_I1
);
1507 if (real_target_type
== TypeManager
.byte_type
)
1508 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I8_U1
);
1509 if (real_target_type
== TypeManager
.short_type
)
1510 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I8_I2
);
1511 if (real_target_type
== TypeManager
.ushort_type
)
1512 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I8_U2
);
1513 if (real_target_type
== TypeManager
.int32_type
)
1514 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I8_I4
);
1515 if (real_target_type
== TypeManager
.uint32_type
)
1516 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I8_U4
);
1517 if (real_target_type
== TypeManager
.uint64_type
)
1518 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I8_U8
);
1519 if (real_target_type
== TypeManager
.char_type
)
1520 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.I8_CH
);
1521 } else if (expr_type
== TypeManager
.uint64_type
){
1523 // From ulong to sbyte, byte, short, ushort, int, uint, long, char
1525 if (real_target_type
== TypeManager
.sbyte_type
)
1526 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U8_I1
);
1527 if (real_target_type
== TypeManager
.byte_type
)
1528 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U8_U1
);
1529 if (real_target_type
== TypeManager
.short_type
)
1530 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U8_I2
);
1531 if (real_target_type
== TypeManager
.ushort_type
)
1532 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U8_U2
);
1533 if (real_target_type
== TypeManager
.int32_type
)
1534 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U8_I4
);
1535 if (real_target_type
== TypeManager
.uint32_type
)
1536 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U8_U4
);
1537 if (real_target_type
== TypeManager
.int64_type
)
1538 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U8_I8
);
1539 if (real_target_type
== TypeManager
.char_type
)
1540 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.U8_CH
);
1541 } else if (expr_type
== TypeManager
.char_type
){
1543 // From char to sbyte, byte, short
1545 if (real_target_type
== TypeManager
.sbyte_type
)
1546 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.CH_I1
);
1547 if (real_target_type
== TypeManager
.byte_type
)
1548 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.CH_U1
);
1549 if (real_target_type
== TypeManager
.short_type
)
1550 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.CH_I2
);
1551 } else if (expr_type
== TypeManager
.float_type
){
1553 // From float to sbyte, byte, short,
1554 // ushort, int, uint, long, ulong, char
1557 if (real_target_type
== TypeManager
.sbyte_type
)
1558 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R4_I1
);
1559 if (real_target_type
== TypeManager
.byte_type
)
1560 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R4_U1
);
1561 if (real_target_type
== TypeManager
.short_type
)
1562 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R4_I2
);
1563 if (real_target_type
== TypeManager
.ushort_type
)
1564 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R4_U2
);
1565 if (real_target_type
== TypeManager
.int32_type
)
1566 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R4_I4
);
1567 if (real_target_type
== TypeManager
.uint32_type
)
1568 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R4_U4
);
1569 if (real_target_type
== TypeManager
.int64_type
)
1570 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R4_I8
);
1571 if (real_target_type
== TypeManager
.uint64_type
)
1572 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R4_U8
);
1573 if (real_target_type
== TypeManager
.char_type
)
1574 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R4_CH
);
1575 if (real_target_type
== TypeManager
.decimal_type
)
1576 return new CastToDecimal (expr
, true);
1577 } else if (expr_type
== TypeManager
.double_type
){
1579 // From double to sbyte, byte, short,
1580 // ushort, int, uint, long, ulong,
1581 // char, float or decimal
1583 if (real_target_type
== TypeManager
.sbyte_type
)
1584 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R8_I1
);
1585 if (real_target_type
== TypeManager
.byte_type
)
1586 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R8_U1
);
1587 if (real_target_type
== TypeManager
.short_type
)
1588 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R8_I2
);
1589 if (real_target_type
== TypeManager
.ushort_type
)
1590 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R8_U2
);
1591 if (real_target_type
== TypeManager
.int32_type
)
1592 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R8_I4
);
1593 if (real_target_type
== TypeManager
.uint32_type
)
1594 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R8_U4
);
1595 if (real_target_type
== TypeManager
.int64_type
)
1596 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R8_I8
);
1597 if (real_target_type
== TypeManager
.uint64_type
)
1598 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R8_U8
);
1599 if (real_target_type
== TypeManager
.char_type
)
1600 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R8_CH
);
1601 if (real_target_type
== TypeManager
.float_type
)
1602 return new ConvCast (expr
, target_type
, ConvCast
.Mode
.R8_R4
);
1603 if (real_target_type
== TypeManager
.decimal_type
)
1604 return new CastToDecimal (expr
, true);
1605 } else if (expr_type
== TypeManager
.decimal_type
) {
1606 return new CastFromDecimal (expr
, target_type
).Resolve ();
1612 /// Returns whether an explicit reference conversion can be performed
1613 /// from source_type to target_type
1615 public static bool ExplicitReferenceConversionExists (Type source_type
, Type target_type
)
1617 bool target_is_type_param
= target_type
.IsGenericParameter
;
1618 bool target_is_value_type
= target_type
.IsValueType
;
1620 if (source_type
== target_type
)
1624 // From generic parameter to any type
1626 if (source_type
.IsGenericParameter
)
1627 return ExplicitTypeParameterConversionExists (source_type
, target_type
);
1630 // From object to a generic parameter
1632 if (source_type
== TypeManager
.object_type
&& target_is_type_param
)
1636 // From object to any reference type
1638 if (source_type
== TypeManager
.object_type
&& !target_is_value_type
)
1642 // From any class S to any class-type T, provided S is a base class of T
1644 if (TypeManager
.IsSubclassOf (target_type
, source_type
))
1648 // From any interface type S to any interface T provided S is not derived from T
1650 if (source_type
.IsInterface
&& target_type
.IsInterface
){
1651 if (!TypeManager
.IsSubclassOf (target_type
, source_type
))
1656 // From any class type S to any interface T, provided S is not sealed
1657 // and provided S does not implement T.
1659 if (target_type
.IsInterface
&& !source_type
.IsSealed
&&
1660 !TypeManager
.ImplementsInterface (source_type
, target_type
))
1664 // From any interface-type S to to any class type T, provided T is not
1665 // sealed, or provided T implements S.
1667 if (source_type
.IsInterface
&&
1668 (!target_type
.IsSealed
|| TypeManager
.ImplementsInterface (target_type
, source_type
)))
1672 // From an array type S with an element type Se to an array type T with an
1673 // element type Te provided all the following are true:
1674 // * S and T differe only in element type, in other words, S and T
1675 // have the same number of dimensions.
1676 // * Both Se and Te are reference types
1677 // * An explicit referenc conversions exist from Se to Te
1679 if (source_type
.IsArray
&& target_type
.IsArray
) {
1680 if (source_type
.GetArrayRank () == target_type
.GetArrayRank ()) {
1682 Type source_element_type
= TypeManager
.GetElementType (source_type
);
1683 Type target_element_type
= TypeManager
.GetElementType (target_type
);
1685 if (source_element_type
.IsGenericParameter
||
1686 (!source_element_type
.IsValueType
&& !target_element_type
.IsValueType
))
1687 if (ExplicitReferenceConversionExists (source_element_type
,
1688 target_element_type
))
1694 // From System.Array to any array-type
1695 if (source_type
== TypeManager
.array_type
&&
1696 target_type
.IsArray
){
1701 // From System delegate to any delegate-type
1703 if (source_type
== TypeManager
.delegate_type
&&
1704 TypeManager
.IsDelegateType (target_type
))
1708 // From ICloneable to Array or Delegate types
1710 if (source_type
== TypeManager
.icloneable_type
&&
1711 (target_type
== TypeManager
.array_type
||
1712 target_type
== TypeManager
.delegate_type
))
1719 /// Implements Explicit Reference conversions
1721 static Expression
ExplicitReferenceConversion (Expression source
, Type target_type
)
1723 Type source_type
= source
.Type
;
1724 bool target_is_type_param
= target_type
.IsGenericParameter
;
1725 bool target_is_value_type
= target_type
.IsValueType
;
1728 // From object to a generic parameter
1730 if (source_type
== TypeManager
.object_type
&& target_is_type_param
)
1731 return new UnboxCast (source
, target_type
);
1734 // Explicit type parameter conversion.
1737 if (source_type
.IsGenericParameter
)
1738 return ExplicitTypeParameterConversion (source
, target_type
);
1741 // From object to any reference type
1743 if (source_type
== TypeManager
.object_type
&& !target_is_value_type
)
1744 return new ClassCast (source
, target_type
);
1747 // Unboxing conversion.
1749 if (((source_type
== TypeManager
.enum_type
&&
1750 !(source
is EmptyCast
)) ||
1751 source_type
== TypeManager
.value_type
) && target_is_value_type
)
1752 return new UnboxCast (source
, target_type
);
1755 // From any class S to any class-type T, provided S is a base class of T
1757 if (TypeManager
.IsSubclassOf (target_type
, source_type
))
1758 return new ClassCast (source
, target_type
);
1761 // From any interface type S to any interface T provided S is not derived from T
1763 if (source_type
.IsInterface
&& target_type
.IsInterface
){
1764 if (TypeManager
.ImplementsInterface (source_type
, target_type
))
1767 return new ClassCast (source
, target_type
);
1771 // From any class type S to any interface T, provides S is not sealed
1772 // and provided S does not implement T.
1774 if (target_type
.IsInterface
&& !source_type
.IsSealed
) {
1775 if (TypeManager
.ImplementsInterface (source_type
, target_type
))
1778 return new ClassCast (source
, target_type
);
1783 // From any interface-type S to to any class type T, provided T is not
1784 // sealed, or provided T implements S.
1786 if (source_type
.IsInterface
) {
1787 if (!target_type
.IsSealed
|| TypeManager
.ImplementsInterface (target_type
, source_type
)) {
1788 if (target_type
.IsClass
)
1789 return new ClassCast (source
, target_type
);
1791 return new UnboxCast (source
, target_type
);
1797 // From an array type S with an element type Se to an array type T with an
1798 // element type Te provided all the following are true:
1799 // * S and T differe only in element type, in other words, S and T
1800 // have the same number of dimensions.
1801 // * Both Se and Te are reference types
1802 // * An explicit referenc conversions exist from Se to Te
1804 if (source_type
.IsArray
&& target_type
.IsArray
) {
1805 if (source_type
.GetArrayRank () == target_type
.GetArrayRank ()) {
1807 Type source_element_type
= TypeManager
.GetElementType (source_type
);
1808 Type target_element_type
= TypeManager
.GetElementType (target_type
);
1810 if (!source_element_type
.IsValueType
&& !target_element_type
.IsValueType
)
1811 if (ExplicitReferenceConversionExists (source_element_type
,
1812 target_element_type
))
1813 return new ClassCast (source
, target_type
);
1818 // From System.Array to any array-type
1819 if (source_type
== TypeManager
.array_type
&&
1820 target_type
.IsArray
) {
1821 return new ClassCast (source
, target_type
);
1825 // From System delegate to any delegate-type
1827 if (source_type
== TypeManager
.delegate_type
&&
1828 TypeManager
.IsDelegateType (target_type
))
1829 return new ClassCast (source
, target_type
);
1832 // From ICloneable to Array or Delegate types
1834 if (source_type
== TypeManager
.icloneable_type
&&
1835 (target_type
== TypeManager
.array_type
||
1836 target_type
== TypeManager
.delegate_type
))
1837 return new ClassCast (source
, target_type
);
1843 /// Performs an explicit conversion of the expression `expr' whose
1844 /// type is expr.Type to `target_type'.
1846 static public Expression
ExplicitConversionCore (EmitContext ec
, Expression expr
,
1847 Type target_type
, Location loc
)
1849 Type expr_type
= expr
.Type
;
1851 // Explicit conversion includes implicit conversion and it used for enum underlying types too
1852 Expression ne
= ImplicitConversionStandard (ec
, expr
, target_type
, loc
);
1857 // Unboxing conversions; only object types can be convertible to enum
1859 if (expr_type
== TypeManager
.object_type
&& target_type
.IsValueType
|| expr_type
== TypeManager
.enum_type
)
1860 return new UnboxCast (expr
, target_type
);
1862 if (TypeManager
.IsEnumType (expr_type
)) {
1863 if (expr
is EnumConstant
)
1864 return ExplicitConversionCore (ec
, ((EnumConstant
) expr
).Child
, target_type
, loc
);
1866 return ExplicitConversionCore (ec
, new EmptyCast (expr
, TypeManager
.EnumToUnderlying (expr_type
)), target_type
, loc
);
1869 if (TypeManager
.IsNullableType (expr_type
) && TypeManager
.IsNullableType (target_type
))
1870 return new Nullable
.LiftedConversion (
1871 expr
, target_type
, false, true, loc
).Resolve (ec
);
1873 if (TypeManager
.IsEnumType (target_type
)){
1874 Expression ce
= ExplicitConversionCore (ec
, expr
, TypeManager
.EnumToUnderlying (target_type
), loc
);
1876 return new EmptyCast (ce
, target_type
);
1879 ne
= ExplicitNumericConversion (expr
, target_type
);
1884 // Skip the ExplicitReferenceConversion because we can not convert
1885 // from Null to a ValueType, and ExplicitReference wont check against
1886 // null literal explicitly
1888 if (expr_type
!= TypeManager
.null_type
){
1889 ne
= ExplicitReferenceConversion (expr
, target_type
);
1895 ne
= ExplicitUnsafe (expr
, target_type
);
1900 ne
= ExplicitUserConversion (ec
, expr
, target_type
, loc
);
1907 public static Expression
ExplicitUnsafe (Expression expr
, Type target_type
)
1909 Type expr_type
= expr
.Type
;
1911 if (target_type
.IsPointer
){
1912 if (expr_type
.IsPointer
)
1913 return new EmptyCast (expr
, target_type
);
1915 if (expr_type
== TypeManager
.sbyte_type
||
1916 expr_type
== TypeManager
.short_type
||
1917 expr_type
== TypeManager
.int32_type
||
1918 expr_type
== TypeManager
.int64_type
)
1919 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I
);
1921 if (expr_type
== TypeManager
.ushort_type
||
1922 expr_type
== TypeManager
.uint32_type
||
1923 expr_type
== TypeManager
.uint64_type
||
1924 expr_type
== TypeManager
.byte_type
)
1925 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U
);
1928 if (expr_type
.IsPointer
){
1929 if (target_type
== TypeManager
.sbyte_type
)
1930 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I1
);
1931 else if (target_type
== TypeManager
.byte_type
)
1932 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U1
);
1933 else if (target_type
== TypeManager
.short_type
)
1934 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I2
);
1935 else if (target_type
== TypeManager
.ushort_type
)
1936 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U2
);
1937 else if (target_type
== TypeManager
.int32_type
)
1938 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I4
);
1939 else if (target_type
== TypeManager
.uint32_type
)
1940 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U4
);
1941 else if (target_type
== TypeManager
.uint64_type
)
1942 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U8
);
1943 else if (target_type
== TypeManager
.int64_type
){
1944 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I8
);
1951 /// Same as ExplicitConversion, only it doesn't include user defined conversions
1953 static public Expression
ExplicitConversionStandard (EmitContext ec
, Expression expr
,
1954 Type target_type
, Location l
)
1956 int errors
= Report
.Errors
;
1957 Expression ne
= ImplicitConversionStandard (ec
, expr
, target_type
, l
);
1958 if (Report
.Errors
> errors
)
1964 if (TypeManager
.IsNullableType (expr
.Type
) && TypeManager
.IsNullableType (target_type
))
1965 return new Nullable
.LiftedConversion (
1966 expr
, target_type
, false, true, l
).Resolve (ec
);
1968 ne
= ExplicitNumericConversion (expr
, target_type
);
1972 ne
= ExplicitReferenceConversion (expr
, target_type
);
1976 if (ec
.InUnsafe
&& expr
.Type
== TypeManager
.void_ptr_type
&& target_type
.IsPointer
)
1977 return new EmptyCast (expr
, target_type
);
1979 expr
.Error_ValueCannotBeConverted (l
, target_type
, true);
1984 /// Performs an explicit conversion of the expression `expr' whose
1985 /// type is expr.Type to `target_type'.
1987 static public Expression
ExplicitConversion (EmitContext ec
, Expression expr
,
1988 Type target_type
, Location loc
)
1990 Expression e
= ExplicitConversionCore (ec
, expr
, target_type
, loc
);
1994 expr
.Error_ValueCannotBeConverted (loc
, target_type
, true);