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 // This is used to prettify the code: a null argument is allowed
24 // for ImplicitStandardConversion as long as it is known that
25 // no anonymous method will play a role.
27 // FIXME: renamed from `const' to `static' to allow bootstraping from older
28 // versions of the compiler that could not cope with this construct.
30 public static EmitContext ConstantEC
= null;
32 static public void Error_CannotConvertType (Location loc
, Type source
, Type target
)
34 Report
.Error (30, loc
, "Cannot convert type '" +
35 TypeManager
.CSharpName (source
) + "' to '" +
36 TypeManager
.CSharpName (target
) + "'");
39 static Expression
TypeParameter_to_Null (Expression expr
, Type target_type
,
42 if (!TypeParameter_to_Null (target_type
)) {
43 Report
.Error (403, loc
, "Cannot convert null to the type " +
44 "parameter `{0}' becaues it could be a value " +
45 "type. Consider using `default ({0})' instead.",
50 return new NullCast (expr
, target_type
);
53 static bool TypeParameter_to_Null (Type target_type
)
55 GenericConstraints gc
= TypeManager
.GetTypeParameterConstraints (target_type
);
59 if (gc
.HasReferenceTypeConstraint
)
61 if (gc
.HasClassConstraint
&& !TypeManager
.IsValueType (gc
.ClassConstraint
))
67 static Type
TypeParam_EffectiveBaseType (EmitContext ec
, Type t
)
69 GenericConstraints gc
= TypeManager
.GetTypeParameterConstraints (t
);
71 return TypeManager
.object_type
;
73 return TypeParam_EffectiveBaseType (ec
, gc
);
76 static Type
TypeParam_EffectiveBaseType (EmitContext ec
, GenericConstraints gc
)
78 ArrayList list
= new ArrayList ();
79 list
.Add (gc
.EffectiveBaseClass
);
80 foreach (Type t
in gc
.InterfaceConstraints
) {
81 if (!t
.IsGenericParameter
)
84 GenericConstraints new_gc
= TypeManager
.GetTypeParameterConstraints (t
);
86 list
.Add (TypeParam_EffectiveBaseType (ec
, new_gc
));
88 return FindMostEncompassedType (ec
, list
);
91 static Expression
TypeParameterConversion (Expression expr
, bool is_reference
, Type target_type
)
94 return new EmptyCast (expr
, target_type
);
96 return new BoxedCast (expr
, target_type
);
99 static Expression
ImplicitTypeParameterConversion (EmitContext ec
, Expression expr
,
102 Type expr_type
= expr
.Type
;
104 GenericConstraints gc
= TypeManager
.GetTypeParameterConstraints (expr_type
);
107 if (target_type
== TypeManager
.object_type
)
108 return new BoxedCast (expr
);
113 // We're converting from a type parameter which is known to be a reference type.
114 bool is_reference
= gc
.IsReferenceType
;
115 Type base_type
= TypeParam_EffectiveBaseType (ec
, gc
);
117 if (TypeManager
.IsSubclassOf (base_type
, target_type
))
118 return TypeParameterConversion (expr
, is_reference
, target_type
);
120 if (target_type
.IsInterface
) {
121 if (TypeManager
.ImplementsInterface (base_type
, target_type
))
122 return TypeParameterConversion (expr
, is_reference
, target_type
);
124 foreach (Type t
in gc
.InterfaceConstraints
) {
125 if (TypeManager
.IsSubclassOf (t
, target_type
))
126 return TypeParameterConversion (expr
, is_reference
, target_type
);
130 foreach (Type t
in gc
.InterfaceConstraints
) {
131 if (!t
.IsGenericParameter
)
133 if (TypeManager
.IsSubclassOf (t
, target_type
))
134 return TypeParameterConversion (expr
, is_reference
, target_type
);
140 static EmptyExpression MyEmptyExpr
;
141 static public Expression
WideningReferenceConversion (EmitContext ec
, Expression expr
, Type target_type
)
143 Type expr_type
= expr
.Type
;
145 if (expr_type
== null && expr
.eclass
== ExprClass
.MethodGroup
){
146 // if we are a method group, emit a warning
151 if (expr_type
== TypeManager
.void_type
)
154 if (expr_type
.IsGenericParameter
)
155 return ImplicitTypeParameterConversion (ec
, expr
, target_type
);
158 // notice that it is possible to write "ValueType v = 1", the ValueType here
159 // is an abstract class, and not really a value type, so we apply the same rules.
161 if (target_type
== TypeManager
.object_type
) {
163 // A pointer type cannot be converted to object
165 if (expr_type
.IsPointer
)
168 if (TypeManager
.IsValueType (expr_type
))
169 return new BoxedCast (expr
);
170 if (expr_type
.IsClass
|| expr_type
.IsInterface
|| expr_type
== TypeManager
.enum_type
){
171 if (expr_type
== TypeManager
.anonymous_method_type
)
173 return new EmptyCast (expr
, target_type
);
177 } else if (target_type
== TypeManager
.value_type
) {
178 if (TypeManager
.IsValueType (expr_type
))
179 return new BoxedCast (expr
);
180 if (expr_type
== TypeManager
.null_type
)
181 return new NullCast (expr
, target_type
);
184 } else if (TypeManager
.IsSubclassOf (expr_type
, target_type
)) {
186 // Special case: enumeration to System.Enum.
187 // System.Enum is not a value type, it is a class, so we need
188 // a boxing conversion
190 if (expr_type
.IsEnum
|| expr_type
.IsGenericParameter
)
191 return new BoxedCast (expr
);
193 return new EmptyCast (expr
, target_type
);
196 // This code is kind of mirrored inside WideningStandardConversionExists
197 // with the small distinction that we only probe there
199 // Always ensure that the code here and there is in sync
201 // from the null type to any reference-type.
202 if (expr_type
== TypeManager
.null_type
){
203 if (target_type
.IsPointer
)
204 return new EmptyCast (expr
, target_type
);
206 if (!target_type
.IsValueType
)
207 return new NullCast (expr
, target_type
);
209 // VB.NET specific: Convert Nothing to value types
211 Expression e
= NothingToPrimitiveTypes (expr
, target_type
);
215 return new NullCast (expr
, target_type
);
218 // from any class-type S to any interface-type T.
219 if (target_type
.IsInterface
) {
220 if (target_type
!= TypeManager
.iconvertible_type
&&
221 expr_type
.IsValueType
&& (expr
is Constant
) &&
222 !(expr
is IntLiteral
|| expr
is BoolLiteral
||
223 expr
is FloatLiteral
|| expr
is DoubleLiteral
||
224 expr
is LongLiteral
|| expr
is CharLiteral
||
225 expr
is StringLiteral
|| expr
is DecimalLiteral
||
226 expr
is UIntLiteral
|| expr
is ULongLiteral
)) {
230 if (TypeManager
.ImplementsInterface (expr_type
, target_type
)){
231 if (expr_type
.IsGenericParameter
|| TypeManager
.IsValueType (expr_type
))
232 return new BoxedCast (expr
, target_type
);
234 return new EmptyCast (expr
, target_type
);
238 // from any interface type S to interface-type T.
239 if (expr_type
.IsInterface
&& target_type
.IsInterface
) {
240 if (TypeManager
.ImplementsInterface (expr_type
, target_type
))
241 return new EmptyCast (expr
, target_type
);
246 // from an array-type S to an array-type of type T
247 if (expr_type
.IsArray
&& target_type
.IsArray
) {
248 if (expr_type
.GetArrayRank () == target_type
.GetArrayRank ()) {
250 Type expr_element_type
= TypeManager
.GetElementType (expr_type
);
252 if (MyEmptyExpr
== null)
253 MyEmptyExpr
= new EmptyExpression ();
255 MyEmptyExpr
.SetType (expr_element_type
);
256 Type target_element_type
= TypeManager
.GetElementType (target_type
);
258 if (!expr_element_type
.IsValueType
&& !target_element_type
.IsValueType
)
259 if (WideningStandardConversionExists (ConstantEC
, MyEmptyExpr
,
260 target_element_type
))
261 return new EmptyCast (expr
, target_type
);
265 // from an array-type to System.Array
266 if (expr_type
.IsArray
&& target_type
== TypeManager
.array_type
)
267 return new EmptyCast (expr
, target_type
);
269 // from an array-type of type T to IEnumerable<T>
270 if (expr_type
.IsArray
&& TypeManager
.IsIEnumerable (expr_type
, target_type
))
271 return new EmptyCast (expr
, target_type
);
273 // from any delegate type to System.Delegate
274 if ((expr_type
== TypeManager
.delegate_type
|| TypeManager
.IsDelegateType (expr_type
)) &&
275 target_type
== TypeManager
.delegate_type
)
276 return new EmptyCast (expr
, target_type
);
278 // from any array-type or delegate type into System.ICloneable.
279 if (expr_type
.IsArray
||
280 expr_type
== TypeManager
.delegate_type
|| TypeManager
.IsDelegateType (expr_type
))
281 if (target_type
== TypeManager
.icloneable_type
)
282 return new EmptyCast (expr
, target_type
);
284 // from a generic type definition to a generic instance.
285 if (TypeManager
.IsEqual (expr_type
, target_type
))
286 return new EmptyCast (expr
, target_type
);
292 // Tests whether an implicit reference conversion exists between expr_type
295 public static bool WideningReferenceConversionExists (EmitContext ec
, Expression expr
, Type target_type
)
297 Type expr_type
= expr
.Type
;
299 if (expr_type
.IsGenericParameter
)
300 return ImplicitTypeParameterConversion (ec
, expr
, target_type
) != null;
303 // This is the boxed case.
305 if (target_type
== TypeManager
.object_type
) {
306 if (expr_type
.IsClass
|| TypeManager
.IsValueType (expr_type
) ||
307 expr_type
.IsInterface
|| expr_type
== TypeManager
.enum_type
)
308 if (target_type
!= TypeManager
.anonymous_method_type
)
312 } else if (TypeManager
.IsSubclassOf (expr_type
, target_type
))
315 // Please remember that all code below actually comes
316 // from WideningReferenceConversion so make sure code remains in sync
318 // from any class-type S to any interface-type T.
319 if (target_type
.IsInterface
) {
320 if (target_type
!= TypeManager
.iconvertible_type
&&
321 expr_type
.IsValueType
&& (expr
is Constant
) &&
322 !(expr
is IntLiteral
|| expr
is BoolLiteral
||
323 expr
is FloatLiteral
|| expr
is DoubleLiteral
||
324 expr
is LongLiteral
|| expr
is CharLiteral
||
325 expr
is StringLiteral
|| expr
is DecimalLiteral
||
326 expr
is UIntLiteral
|| expr
is ULongLiteral
)) {
330 if (TypeManager
.ImplementsInterface (expr_type
, target_type
))
334 // from any interface type S to interface-type T.
335 if (expr_type
.IsInterface
&& target_type
.IsInterface
)
336 if (TypeManager
.ImplementsInterface (expr_type
, target_type
))
339 // from an array-type S to an array-type of type T
340 if (expr_type
.IsArray
&& target_type
.IsArray
) {
341 if (expr_type
.GetArrayRank () == target_type
.GetArrayRank ()) {
343 Type expr_element_type
= expr_type
.GetElementType ();
345 if (MyEmptyExpr
== null)
346 MyEmptyExpr
= new EmptyExpression ();
348 MyEmptyExpr
.SetType (expr_element_type
);
349 Type target_element_type
= TypeManager
.GetElementType (target_type
);
351 if (!expr_element_type
.IsValueType
&& !target_element_type
.IsValueType
)
352 if (WideningStandardConversionExists (ConstantEC
, MyEmptyExpr
,
353 target_element_type
))
358 // from an array-type to System.Array
359 if (expr_type
.IsArray
&& (target_type
== TypeManager
.array_type
))
362 // from an array-type of type T to IEnumerable<T>
363 if (expr_type
.IsArray
&& TypeManager
.IsIEnumerable (expr_type
, target_type
))
366 // from any delegate type to System.Delegate
367 if ((expr_type
== TypeManager
.delegate_type
|| TypeManager
.IsDelegateType (expr_type
)) &&
368 target_type
== TypeManager
.delegate_type
)
369 if (target_type
.IsAssignableFrom (expr_type
))
372 // from any array-type or delegate type into System.ICloneable.
373 if (expr_type
.IsArray
||
374 expr_type
== TypeManager
.delegate_type
|| TypeManager
.IsDelegateType (expr_type
))
375 if (target_type
== TypeManager
.icloneable_type
)
378 // from the null type to any reference-type.
379 if (expr_type
== TypeManager
.null_type
){
380 if (target_type
.IsPointer
)
383 if (!target_type
.IsValueType
)
387 // from a generic type definition to a generic instance.
388 if (TypeManager
.IsEqual (expr_type
, target_type
))
395 /// Implicit Numeric Conversions.
397 /// expr is the expression to convert, returns a new expression of type
398 /// target_type or null if an implicit conversion is not possible.
400 static public Expression
WideningNumericConversion (EmitContext ec
, Expression expr
,
401 Type target_type
, Location loc
)
403 Type expr_type
= expr
.Type
;
406 // Attempt to do the implicit constant expression conversions
408 if (expr
is Constant
){
411 e
= WideningConstantConversions (target_type
, (Constant
) expr
);
415 if (expr
is IntConstant
){
416 e
= TryWideningIntConversion (target_type
, (IntConstant
) expr
);
423 Type real_target_type
= target_type
;
425 // VB.NET specific: Convert an enum to it's
426 // underlying numeric type or any type that
427 // it's underlyinmg type has widening
430 if (expr_type
.IsSubclassOf (TypeManager
.enum_type
)){
431 if (target_type
== TypeManager
.enum_type
||
432 target_type
== TypeManager
.object_type
) {
433 if (expr
is EnumConstant
)
434 expr
= ((EnumConstant
) expr
).Child
;
435 // We really need all these casts here .... :-(
436 expr
= new BoxedCast (new EmptyCast (expr
, expr_type
));
437 return new EmptyCast (expr
, target_type
);
441 // Notice that we have kept the expr_type unmodified, which is only
443 if (expr
is EnumConstant
)
444 expr
= ((EnumConstant
) expr
).Child
;
446 expr
= new EmptyCast (expr
, TypeManager
.EnumToUnderlying (expr_type
));
447 expr_type
= expr
.Type
;
449 if (expr_type
== target_type
)
453 if (expr_type
== TypeManager
.sbyte_type
){
455 // From sbyte to short, int, long, float, double.
457 if (real_target_type
== TypeManager
.int32_type
)
458 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I4
);
459 if (real_target_type
== TypeManager
.int64_type
)
460 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I8
);
461 if (real_target_type
== TypeManager
.double_type
)
462 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
463 if (real_target_type
== TypeManager
.float_type
)
464 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R4
);
465 if (real_target_type
== TypeManager
.short_type
)
466 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I2
);
467 } else if (expr_type
== TypeManager
.byte_type
){
469 // From byte to short, ushort, int, uint, long, ulong, float, double
471 if ((real_target_type
== TypeManager
.short_type
) ||
472 (real_target_type
== TypeManager
.ushort_type
) ||
473 (real_target_type
== TypeManager
.int32_type
) ||
474 (real_target_type
== TypeManager
.uint32_type
))
475 return new EmptyCast (expr
, target_type
);
477 if (real_target_type
== TypeManager
.uint64_type
)
478 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U8
);
479 if (real_target_type
== TypeManager
.int64_type
)
480 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I8
);
481 if (real_target_type
== TypeManager
.float_type
)
482 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R4
);
483 if (real_target_type
== TypeManager
.double_type
)
484 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
485 if (real_target_type
== TypeManager
.decimal_type
)
486 return new ImplicitNew (ec
, "System", "Decimal", loc
, expr
);
487 } else if (expr_type
== TypeManager
.short_type
){
489 // From short to int, long, float, double
491 if (real_target_type
== TypeManager
.int32_type
)
492 return new EmptyCast (expr
, target_type
);
493 if (real_target_type
== TypeManager
.int64_type
)
494 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I8
);
495 if (real_target_type
== TypeManager
.double_type
)
496 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
497 if (real_target_type
== TypeManager
.float_type
)
498 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R4
);
499 if (real_target_type
== TypeManager
.decimal_type
)
500 return new ImplicitNew (ec
, "System", "Decimal", loc
, expr
);
501 } else if (expr_type
== TypeManager
.ushort_type
){
503 // From ushort to int, uint, long, ulong, float, double
505 if (real_target_type
== TypeManager
.uint32_type
)
506 return new EmptyCast (expr
, target_type
);
508 if (real_target_type
== TypeManager
.uint64_type
)
509 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U8
);
510 if (real_target_type
== TypeManager
.int32_type
)
511 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I4
);
512 if (real_target_type
== TypeManager
.int64_type
)
513 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I8
);
514 if (real_target_type
== TypeManager
.double_type
)
515 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
516 if (real_target_type
== TypeManager
.float_type
)
517 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R4
);
518 } else if (expr_type
== TypeManager
.int32_type
){
520 // From int to long, float, double
522 if (real_target_type
== TypeManager
.int64_type
)
523 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I8
);
524 if (real_target_type
== TypeManager
.double_type
)
525 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
526 if (real_target_type
== TypeManager
.float_type
)
527 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R4
);
528 if (real_target_type
== TypeManager
.decimal_type
)
529 return new ImplicitNew (ec
, "System", "Decimal", loc
, expr
);
530 } else if (expr_type
== TypeManager
.uint32_type
){
532 // From uint to long, ulong, float, double
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 } else if (expr_type
== TypeManager
.uint64_type
){
546 // From ulong to float, double
548 if (real_target_type
== TypeManager
.double_type
)
549 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R_Un
,
551 if (real_target_type
== TypeManager
.float_type
)
552 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R_Un
,
554 } else if (expr_type
== TypeManager
.int64_type
){
556 // From long/ulong to float, double
558 if (real_target_type
== TypeManager
.double_type
)
559 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
560 if (real_target_type
== TypeManager
.float_type
)
561 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R4
);
562 if (real_target_type
== TypeManager
.decimal_type
)
563 return new ImplicitNew (ec
, "System", "Decimal", loc
, expr
);
564 } else if (expr_type
== TypeManager
.float_type
){
568 if (real_target_type
== TypeManager
.double_type
)
569 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_R8
);
570 } else if (expr_type
== TypeManager
.decimal_type
){
572 // From decimal to float, double
574 if (real_target_type
== TypeManager
.double_type
)
575 return new HelperMethodInvocation (ec
, loc
, TypeManager
.double_type
, TypeManager
.convert_to_double_decimal
, expr
);
576 if (real_target_type
== TypeManager
.float_type
)
577 return new HelperMethodInvocation (ec
, loc
, TypeManager
.float_type
, TypeManager
.convert_to_single_decimal
, expr
);
585 /// Same as WideningStandardConversionExists except that it also looks at
586 /// implicit user defined conversions - needed for overload resolution
588 public static bool WideningConversionExists (EmitContext ec
, Expression expr
, Type target_type
)
590 if (expr
is NullLiteral
) {
591 if (target_type
.IsGenericParameter
)
592 return TypeParameter_to_Null (target_type
);
594 if (TypeManager
.IsNullableType (target_type
))
598 if (WideningStandardConversionExists (ec
, expr
, target_type
))
602 // VB.NET has no notion of User defined conversions
605 // Expression dummy = ImplicitUserConversion (ec, expr, target_type, Location.Null);
607 // if (dummy != null)
614 // VB.NET has no notion of User defined conversions
617 // public static bool ImplicitUserConversionExists (EmitContext ec, Type source, Type target)
619 // Expression dummy = ImplicitUserConversion (
620 // ec, new EmptyExpression (source), target, Location.Null);
621 // return dummy != null;
625 /// Determines if a standard implicit conversion exists from
626 /// expr_type to target_type
628 /// ec should point to a real EmitContext if expr.Type is TypeManager.anonymous_method_type.
630 public static bool WideningStandardConversionExists (EmitContext ec
, Expression expr
, Type target_type
)
632 Type expr_type
= expr
.Type
;
634 if (expr_type
== TypeManager
.void_type
)
637 //Console.WriteLine ("Expr is {0}", expr);
638 //Console.WriteLine ("{0} -> {1} ?", expr_type, target_type);
639 if (expr_type
.Equals (target_type
))
643 // First numeric conversions
645 if (expr_type
== TypeManager
.sbyte_type
){
647 // From sbyte to short, int, long, float, double.
649 if ((target_type
== TypeManager
.int32_type
) ||
650 (target_type
== TypeManager
.int64_type
) ||
651 (target_type
== TypeManager
.double_type
) ||
652 (target_type
== TypeManager
.float_type
) ||
653 (target_type
== TypeManager
.short_type
) ||
654 (target_type
== TypeManager
.decimal_type
))
657 } else if (expr_type
== TypeManager
.byte_type
){
659 // From byte to short, ushort, int, uint, long, ulong, float, double
661 if ((target_type
== TypeManager
.short_type
) ||
662 (target_type
== TypeManager
.ushort_type
) ||
663 (target_type
== TypeManager
.int32_type
) ||
664 (target_type
== TypeManager
.uint32_type
) ||
665 (target_type
== TypeManager
.uint64_type
) ||
666 (target_type
== TypeManager
.int64_type
) ||
667 (target_type
== TypeManager
.float_type
) ||
668 (target_type
== TypeManager
.double_type
) ||
669 (target_type
== TypeManager
.decimal_type
))
672 } else if (expr_type
== TypeManager
.short_type
){
674 // From short to int, long, float, double
676 if ((target_type
== TypeManager
.int32_type
) ||
677 (target_type
== TypeManager
.int64_type
) ||
678 (target_type
== TypeManager
.double_type
) ||
679 (target_type
== TypeManager
.float_type
) ||
680 (target_type
== TypeManager
.decimal_type
))
683 } else if (expr_type
== TypeManager
.ushort_type
){
685 // From ushort to int, uint, long, ulong, float, double
687 if ((target_type
== TypeManager
.uint32_type
) ||
688 (target_type
== TypeManager
.uint64_type
) ||
689 (target_type
== TypeManager
.int32_type
) ||
690 (target_type
== TypeManager
.int64_type
) ||
691 (target_type
== TypeManager
.double_type
) ||
692 (target_type
== TypeManager
.float_type
) ||
693 (target_type
== TypeManager
.decimal_type
))
696 } else if (expr_type
== TypeManager
.int32_type
){
698 // From int to long, float, double
700 if ((target_type
== TypeManager
.int64_type
) ||
701 (target_type
== TypeManager
.double_type
) ||
702 (target_type
== TypeManager
.float_type
) ||
703 (target_type
== TypeManager
.decimal_type
))
706 } else if (expr_type
== TypeManager
.uint32_type
){
708 // From uint to long, ulong, float, double
710 if ((target_type
== TypeManager
.int64_type
) ||
711 (target_type
== TypeManager
.uint64_type
) ||
712 (target_type
== TypeManager
.double_type
) ||
713 (target_type
== TypeManager
.float_type
) ||
714 (target_type
== TypeManager
.decimal_type
))
717 } else if ((expr_type
== TypeManager
.uint64_type
) ||
718 (expr_type
== TypeManager
.int64_type
)) {
720 // From long/ulong to float, double
722 if ((target_type
== TypeManager
.double_type
) ||
723 (target_type
== TypeManager
.float_type
) ||
724 (target_type
== TypeManager
.decimal_type
))
727 } else if (expr_type
== TypeManager
.char_type
){
729 // From char to ushort, int, uint, long, ulong, float, double
731 if ((target_type
== TypeManager
.ushort_type
) ||
732 (target_type
== TypeManager
.int32_type
) ||
733 (target_type
== TypeManager
.uint32_type
) ||
734 (target_type
== TypeManager
.uint64_type
) ||
735 (target_type
== TypeManager
.int64_type
) ||
736 (target_type
== TypeManager
.float_type
) ||
737 (target_type
== TypeManager
.double_type
) ||
738 (target_type
== TypeManager
.decimal_type
))
741 } else if (expr_type
== TypeManager
.float_type
){
745 if (target_type
== TypeManager
.double_type
)
749 if (expr
.eclass
== ExprClass
.MethodGroup
){
750 if (TypeManager
.IsDelegateType (target_type
) && RootContext
.Version
!= LanguageVersion
.ISO_1
){
751 MethodGroupExpr mg
= expr
as MethodGroupExpr
;
754 // This should not happen frequently, so we can create an object
755 // to test compatibility
757 Expression c
= ImplicitDelegateCreation
.Create (ec
, mg
, target_type
, Location
.Null
);
763 if (WideningReferenceConversionExists (ec
, expr
, target_type
))
767 // Implicit Constant Expression Conversions
769 if (expr
is IntConstant
){
770 int value = ((IntConstant
) expr
).Value
;
772 if (target_type
== TypeManager
.sbyte_type
){
773 if (value >= SByte
.MinValue
&& value <= SByte
.MaxValue
)
775 } else if (target_type
== TypeManager
.byte_type
){
776 if (Byte
.MinValue
>= 0 && value <= Byte
.MaxValue
)
778 } else if (target_type
== TypeManager
.short_type
){
779 if (value >= Int16
.MinValue
&& value <= Int16
.MaxValue
)
781 } else if (target_type
== TypeManager
.ushort_type
){
782 if (value >= UInt16
.MinValue
&& value <= UInt16
.MaxValue
)
784 } else if (target_type
== TypeManager
.uint32_type
){
787 } else if (target_type
== TypeManager
.uint64_type
){
789 // we can optimize this case: a positive int32
790 // always fits on a uint64. But we need an opcode
797 if (value == 0 && expr
is IntLiteral
&& TypeManager
.IsEnumType (target_type
))
801 if (expr
is LongConstant
&& target_type
== TypeManager
.uint64_type
){
803 // Try the implicit constant expression conversion
804 // from long to ulong, instead of a nice routine,
807 long v
= ((LongConstant
) expr
).Value
;
812 if ((target_type
== TypeManager
.enum_type
||
813 target_type
.IsSubclassOf (TypeManager
.enum_type
)) &&
815 IntLiteral i
= (IntLiteral
) expr
;
822 // If `expr_type' implements `target_type' (which is an iface)
823 // see TryWideningIntConversion
825 if (target_type
.IsInterface
&& target_type
.IsAssignableFrom (expr_type
))
828 if (target_type
== TypeManager
.void_ptr_type
&& expr_type
.IsPointer
)
831 if (TypeManager
.IsNullableType (expr_type
) && TypeManager
.IsNullableType (target_type
))
834 if (expr_type
== TypeManager
.anonymous_method_type
){
835 if (!TypeManager
.IsDelegateType (target_type
))
838 AnonymousMethod am
= (AnonymousMethod
) expr
;
840 Expression conv
= am
.Compatible (ec
, target_type
, true);
849 // Used internally by FindMostEncompassedType, this is used
850 // to avoid creating lots of objects in the tight loop inside
851 // FindMostEncompassedType
853 static EmptyExpression priv_fmet_param
;
856 /// Finds "most encompassed type" according to the spec (13.4.2)
857 /// amongst the methods in the MethodGroupExpr
859 static Type
FindMostEncompassedType (EmitContext ec
, ArrayList types
)
863 if (priv_fmet_param
== null)
864 priv_fmet_param
= new EmptyExpression ();
866 foreach (Type t
in types
){
867 priv_fmet_param
.SetType (t
);
874 if (WideningStandardConversionExists (ec
, priv_fmet_param
, best
))
882 // Used internally by FindMostEncompassingType, this is used
883 // to avoid creating lots of objects in the tight loop inside
884 // FindMostEncompassingType
886 static EmptyExpression priv_fmee_ret
;
889 /// Finds "most encompassing type" according to the spec (13.4.2)
890 /// amongst the types in the given set
892 static Type
FindMostEncompassingType (EmitContext ec
, ArrayList types
)
896 if (priv_fmee_ret
== null)
897 priv_fmee_ret
= new EmptyExpression ();
899 foreach (Type t
in types
){
900 priv_fmee_ret
.SetType (best
);
907 if (WideningStandardConversionExists (ec
, priv_fmee_ret
, t
))
915 // Used to avoid creating too many objects
917 static EmptyExpression priv_fms_expr
;
920 /// Finds the most specific source Sx according to the rules of the spec (13.4.4)
921 /// by making use of FindMostEncomp* methods. Applies the correct rules separately
922 /// for explicit and implicit conversion operators.
924 static public Type
FindMostSpecificSource (EmitContext ec
, MethodGroupExpr me
,
925 Expression source
, bool apply_explicit_conv_rules
,
928 ArrayList src_types_set
= new ArrayList ();
930 if (priv_fms_expr
== null)
931 priv_fms_expr
= new EmptyExpression ();
934 // If any operator converts from S then Sx = S
936 Type source_type
= source
.Type
;
937 foreach (MethodBase mb
in me
.Methods
){
938 ParameterData pd
= Invocation
.GetParameterData (mb
);
939 Type param_type
= pd
.ParameterType (0);
941 if (param_type
== source_type
)
944 if (apply_explicit_conv_rules
) {
947 // Find the set of applicable user-defined conversion operators, U. This set
949 // user-defined implicit or explicit conversion operators declared by
950 // the classes or structs in D that convert from a type encompassing
951 // or encompassed by S to a type encompassing or encompassed by T
953 priv_fms_expr
.SetType (param_type
);
954 if (WideningStandardConversionExists (ec
, priv_fms_expr
, source_type
))
955 src_types_set
.Add (param_type
);
957 if (WideningStandardConversionExists (ec
, source
, param_type
))
958 src_types_set
.Add (param_type
);
962 // Only if S is encompassed by param_type
964 if (WideningStandardConversionExists (ec
, source
, param_type
))
965 src_types_set
.Add (param_type
);
970 // Explicit Conv rules
972 if (apply_explicit_conv_rules
) {
973 ArrayList candidate_set
= new ArrayList ();
975 foreach (Type param_type
in src_types_set
){
976 if (WideningStandardConversionExists (ec
, source
, param_type
))
977 candidate_set
.Add (param_type
);
980 if (candidate_set
.Count
!= 0)
981 return FindMostEncompassedType (ec
, candidate_set
);
987 if (apply_explicit_conv_rules
)
988 return FindMostEncompassingType (ec
, src_types_set
);
990 return FindMostEncompassedType (ec
, src_types_set
);
994 // Useful in avoiding proliferation of objects
996 static EmptyExpression priv_fmt_expr
;
999 /// Finds the most specific target Tx according to section 13.4.4
1001 static public Type
FindMostSpecificTarget (EmitContext ec
, MethodGroupExpr me
,
1002 Type target
, bool apply_explicit_conv_rules
,
1005 ArrayList tgt_types_set
= new ArrayList ();
1007 if (priv_fmt_expr
== null)
1008 priv_fmt_expr
= new EmptyExpression ();
1011 // If any operator converts to T then Tx = T
1013 foreach (MethodInfo mi
in me
.Methods
){
1014 Type ret_type
= mi
.ReturnType
;
1016 if (ret_type
== target
)
1019 if (apply_explicit_conv_rules
) {
1022 // Find the set of applicable user-defined conversion operators, U.
1024 // This set consists of the
1025 // user-defined implicit or explicit conversion operators declared by
1026 // the classes or structs in D that convert from a type encompassing
1027 // or encompassed by S to a type encompassing or encompassed by T
1029 priv_fms_expr
.SetType (ret_type
);
1030 if (WideningStandardConversionExists (ec
, priv_fms_expr
, target
))
1031 tgt_types_set
.Add (ret_type
);
1033 priv_fms_expr
.SetType (target
);
1034 if (WideningStandardConversionExists (ec
, priv_fms_expr
, ret_type
))
1035 tgt_types_set
.Add (ret_type
);
1039 // Only if T is encompassed by param_type
1041 priv_fms_expr
.SetType (ret_type
);
1042 if (WideningStandardConversionExists (ec
, priv_fms_expr
, target
))
1043 tgt_types_set
.Add (ret_type
);
1048 // Explicit conv rules
1050 if (apply_explicit_conv_rules
) {
1051 ArrayList candidate_set
= new ArrayList ();
1053 foreach (Type ret_type
in tgt_types_set
){
1054 priv_fmt_expr
.SetType (ret_type
);
1056 if (WideningStandardConversionExists (ec
, priv_fmt_expr
, target
))
1057 candidate_set
.Add (ret_type
);
1060 if (candidate_set
.Count
!= 0)
1061 return FindMostEncompassingType (ec
, candidate_set
);
1065 // Okay, final case !
1067 if (apply_explicit_conv_rules
)
1068 return FindMostEncompassedType (ec
, tgt_types_set
);
1070 return FindMostEncompassingType (ec
, tgt_types_set
);
1074 /// User-defined Implicit conversions
1078 // VB.NET has no notion of User defined conversions
1081 // static public Expression ImplicitUserConversion (EmitContext ec, Expression source,
1082 // Type target, Location loc)
1084 // return UserDefinedConversion (ec, source, target, loc, false);
1088 /// User-defined Explicit conversions
1092 // VB.NET has no notion of User defined conversions
1095 // static public Expression ExplicitUserConversion (EmitContext ec, Expression source,
1096 // Type target, Location loc)
1098 // return UserDefinedConversion (ec, source, target, loc, true);
1101 static DoubleHash explicit_conv
= new DoubleHash (100);
1102 static DoubleHash implicit_conv
= new DoubleHash (100);
1104 /// Computes the MethodGroup for the user-defined conversion
1105 /// operators from source_type to target_type. `look_for_explicit'
1106 /// controls whether we should also include the list of explicit
1109 static MethodGroupExpr
GetConversionOperators (EmitContext ec
,
1110 Type source_type
, Type target_type
,
1111 Location loc
, bool look_for_explicit
)
1113 Expression mg1
= null, mg2
= null;
1114 Expression mg5
= null, mg6
= null, mg7
= null, mg8
= null;
1117 op_name
= "op_Implicit";
1119 MethodGroupExpr union3
;
1121 if ((look_for_explicit
? explicit_conv
: implicit_conv
).Lookup (source_type
, target_type
, out r
))
1122 return (MethodGroupExpr
) r
;
1124 mg1
= Expression
.MethodLookup (ec
, source_type
, op_name
, loc
);
1125 if (source_type
.BaseType
!= null)
1126 mg2
= Expression
.MethodLookup (ec
, source_type
.BaseType
, op_name
, loc
);
1129 union3
= (MethodGroupExpr
) mg2
;
1130 else if (mg2
== null)
1131 union3
= (MethodGroupExpr
) mg1
;
1133 union3
= Invocation
.MakeUnionSet (mg1
, mg2
, loc
);
1135 mg1
= Expression
.MethodLookup (ec
, target_type
, op_name
, loc
);
1138 union3
= Invocation
.MakeUnionSet (union3
, mg1
, loc
);
1140 union3
= (MethodGroupExpr
) mg1
;
1143 if (target_type
.BaseType
!= null)
1144 mg1
= Expression
.MethodLookup (ec
, target_type
.BaseType
, op_name
, loc
);
1148 union3
= Invocation
.MakeUnionSet (union3
, mg1
, loc
);
1150 union3
= (MethodGroupExpr
) mg1
;
1153 MethodGroupExpr union4
= null;
1155 if (look_for_explicit
) {
1156 op_name
= "op_Explicit";
1158 mg5
= Expression
.MemberLookup (ec
, source_type
, op_name
, loc
);
1159 if (source_type
.BaseType
!= null)
1160 mg6
= Expression
.MethodLookup (ec
, source_type
.BaseType
, op_name
, loc
);
1162 mg7
= Expression
.MemberLookup (ec
, target_type
, op_name
, loc
);
1163 if (target_type
.BaseType
!= null)
1164 mg8
= Expression
.MethodLookup (ec
, target_type
.BaseType
, op_name
, loc
);
1166 MethodGroupExpr union5
= Invocation
.MakeUnionSet (mg5
, mg6
, loc
);
1167 MethodGroupExpr union6
= Invocation
.MakeUnionSet (mg7
, mg8
, loc
);
1169 union4
= Invocation
.MakeUnionSet (union5
, union6
, loc
);
1172 MethodGroupExpr ret
= Invocation
.MakeUnionSet (union3
, union4
, loc
);
1173 (look_for_explicit
? explicit_conv
: implicit_conv
).Insert (source_type
, target_type
, ret
);
1178 /// User-defined conversions
1182 // VB.NET has no notion of User defined conversions. This method is not used.
1184 static public Expression
UserDefinedConversion (EmitContext ec
, Expression source
,
1185 Type target
, Location loc
,
1186 bool look_for_explicit
)
1188 MethodGroupExpr union
;
1189 Type source_type
= source
.Type
;
1190 MethodBase method
= null;
1192 if (TypeManager
.IsNullableType (source_type
) && TypeManager
.IsNullableType (target
))
1193 return new Nullable
.LiftedConversion (
1194 source
, target
, true, look_for_explicit
, loc
).Resolve (ec
);
1196 union
= GetConversionOperators (ec
, source_type
, target
, loc
, look_for_explicit
);
1200 Type most_specific_source
, most_specific_target
;
1202 most_specific_source
= FindMostSpecificSource (ec
, union
, source
, look_for_explicit
, loc
);
1203 if (most_specific_source
== null)
1206 most_specific_target
= FindMostSpecificTarget (ec
, union
, target
, look_for_explicit
, loc
);
1207 if (most_specific_target
== null)
1213 foreach (MethodBase mb
in union
.Methods
){
1214 ParameterData pd
= Invocation
.GetParameterData (mb
);
1215 MethodInfo mi
= (MethodInfo
) mb
;
1217 if (pd
.ParameterType (0) == most_specific_source
&&
1218 mi
.ReturnType
== most_specific_target
) {
1224 if (method
== null || count
> 1)
1229 // This will do the conversion to the best match that we
1230 // found. Now we need to perform an implict standard conversion
1231 // if the best match was not the type that we were requested
1234 if (look_for_explicit
)
1235 source
= WideningAndNarrowingConversionStandard (ec
, source
, most_specific_source
, loc
);
1237 source
= WideningConversionStandard (ec
, source
, most_specific_source
, loc
);
1243 e
= new UserCast ((MethodInfo
) method
, source
, loc
);
1244 if (e
.Type
!= target
){
1245 if (!look_for_explicit
)
1246 e
= WideningConversionStandard (ec
, e
, target
, loc
);
1248 e
= WideningAndNarrowingConversionStandard (ec
, e
, target
, loc
);
1255 /// Converts implicitly the resolved expression `expr' into the
1256 /// `target_type'. It returns a new expression that can be used
1257 /// in a context that expects a `target_type'.
1259 static public Expression
WideningConversion (EmitContext ec
, Expression expr
,
1260 Type target_type
, Location loc
)
1264 if (target_type
== null)
1265 throw new Exception ("Target type is null");
1267 e
= WideningConversionStandard (ec
, expr
, target_type
, loc
);
1272 // VB.NET has no notion of User defined conversions
1275 // e = ImplicitUserConversion (ec, expr, target_type, loc);
1284 /// Attempts to apply the `Standard Implicit
1285 /// Conversion' rules to the expression `expr' into
1286 /// the `target_type'. It returns a new expression
1287 /// that can be used in a context that expects a
1290 /// This is different from `WideningConversion' in that the
1291 /// user defined implicit conversions are excluded.
1293 static public Expression
WideningConversionStandard (EmitContext ec
, Expression expr
,
1294 Type target_type
, Location loc
)
1296 Type expr_type
= expr
.Type
;
1299 if (expr
is NullLiteral
) {
1300 if (target_type
.IsGenericParameter
)
1301 return TypeParameter_to_Null (expr
, target_type
, loc
);
1303 if (TypeManager
.IsNullableType (target_type
))
1304 return new Nullable
.NullableLiteral (target_type
, loc
);
1307 if (TypeManager
.IsNullableType (expr_type
) && TypeManager
.IsNullableType (target_type
))
1308 return new Nullable
.LiftedConversion (
1309 expr
, target_type
, false, false, loc
).Resolve (ec
);
1311 if (expr
.eclass
== ExprClass
.MethodGroup
){
1312 if (!TypeManager
.IsDelegateType (target_type
)){
1317 // Only allow anonymous method conversions on post ISO_1
1319 if (RootContext
.Version
!= LanguageVersion
.ISO_1
){
1320 MethodGroupExpr mg
= expr
as MethodGroupExpr
;
1322 return ImplicitDelegateCreation
.Create (ec
, mg
, target_type
, loc
);
1326 if (expr_type
.Equals (target_type
) && !TypeManager
.IsNullType (expr_type
))
1329 e
= WideningNumericConversion (ec
, expr
, target_type
, loc
);
1333 e
= WideningReferenceConversion (ec
, expr
, target_type
);
1337 if ((target_type
== TypeManager
.enum_type
||
1338 target_type
.IsSubclassOf (TypeManager
.enum_type
)) &&
1339 expr
is IntLiteral
){
1340 IntLiteral i
= (IntLiteral
) expr
;
1343 return new EnumConstant ((Constant
) expr
, target_type
);
1347 if (expr_type
.IsPointer
){
1348 if (target_type
== TypeManager
.void_ptr_type
)
1349 return new EmptyCast (expr
, target_type
);
1352 // yep, comparing pointer types cant be done with
1353 // t1 == t2, we have to compare their element types.
1355 if (target_type
.IsPointer
){
1356 if (TypeManager
.GetElementType(target_type
) == TypeManager
.GetElementType(expr_type
))
1361 if (target_type
.IsPointer
) {
1362 if (expr_type
== TypeManager
.null_type
)
1363 return new EmptyCast (expr
, target_type
);
1365 if (expr_type
== TypeManager
.void_ptr_type
)
1366 return new EmptyCast (expr
, target_type
);
1370 if (expr_type
== TypeManager
.anonymous_method_type
){
1371 if (!TypeManager
.IsDelegateType (target_type
)){
1372 Report
.Error (1660, loc
,
1373 "Cannot convert anonymous method to `{0}', since it is not a delegate",
1374 TypeManager
.CSharpName (target_type
));
1378 AnonymousMethod am
= (AnonymousMethod
) expr
;
1379 int errors
= Report
.Errors
;
1381 Expression conv
= am
.Compatible (ec
, target_type
, false);
1386 // We return something instead of null, to avoid
1387 // the duplicate error, since am.Compatible would have
1388 // reported that already
1390 if (errors
!= Report
.Errors
)
1391 return new EmptyCast (expr
, target_type
);
1395 // VB.NET specific conversions
1398 e
= WideningStringConversions (ec
, expr
, target_type
, loc
);
1407 /// Attempts to perform an implicit constant conversion of the IntConstant
1408 /// into a different data type using casts (See Implicit Constant
1409 /// Expression Conversions)
1411 static public Expression
TryWideningIntConversion (Type target_type
, IntConstant ic
)
1413 int value = ic
.Value
;
1415 if (value == 0 && ic
is IntLiteral
&& TypeManager
.IsEnumType (target_type
)){
1416 Type underlying
= TypeManager
.EnumToUnderlying (target_type
);
1417 Constant e
= (Constant
) ic
;
1420 // Possibly, we need to create a different 0 literal before passing
1423 if (underlying
== TypeManager
.int64_type
)
1424 e
= new LongLiteral (0);
1425 else if (underlying
== TypeManager
.uint64_type
)
1426 e
= new ULongLiteral (0);
1428 return new EnumConstant (e
, target_type
);
1432 // If `target_type' is an interface and the type of `ic' implements the interface
1433 // e.g. target_type is IComparable, IConvertible, IFormattable
1435 if (target_type
.IsInterface
&& target_type
.IsAssignableFrom (ic
.Type
))
1436 return new BoxedCast (ic
);
1442 /// Attempts to perform an implicit constant conversion of the IntConstant
1443 /// into a different data type using casts (See Implicit Constant
1444 /// Expression Conversions)
1446 static public Expression
WideningConstantConversions (Type target_type
, Constant const_expr
)
1450 Type const_expr_type
= const_expr
.Type
;
1451 Location loc
= const_expr
.Location
;
1453 if (target_type
== TypeManager
.byte_type
){
1454 if (const_expr_type
== TypeManager
.short_type
||
1455 const_expr_type
== TypeManager
.int32_type
||
1456 const_expr_type
== TypeManager
.int64_type
)
1457 return const_expr
.ToByte (loc
);
1460 if (target_type
== TypeManager
.short_type
){
1461 if (const_expr_type
== TypeManager
.int32_type
||
1462 const_expr_type
== TypeManager
.int64_type
)
1463 return const_expr
.ToShort (loc
);
1466 if (target_type
== TypeManager
.int32_type
){
1467 if (const_expr_type
== TypeManager
.int64_type
)
1468 return const_expr
.ToInt (loc
);
1471 if (target_type
== TypeManager
.float_type
) {
1472 if (const_expr_type
== TypeManager
.double_type
)
1473 return const_expr
.ToDouble (loc
);
1479 static public Constant
NothingToPrimitiveTypes (Expression expr
, Type target_type
)
1481 NullLiteral null_literal
= (NullLiteral
) expr
;
1482 Location loc
= null_literal
.Location
;
1483 Type real_target_type
= target_type
;
1484 Constant retval
= null;
1486 if (null_literal
== null)
1487 throw new Exception ("FIXME: I was expecting that I would always get only NullLiterals");
1489 if (target_type
.IsSubclassOf(TypeManager
.enum_type
))
1490 real_target_type
= TypeManager
.EnumToUnderlying (target_type
);
1492 if (real_target_type
== TypeManager
.bool_type
)
1493 retval
= null_literal
.ToBoolean (loc
);
1494 else if (real_target_type
== TypeManager
.byte_type
)
1495 retval
= null_literal
.ToByte (loc
);
1496 else if (real_target_type
== TypeManager
.short_type
)
1497 retval
= null_literal
.ToShort (loc
);
1498 else if (real_target_type
== TypeManager
.int32_type
)
1499 retval
= null_literal
.ToInt (loc
);
1500 else if (real_target_type
== TypeManager
.int64_type
)
1501 retval
= null_literal
.ToLong (loc
);
1502 else if (real_target_type
== TypeManager
.decimal_type
)
1503 retval
= null_literal
.ToDecimal (loc
);
1504 else if (real_target_type
== TypeManager
.float_type
)
1505 retval
= null_literal
.ToLong (loc
);
1506 else if (real_target_type
== TypeManager
.double_type
)
1507 retval
= null_literal
.ToDouble (loc
);
1508 else if (real_target_type
== TypeManager
.char_type
)
1509 retval
= null_literal
.ToChar (loc
);
1510 else if (real_target_type
== TypeManager
.string_type
)
1511 retval
= new StringConstant (null);
1513 if (real_target_type
!= target_type
&& retval
!= null)
1514 retval
= new EnumConstant (retval
, target_type
);
1519 static public void Error_CannotWideningConversion (Location loc
, Type source
, Type target
)
1521 if (source
.Name
== target
.Name
){
1522 Report
.ExtraInformation (loc
,
1524 "The type {0} has two conflicting definitons, one comes from {0} and the other from {1}",
1525 source
.Assembly
.FullName
, target
.Assembly
.FullName
));
1528 Report
.Error (29, loc
, "Cannot convert implicitly from {0} to `{1}'",
1529 source
== TypeManager
.anonymous_method_type
?
1530 "anonymous method" : "`" + TypeManager
.CSharpName (source
) + "'",
1531 TypeManager
.CSharpName (target
));
1535 /// Attempts to implicitly convert `source' into `target_type', using
1536 /// WideningConversion. If there is no implicit conversion, then
1537 /// an error is signaled
1539 static public Expression
WideningConversionRequired (EmitContext ec
, Expression source
,
1540 Type target_type
, Location loc
)
1544 int errors
= Report
.Errors
;
1545 e
= WideningConversion (ec
, source
, target_type
, loc
);
1546 if (Report
.Errors
> errors
)
1551 if (source
is DoubleLiteral
) {
1552 if (target_type
== TypeManager
.float_type
) {
1553 Error_664 (loc
, "float", "f");
1556 if (target_type
== TypeManager
.decimal_type
) {
1557 Error_664 (loc
, "decimal", "m");
1562 if (source
is Constant
){
1563 Constant c
= (Constant
) source
;
1565 Expression
.Error_ConstantValueCannotBeConverted (loc
, c
.AsString (), target_type
);
1569 Error_CannotWideningConversion (loc
, source
.Type
, target_type
);
1574 static void Error_664 (Location loc
, string type
, string suffix
) {
1575 Report
.Error (664, loc
,
1576 "Literal of type double cannot be implicitly converted to type '{0}'. Add suffix '{1}' to create a literal of this type",
1581 /// Performs the explicit numeric conversions
1585 /// Performs the explicit numeric conversions
1587 static Expression
NarrowingNumericConversion (EmitContext ec
, Expression expr
, Type target_type
, Location loc
)
1589 Type expr_type
= expr
.Type
;
1592 // If we have an enumeration, extract the underlying type,
1593 // use this during the comparison, but wrap around the original
1596 Type real_target_type
= target_type
;
1598 if (TypeManager
.IsEnumType (real_target_type
))
1599 real_target_type
= TypeManager
.EnumToUnderlying (real_target_type
);
1601 if (WideningStandardConversionExists (ec
, expr
, real_target_type
)){
1602 Expression ce
= WideningConversionStandard (ec
, expr
, real_target_type
, loc
);
1604 if (real_target_type
!= target_type
)
1605 return new EmptyCast (ce
, target_type
);
1609 if (expr_type
== TypeManager
.sbyte_type
){
1611 // From sbyte to byte, ushort, uint, ulong, char
1613 if (real_target_type
== TypeManager
.byte_type
)
1614 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I1_U1
);
1615 if (real_target_type
== TypeManager
.ushort_type
)
1616 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I1_U2
);
1617 if (real_target_type
== TypeManager
.uint32_type
)
1618 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I1_U4
);
1619 if (real_target_type
== TypeManager
.uint64_type
)
1620 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I1_U8
);
1621 if (real_target_type
== TypeManager
.char_type
)
1622 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I1_CH
);
1623 } else if (expr_type
== TypeManager
.byte_type
){
1625 // From byte to sbyte and char
1627 if (real_target_type
== TypeManager
.sbyte_type
)
1628 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U1_I1
);
1629 } else if (expr_type
== TypeManager
.short_type
){
1631 // From short to byte
1633 if (real_target_type
== TypeManager
.sbyte_type
)
1634 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I2_I1
);
1635 if (real_target_type
== TypeManager
.byte_type
)
1636 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I2_U1
);
1637 if (real_target_type
== TypeManager
.ushort_type
)
1638 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I2_U2
);
1639 if (real_target_type
== TypeManager
.uint32_type
)
1640 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I2_U4
);
1641 if (real_target_type
== TypeManager
.uint64_type
)
1642 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I2_U8
);
1643 } else if (expr_type
== TypeManager
.ushort_type
){
1645 // From ushort to sbyte, byte, short, char
1647 if (real_target_type
== TypeManager
.sbyte_type
)
1648 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U2_I1
);
1649 if (real_target_type
== TypeManager
.byte_type
)
1650 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U2_U1
);
1651 if (real_target_type
== TypeManager
.short_type
)
1652 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U2_I2
);
1653 if (real_target_type
== TypeManager
.char_type
)
1654 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U2_CH
);
1655 } else if (expr_type
== TypeManager
.int32_type
){
1657 // From int to byte, short
1659 if (real_target_type
== TypeManager
.sbyte_type
)
1660 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I4_I1
);
1661 if (real_target_type
== TypeManager
.byte_type
)
1662 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I4_U1
);
1663 if (real_target_type
== TypeManager
.short_type
)
1664 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I4_I2
);
1665 if (real_target_type
== TypeManager
.ushort_type
)
1666 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I4_U2
);
1667 if (real_target_type
== TypeManager
.uint32_type
)
1668 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I4_U4
);
1669 if (real_target_type
== TypeManager
.uint64_type
)
1670 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I4_U8
);
1671 } else if (expr_type
== TypeManager
.uint32_type
){
1673 // From uint to sbyte, byte, short, ushort, int, char
1675 if (real_target_type
== TypeManager
.sbyte_type
)
1676 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U4_I1
);
1677 if (real_target_type
== TypeManager
.byte_type
)
1678 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U4_U1
);
1679 if (real_target_type
== TypeManager
.short_type
)
1680 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U4_I2
);
1681 if (real_target_type
== TypeManager
.ushort_type
)
1682 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U4_U2
);
1683 if (real_target_type
== TypeManager
.int32_type
)
1684 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U4_I4
);
1685 if (real_target_type
== TypeManager
.char_type
)
1686 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U4_CH
);
1687 } else if (expr_type
== TypeManager
.int64_type
){
1689 // From long to byte, short, int
1691 if (real_target_type
== TypeManager
.sbyte_type
)
1692 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I8_I1
);
1693 if (real_target_type
== TypeManager
.byte_type
)
1694 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I8_U1
);
1695 if (real_target_type
== TypeManager
.short_type
)
1696 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I8_I2
);
1697 if (real_target_type
== TypeManager
.ushort_type
)
1698 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I8_U2
);
1699 if (real_target_type
== TypeManager
.int32_type
)
1700 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I8_I4
);
1701 if (real_target_type
== TypeManager
.uint32_type
)
1702 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I8_U4
);
1703 if (real_target_type
== TypeManager
.uint64_type
)
1704 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.I8_U8
);
1705 } else if (expr_type
== TypeManager
.uint64_type
){
1707 // From ulong to sbyte, byte, short, ushort, int, uint, long, char
1709 if (real_target_type
== TypeManager
.sbyte_type
)
1710 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U8_I1
);
1711 if (real_target_type
== TypeManager
.byte_type
)
1712 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U8_U1
);
1713 if (real_target_type
== TypeManager
.short_type
)
1714 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U8_I2
);
1715 if (real_target_type
== TypeManager
.ushort_type
)
1716 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U8_U2
);
1717 if (real_target_type
== TypeManager
.int32_type
)
1718 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U8_I4
);
1719 if (real_target_type
== TypeManager
.uint32_type
)
1720 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U8_U4
);
1721 if (real_target_type
== TypeManager
.int64_type
)
1722 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U8_I8
);
1723 if (real_target_type
== TypeManager
.char_type
)
1724 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.U8_CH
);
1725 } else if (expr_type
== TypeManager
.float_type
){
1727 // From float to byte, short, int, long, decimal
1729 if (real_target_type
== TypeManager
.sbyte_type
)
1730 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.R4_I1
);
1731 if (real_target_type
== TypeManager
.byte_type
)
1732 return new FloatingToFixedCast (ec
, expr
, target_type
, ConvCast
.Mode
.R8_U1
);
1733 if (real_target_type
== TypeManager
.short_type
)
1734 return new FloatingToFixedCast (ec
, expr
, target_type
, ConvCast
.Mode
.R8_I2
);
1735 if (real_target_type
== TypeManager
.ushort_type
)
1736 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.R4_U2
);
1737 if (real_target_type
== TypeManager
.int32_type
)
1738 return new FloatingToFixedCast (ec
, expr
, target_type
, ConvCast
.Mode
.R8_I4
);
1739 if (real_target_type
== TypeManager
.uint32_type
)
1740 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.R4_U4
);
1741 if (real_target_type
== TypeManager
.int64_type
)
1742 return new FloatingToFixedCast (ec
, expr
, target_type
, ConvCast
.Mode
.R8_I8
);
1743 if (real_target_type
== TypeManager
.uint64_type
)
1744 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.R4_U8
);
1745 if (real_target_type
== TypeManager
.decimal_type
)
1746 return new ImplicitNew (ec
, "System", "Decimal", loc
, expr
);
1747 } else if (expr_type
== TypeManager
.double_type
){
1749 // From double to byte, short, int, long, float, decimal
1751 if (real_target_type
== TypeManager
.sbyte_type
)
1752 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.R8_I1
);
1753 if (real_target_type
== TypeManager
.byte_type
)
1754 return new FloatingToFixedCast (ec
, expr
, target_type
, ConvCast
.Mode
.R8_U1
);
1755 if (real_target_type
== TypeManager
.short_type
)
1756 return new FloatingToFixedCast (ec
, expr
, target_type
, ConvCast
.Mode
.R8_I2
);
1757 if (real_target_type
== TypeManager
.ushort_type
)
1758 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.R8_U2
);
1759 if (real_target_type
== TypeManager
.int32_type
)
1760 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.R8_I4
);
1761 if (real_target_type
== TypeManager
.uint32_type
)
1762 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.R8_U4
);
1763 if (real_target_type
== TypeManager
.int64_type
)
1764 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.R8_I8
);
1765 if (real_target_type
== TypeManager
.uint64_type
)
1766 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.R8_U8
);
1768 if (real_target_type
== TypeManager
.float_type
)
1769 return new ConvCast (ec
, expr
, target_type
, ConvCast
.Mode
.R8_R4
);
1770 if (real_target_type
== TypeManager
.decimal_type
)
1771 return new ImplicitNew (ec
, "System", "Decimal", loc
, expr
);
1772 } else if (expr_type
== TypeManager
.decimal_type
){
1774 // From decimal to byte, short, int, long
1776 if (real_target_type
== TypeManager
.byte_type
)
1777 return new HelperMethodInvocation (ec
, loc
, TypeManager
.byte_type
, TypeManager
.convert_to_byte_decimal
, expr
);
1778 if (real_target_type
== TypeManager
.short_type
)
1779 return new HelperMethodInvocation (ec
, loc
, TypeManager
.short_type
, TypeManager
.convert_to_int16_decimal
, expr
);
1780 if (real_target_type
== TypeManager
.int32_type
)
1781 return new HelperMethodInvocation (ec
, loc
, TypeManager
.int32_type
, TypeManager
.convert_to_int32_decimal
, expr
);
1782 if (real_target_type
== TypeManager
.int64_type
)
1783 return new HelperMethodInvocation (ec
, loc
, TypeManager
.int64_type
, TypeManager
.convert_to_int64_decimal
, expr
);
1790 /// VB.NET specific: Convert to and from boolean
1793 static public Expression
BooleanConversions (EmitContext ec
, Expression expr
,
1794 Type target_type
, Location loc
)
1796 Type expr_type
= expr
.Type
;
1797 Type real_target_type
= target_type
;
1799 if (expr_type
== TypeManager
.bool_type
) {
1802 // From boolean to byte, short, int,
1803 // long, float, double, decimal
1806 if (real_target_type
== TypeManager
.byte_type
)
1807 return new BooleanToNumericCast (expr
, target_type
, OpCodes
.Conv_U1
);
1808 if (real_target_type
== TypeManager
.short_type
)
1809 return new BooleanToNumericCast (expr
, target_type
, OpCodes
.Conv_I2
);
1810 if (real_target_type
== TypeManager
.int32_type
)
1811 return new BooleanToNumericCast (expr
, target_type
, OpCodes
.Conv_I4
);
1812 if (real_target_type
== TypeManager
.int64_type
)
1813 return new BooleanToNumericCast (expr
, target_type
, OpCodes
.Conv_I8
);
1814 if (real_target_type
== TypeManager
.float_type
)
1815 return new BooleanToNumericCast (expr
, target_type
, OpCodes
.Conv_R4
);
1816 if (real_target_type
== TypeManager
.double_type
)
1817 return new BooleanToNumericCast (expr
, target_type
, OpCodes
.Conv_R8
);
1818 if (real_target_type
== TypeManager
.decimal_type
) {
1819 return new HelperMethodInvocation (ec
, expr
.Location
, TypeManager
.decimal_type
, TypeManager
.msvbcs_decimaltype_from_boolean
, expr
);
1821 } if (real_target_type
== TypeManager
.bool_type
) {
1824 // From byte, short, int, long, float,
1825 // double, decimal to boolean
1828 if (expr_type
== TypeManager
.byte_type
||
1829 expr_type
== TypeManager
.short_type
||
1830 expr_type
== TypeManager
.int32_type
||
1831 expr_type
== TypeManager
.int64_type
||
1832 expr_type
== TypeManager
.float_type
||
1833 expr_type
== TypeManager
.double_type
)
1834 return new NumericToBooleanCast (expr
, expr_type
);
1835 if (expr_type
== TypeManager
.decimal_type
) {
1836 return new HelperMethodInvocation (ec
, expr
.Location
, TypeManager
.bool_type
, TypeManager
.convert_to_boolean_decimal
, expr
);
1844 /// VB.NET specific: Widening conversions to string
1847 static public Expression
WideningStringConversions (EmitContext ec
, Expression expr
,
1848 Type target_type
, Location loc
)
1851 Type expr_type
= expr
.Type
;
1852 Type real_target_type
= target_type
;
1854 if (real_target_type
== TypeManager
.string_type
) {
1856 // From char to string
1858 if (expr_type
== TypeManager
.char_type
)
1859 return new HelperMethodInvocation (ec
, expr
.Location
, TypeManager
.string_type
, TypeManager
.msvbcs_stringtype_from_char
, expr
);
1862 if(expr_type
.IsArray
&& (expr_type
.GetElementType() == TypeManager
.char_type
)) {
1864 // From char array to string
1866 return new ImplicitNew (ec
, "System", "String", loc
, expr
);
1873 /// VB.NET specific: Narrowing conversions involving strings
1876 static public Expression
NarrowingStringConversions (EmitContext ec
, Expression expr
,
1877 Type target_type
, Location loc
)
1879 Type expr_type
= expr
.Type
;
1880 Type real_target_type
= target_type
;
1882 // FIXME: Need to take care of Constants
1884 if (expr_type
== TypeManager
.string_type
) {
1887 // From string to chararray, bool,
1888 // byte, short, char, int, long,
1889 // float, double, decimal and date
1892 // if (real_target_type.IsArray && (real_target_type.GetElementType() == TypeManager.char_type))
1893 // return new HelperMethodInvocation (ec, loc, TypeManager.char_array_type, TypeManager.msvbcs_char_array_type_from_string, loc, expr);
1894 if (real_target_type
== TypeManager
.bool_type
)
1895 return new HelperMethodInvocation (ec
, loc
, TypeManager
.bool_type
, TypeManager
.msvbcs_booleantype_from_string
, expr
);
1896 if (real_target_type
== TypeManager
.byte_type
)
1897 return new HelperMethodInvocation (ec
, loc
, TypeManager
.byte_type
, TypeManager
.msvbcs_bytetype_from_string
, expr
);
1898 if (real_target_type
== TypeManager
.short_type
)
1899 return new HelperMethodInvocation (ec
, loc
, TypeManager
.short_type
, TypeManager
.msvbcs_shorttype_from_string
, expr
);
1900 if (real_target_type
== TypeManager
.char_type
)
1901 return new HelperMethodInvocation (ec
, loc
, TypeManager
.char_type
, TypeManager
.msvbcs_chartype_from_string
, expr
);
1902 if (real_target_type
== TypeManager
.int32_type
)
1903 return new HelperMethodInvocation (ec
, loc
, TypeManager
.int32_type
, TypeManager
.msvbcs_integertype_from_string
, expr
);
1904 if (real_target_type
== TypeManager
.int64_type
)
1905 return new HelperMethodInvocation (ec
, loc
, TypeManager
.int64_type
, TypeManager
.msvbcs_longtype_from_string
, expr
);
1906 if (real_target_type
== TypeManager
.float_type
)
1907 return new HelperMethodInvocation (ec
, loc
, TypeManager
.float_type
, TypeManager
.msvbcs_singletype_from_string
, expr
);
1908 if (real_target_type
== TypeManager
.double_type
)
1909 return new HelperMethodInvocation (ec
, loc
, TypeManager
.double_type
, TypeManager
.msvbcs_doubletype_from_string
, expr
);
1910 if (real_target_type
== TypeManager
.decimal_type
)
1911 return new HelperMethodInvocation (ec
, loc
, TypeManager
.decimal_type
, TypeManager
.msvbcs_decimaltype_from_string
, expr
);
1912 if (real_target_type
== TypeManager
.date_type
)
1913 return new HelperMethodInvocation (ec
, loc
, TypeManager
.date_type
, TypeManager
.msvbcs_datetype_from_string
, expr
);
1914 } if (real_target_type
== TypeManager
.string_type
) {
1917 // From bool, byte, short, char, int,
1918 // long, float, double, decimal and
1922 if (expr_type
== TypeManager
.bool_type
)
1923 return new HelperMethodInvocation (ec
, loc
, TypeManager
.string_type
, TypeManager
.msvbcs_stringtype_from_boolean
, expr
);
1924 if (expr_type
== TypeManager
.byte_type
)
1925 return new HelperMethodInvocation (ec
, loc
, TypeManager
.string_type
, TypeManager
.msvbcs_stringtype_from_byte
, expr
);
1926 if (expr_type
== TypeManager
.short_type
)
1927 return new HelperMethodInvocation (ec
, loc
, TypeManager
.string_type
, TypeManager
.msvbcs_stringtype_from_short
, expr
);
1928 if (expr_type
== TypeManager
.int32_type
)
1929 return new HelperMethodInvocation (ec
, loc
, TypeManager
.string_type
, TypeManager
.msvbcs_stringtype_from_integer
, expr
);
1930 if (expr_type
== TypeManager
.int64_type
)
1931 return new HelperMethodInvocation (ec
, loc
, TypeManager
.string_type
, TypeManager
.msvbcs_stringtype_from_long
, expr
);
1932 if (expr_type
== TypeManager
.float_type
)
1933 return new HelperMethodInvocation (ec
, loc
, TypeManager
.string_type
, TypeManager
.msvbcs_stringtype_from_single
, expr
);
1934 if (expr_type
== TypeManager
.double_type
)
1935 return new HelperMethodInvocation (ec
, loc
, TypeManager
.string_type
, TypeManager
.msvbcs_stringtype_from_double
, expr
);
1936 if (expr_type
== TypeManager
.decimal_type
)
1937 return new HelperMethodInvocation (ec
, loc
, TypeManager
.string_type
, TypeManager
.msvbcs_stringtype_from_decimal
, expr
);
1938 if (expr_type
== TypeManager
.date_type
)
1939 return new HelperMethodInvocation (ec
, loc
, TypeManager
.string_type
, TypeManager
.msvbcs_stringtype_from_date
, expr
);
1947 /// VB.NET specific: Conversions from Object to Primitive Types
1950 static public Expression
ObjectTypeToPrimitiveTypes (EmitContext ec
, Expression expr
,
1951 Type target_type
, Location loc
)
1953 Type expr_type
= expr
.Type
;
1954 Type real_target_type
= target_type
;
1955 MethodInfo helper_method
= null;
1958 if (expr_type
!= TypeManager
.object_type
)
1961 if (target_type
.IsSubclassOf (TypeManager
.enum_type
))
1962 real_target_type
= TypeManager
.EnumToUnderlying (target_type
);
1965 if (real_target_type
== TypeManager
.bool_type
)
1966 helper_method
= TypeManager
.msvbcs_booleantype_fromobject_object
;
1967 if (real_target_type
== TypeManager
.byte_type
)
1968 helper_method
= TypeManager
.msvbcs_bytetype_fromobject_object
;
1969 if (real_target_type
== TypeManager
.short_type
)
1970 helper_method
= TypeManager
.msvbcs_shorttype_fromobject_object
;
1971 if (real_target_type
== TypeManager
.char_type
)
1972 helper_method
= TypeManager
.msvbcs_chartype_fromobject_object
;
1973 if (real_target_type
== TypeManager
.int32_type
)
1974 helper_method
= TypeManager
.msvbcs_integertype_fromobject_object
;
1975 if (real_target_type
== TypeManager
.int64_type
)
1976 helper_method
= TypeManager
.msvbcs_longtype_fromobject_object
;
1977 if (real_target_type
== TypeManager
.float_type
)
1978 helper_method
= TypeManager
.msvbcs_singletype_fromobject_object
;
1979 if (real_target_type
== TypeManager
.double_type
)
1980 helper_method
= TypeManager
.msvbcs_doubletype_fromobject_object
;
1981 if (real_target_type
== TypeManager
.decimal_type
)
1982 helper_method
= TypeManager
.msvbcs_decimaltype_fromobject_object
;
1983 if (real_target_type
== TypeManager
.date_type
)
1984 helper_method
= TypeManager
.msvbcs_datetype_fromobject_object
;
1985 if (real_target_type
== TypeManager
.string_type
)
1986 helper_method
= TypeManager
.msvbcs_stringtype_fromobject_object
;
1988 if (helper_method
!= null) {
1989 retexpr
= new HelperMethodInvocation (ec
, loc
, real_target_type
, helper_method
, expr
);
1990 if (target_type
!= real_target_type
)
1991 retexpr
= new EmptyCast (retexpr
, target_type
);
2001 /// Returns whether an explicit reference conversion can be performed
2002 /// from source_type to target_type
2004 public static bool NarrowingReferenceConversionExists (Type source_type
, Type target_type
)
2006 bool target_is_type_param
= target_type
.IsGenericParameter
;
2007 bool target_is_value_type
= target_type
.IsValueType
;
2009 if (source_type
== target_type
)
2013 // From generic parameter to any type
2015 if (source_type
.IsGenericParameter
)
2019 // From object to a generic parameter
2021 if (source_type
== TypeManager
.object_type
&& target_is_type_param
)
2025 // From object to any reference type
2027 if (source_type
== TypeManager
.object_type
&& !target_is_value_type
)
2031 // From any class S to any class-type T, provided S is a base class of T
2033 if (TypeManager
.IsSubclassOf (target_type
, source_type
))
2037 // From any interface type S to any interface T provided S is not derived from T
2039 if (source_type
.IsInterface
&& target_type
.IsInterface
){
2040 if (!TypeManager
.IsSubclassOf (target_type
, source_type
))
2045 // From any class type S to any interface T, provided S is not sealed
2046 // and provided S does not implement T.
2048 if (target_type
.IsInterface
&& !source_type
.IsSealed
&&
2049 !TypeManager
.ImplementsInterface (source_type
, target_type
))
2053 // From any interface-type S to to any class type T, provided T is not
2054 // sealed, or provided T implements S.
2056 if (source_type
.IsInterface
&&
2057 (!target_type
.IsSealed
|| TypeManager
.ImplementsInterface (target_type
, source_type
)))
2061 // From an array type S with an element type Se to an array type T with an
2062 // element type Te provided all the following are true:
2063 // * S and T differe only in element type, in other words, S and T
2064 // have the same number of dimensions.
2065 // * Both Se and Te are reference types
2066 // * An explicit referenc conversions exist from Se to Te
2068 if (source_type
.IsArray
&& target_type
.IsArray
) {
2069 if (source_type
.GetArrayRank () == target_type
.GetArrayRank ()) {
2071 Type source_element_type
= TypeManager
.GetElementType (source_type
);
2072 Type target_element_type
= TypeManager
.GetElementType (target_type
);
2074 if (source_element_type
.IsGenericParameter
||
2075 (!source_element_type
.IsValueType
&& !target_element_type
.IsValueType
))
2076 if (NarrowingReferenceConversionExists (source_element_type
,
2077 target_element_type
))
2083 // From System.Array to any array-type
2084 if (source_type
== TypeManager
.array_type
&&
2085 target_type
.IsArray
){
2090 // From System delegate to any delegate-type
2092 if (source_type
== TypeManager
.delegate_type
&&
2093 TypeManager
.IsDelegateType (target_type
))
2097 // From ICloneable to Array or Delegate types
2099 if (source_type
== TypeManager
.icloneable_type
&&
2100 (target_type
== TypeManager
.array_type
||
2101 target_type
== TypeManager
.delegate_type
))
2108 /// Implements Explicit Reference conversions
2110 static Expression
NarrowingReferenceConversion (Expression source
, Type target_type
)
2112 Type source_type
= source
.Type
;
2113 bool target_is_type_param
= target_type
.IsGenericParameter
;
2114 bool target_is_value_type
= target_type
.IsValueType
;
2117 // From object to a generic parameter
2119 if (source_type
== TypeManager
.object_type
&& target_is_type_param
)
2120 return new UnboxCast (source
, target_type
);
2123 // From object to any reference type
2125 if (source_type
== TypeManager
.object_type
&& !target_is_value_type
)
2126 return new ClassCast (source
, target_type
);
2129 // Unboxing conversion.
2131 if (((source_type
== TypeManager
.enum_type
&&
2132 !(source
is EmptyCast
)) ||
2133 source_type
== TypeManager
.value_type
) && target_is_value_type
)
2134 return new UnboxCast (source
, target_type
);
2137 // From any class S to any class-type T, provided S is a base class of T
2139 if (TypeManager
.IsSubclassOf (target_type
, source_type
))
2140 return new ClassCast (source
, target_type
);
2143 // From any interface type S to any interface T provided S is not derived from T
2145 if (source_type
.IsInterface
&& target_type
.IsInterface
){
2146 if (TypeManager
.ImplementsInterface (source_type
, target_type
))
2149 return new ClassCast (source
, target_type
);
2153 // From any class type S to any interface T, provides S is not sealed
2154 // and provided S does not implement T.
2156 if (target_type
.IsInterface
&& !source_type
.IsSealed
) {
2157 if (TypeManager
.ImplementsInterface (source_type
, target_type
))
2160 return new ClassCast (source
, target_type
);
2165 // From any interface-type S to to any class type T, provided T is not
2166 // sealed, or provided T implements S.
2168 if (source_type
.IsInterface
) {
2169 if (!target_type
.IsSealed
|| TypeManager
.ImplementsInterface (target_type
, source_type
)) {
2170 if (target_type
.IsClass
)
2171 return new ClassCast (source
, target_type
);
2173 return new UnboxCast (source
, target_type
);
2179 // From an array type S with an element type Se to an array type T with an
2180 // element type Te provided all the following are true:
2181 // * S and T differe only in element type, in other words, S and T
2182 // have the same number of dimensions.
2183 // * Both Se and Te are reference types
2184 // * An explicit referenc conversions exist from Se to Te
2186 if (source_type
.IsArray
&& target_type
.IsArray
) {
2187 if (source_type
.GetArrayRank () == target_type
.GetArrayRank ()) {
2189 Type source_element_type
= TypeManager
.GetElementType (source_type
);
2190 Type target_element_type
= TypeManager
.GetElementType (target_type
);
2192 if (!source_element_type
.IsValueType
&& !target_element_type
.IsValueType
)
2193 if (NarrowingReferenceConversionExists (source_element_type
,
2194 target_element_type
))
2195 return new ClassCast (source
, target_type
);
2200 // From System.Array to any array-type
2201 if (source_type
== TypeManager
.array_type
&&
2202 target_type
.IsArray
) {
2203 return new ClassCast (source
, target_type
);
2207 // From System delegate to any delegate-type
2209 if (source_type
== TypeManager
.delegate_type
&&
2210 TypeManager
.IsDelegateType (target_type
))
2211 return new ClassCast (source
, target_type
);
2214 // From ICloneable to Array or Delegate types
2216 if (source_type
== TypeManager
.icloneable_type
&&
2217 (target_type
== TypeManager
.array_type
||
2218 target_type
== TypeManager
.delegate_type
))
2219 return new ClassCast (source
, target_type
);
2225 /// Performs an explicit conversion of the expression `expr' whose
2226 /// type is expr.Type to `target_type'.
2228 static public Expression
WideningAndNarrowingConversion (EmitContext ec
, Expression expr
,
2229 Type target_type
, Location loc
)
2231 Type expr_type
= expr
.Type
;
2232 Type original_expr_type
= expr_type
;
2234 if (expr_type
.IsSubclassOf (TypeManager
.enum_type
)){
2235 if (target_type
== TypeManager
.enum_type
||
2236 target_type
== TypeManager
.object_type
) {
2237 if (expr
is EnumConstant
)
2238 expr
= ((EnumConstant
) expr
).Child
;
2239 // We really need all these casts here .... :-(
2240 expr
= new BoxedCast (new EmptyCast (expr
, expr_type
));
2241 return new EmptyCast (expr
, target_type
);
2242 } else if ((expr_type
== TypeManager
.enum_type
) && target_type
.IsValueType
&&
2243 target_type
.IsSubclassOf (TypeManager
.enum_type
))
2244 return new UnboxCast (expr
, target_type
);
2247 // Notice that we have kept the expr_type unmodified, which is only
2249 if (expr
is EnumConstant
)
2250 expr
= ((EnumConstant
) expr
).Child
;
2252 expr
= new EmptyCast (expr
, TypeManager
.EnumToUnderlying (expr_type
));
2253 expr_type
= expr
.Type
;
2256 int errors
= Report
.Errors
;
2257 Expression ne
= WideningConversionStandard (ec
, expr
, target_type
, loc
);
2258 if (Report
.Errors
> errors
)
2264 if (TypeManager
.IsNullableType (expr
.Type
) && TypeManager
.IsNullableType (target_type
))
2265 return new Nullable
.LiftedConversion (
2266 expr
, target_type
, false, true, loc
).Resolve (ec
);
2268 ne
= NarrowingNumericConversion (ec
, expr
, target_type
, loc
);
2273 // Unboxing conversion.
2277 // VB.NET treats conversions from object to
2278 // the primitive types using the helper
2279 // routines in Microsoft.VisualBasic.dll
2282 ne
= ObjectTypeToPrimitiveTypes(ec
, expr
, target_type
, loc
);
2286 if (expr_type
== TypeManager
.object_type
&& target_type
.IsValueType
)
2287 return new UnboxCast (expr
, target_type
);
2290 // Skip the NarrowingReferenceConversion because we can not convert
2291 // from Null to a ValueType, and ExplicitReference wont check against
2292 // null literal explicitly
2294 if (expr_type
!= TypeManager
.null_type
){
2295 ne
= NarrowingReferenceConversion (expr
, target_type
);
2302 if (target_type
.IsPointer
){
2303 if (expr_type
.IsPointer
)
2304 return new EmptyCast (expr
, target_type
);
2306 if (expr_type
== TypeManager
.sbyte_type
||
2307 expr_type
== TypeManager
.byte_type
||
2308 expr_type
== TypeManager
.short_type
||
2309 expr_type
== TypeManager
.ushort_type
||
2310 expr_type
== TypeManager
.int32_type
||
2311 expr_type
== TypeManager
.uint32_type
||
2312 expr_type
== TypeManager
.uint64_type
||
2313 expr_type
== TypeManager
.int64_type
)
2314 return new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U
);
2316 if (expr_type
.IsPointer
){
2317 Expression e
= null;
2319 if (target_type
== TypeManager
.sbyte_type
)
2320 e
= new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I1
);
2321 else if (target_type
== TypeManager
.byte_type
)
2322 e
= new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U1
);
2323 else if (target_type
== TypeManager
.short_type
)
2324 e
= new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I2
);
2325 else if (target_type
== TypeManager
.ushort_type
)
2326 e
= new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U2
);
2327 else if (target_type
== TypeManager
.int32_type
)
2328 e
= new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I4
);
2329 else if (target_type
== TypeManager
.uint32_type
)
2330 e
= new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U4
);
2331 else if (target_type
== TypeManager
.uint64_type
)
2332 e
= new OpcodeCast (expr
, target_type
, OpCodes
.Conv_U8
);
2333 else if (target_type
== TypeManager
.int64_type
){
2334 e
= new OpcodeCast (expr
, target_type
, OpCodes
.Conv_I8
);
2340 ci
= WideningConversionStandard (ec
, e
, target_type
, loc
);
2345 ce
= NarrowingNumericConversion (ec
, e
, target_type
, loc
);
2349 // We should always be able to go from an uint32
2350 // implicitly or explicitly to the other integral
2353 throw new Exception ("Internal compiler error");
2359 // VB.NET specific conversions
2362 ne
= BooleanConversions (ec
, expr
, target_type
, loc
);
2366 ne
= NarrowingStringConversions (ec
, expr
, target_type
, loc
);
2372 // VB.NET has no notion of User defined conversions
2375 // ne = ExplicitUserConversion (ec, expr, target_type, loc);
2379 if (expr
is NullLiteral
){
2380 Report
.Error (37, loc
, "Cannot convert null to value type `" +
2381 TypeManager
.CSharpName (target_type
) + "'");
2385 Error_CannotConvertType (loc
, original_expr_type
, target_type
);
2390 /// Same as WideningAndNarrowingConversion, only it doesn't include user defined conversions
2392 static public Expression
WideningAndNarrowingConversionStandard (EmitContext ec
, Expression expr
,
2393 Type target_type
, Location l
)
2395 int errors
= Report
.Errors
;
2396 Expression ne
= WideningConversionStandard (ec
, expr
, target_type
, l
);
2397 if (Report
.Errors
> errors
)
2403 if (TypeManager
.IsNullableType (expr
.Type
) && TypeManager
.IsNullableType (target_type
))
2404 return new Nullable
.LiftedConversion (
2405 expr
, target_type
, false, true, l
).Resolve (ec
);
2407 ne
= NarrowingNumericConversion (ec
, expr
, target_type
, l
);
2411 ne
= NarrowingReferenceConversion (expr
, target_type
);
2415 Error_CannotConvertType (l
, expr
.Type
, target_type
);
2420 /// Entry point for VB.NET specific implicit conversions
2422 static public Expression
ImplicitVBConversion (EmitContext ec
, Expression expr
,
2423 Type target_type
, Location loc
)
2425 if (RootContext
.StricterTypeChecking
)
2426 return WideningConversion (ec
, expr
, target_type
, loc
);
2428 return WideningAndNarrowingConversion(ec
, expr
, target_type
, loc
);
2432 /// Mandates VB.NET specific implicit conversions
2434 static public Expression
ImplicitVBConversionRequired (EmitContext ec
, Expression source
,
2435 Type target_type
, Location loc
)
2440 int errors
= Report
.Errors
;
2441 e
= ImplicitVBConversion (ec
, source
, target_type
, loc
);
2442 if (Report
.Errors
> errors
)
2447 if (source
is DoubleLiteral
) {
2448 if (target_type
== TypeManager
.float_type
) {
2449 Error_664 (loc
, "float", "f");
2452 if (target_type
== TypeManager
.decimal_type
) {
2453 Error_664 (loc
, "decimal", "m");
2458 if (source
is Constant
){
2459 Constant c
= (Constant
) source
;
2461 Expression
.Error_ConstantValueCannotBeConverted (loc
, c
.AsString (), target_type
);
2465 Error_CannotWideningConversion (loc
, source
.Type
, target_type
);
2471 /// Entry point for VB.NET specific explicit conversions
2473 static public Expression
ExplicitVBConversion (EmitContext ec
, Expression expr
,
2474 Type target_type
, Location loc
)
2476 return WideningAndNarrowingConversion(ec
, expr
, target_type
, loc
);