PageRenderTime 54ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/mcs/mcs/convert.cs

https://bitbucket.org/danipen/mono
C# | 2198 lines | 1368 code | 301 blank | 529 comment | 609 complexity | 5726168b1d7eff0a5bb91643ead67e5e MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. //
  2. // conversion.cs: various routines for implementing conversions.
  3. //
  4. // Authors:
  5. // Miguel de Icaza (miguel@ximian.com)
  6. // Ravi Pratap (ravi@ximian.com)
  7. // Marek Safar (marek.safar@gmail.com)
  8. //
  9. // Copyright 2001, 2002, 2003 Ximian, Inc.
  10. // Copyright 2003-2008 Novell, Inc.
  11. // Copyright 2011 Xamarin Inc (http://www.xamarin.com)
  12. //
  13. using System;
  14. using System.Collections.Generic;
  15. #if STATIC
  16. using IKVM.Reflection.Emit;
  17. #else
  18. using System.Reflection.Emit;
  19. #endif
  20. namespace Mono.CSharp {
  21. //
  22. // A container class for all the conversion operations
  23. //
  24. static class Convert
  25. {
  26. //
  27. // From a one-dimensional array-type S[] to System.Collections.IList<T> and base
  28. // interfaces of this interface, provided there is an implicit reference conversion
  29. // from S to T.
  30. //
  31. static bool ArrayToIList (ArrayContainer array, TypeSpec list, bool isExplicit)
  32. {
  33. if (array.Rank != 1 || !list.IsGenericIterateInterface)
  34. return false;
  35. var arg_type = list.TypeArguments[0];
  36. if (array.Element == arg_type)
  37. return true;
  38. //
  39. // Reject conversion from T[] to IList<U> even if T has U dependency
  40. //
  41. if (arg_type.IsGenericParameter)
  42. return false;
  43. if (isExplicit)
  44. return ExplicitReferenceConversionExists (array.Element, arg_type);
  45. return ImplicitReferenceConversionExists (array.Element, arg_type);
  46. }
  47. static bool IList_To_Array(TypeSpec list, ArrayContainer array)
  48. {
  49. if (array.Rank != 1 || !list.IsGenericIterateInterface)
  50. return false;
  51. var arg_type = list.TypeArguments[0];
  52. if (array.Element == arg_type)
  53. return true;
  54. return ImplicitReferenceConversionExists (array.Element, arg_type) || ExplicitReferenceConversionExists (array.Element, arg_type);
  55. }
  56. public static Expression ImplicitTypeParameterConversion (Expression expr, TypeParameterSpec expr_type, TypeSpec target_type)
  57. {
  58. //
  59. // From T to a type parameter U, provided T depends on U
  60. //
  61. if (target_type.IsGenericParameter) {
  62. if (expr_type.TypeArguments != null) {
  63. foreach (var targ in expr_type.TypeArguments) {
  64. if (!TypeSpecComparer.Override.IsEqual (target_type, targ))
  65. continue;
  66. if (expr == null)
  67. return EmptyExpression.Null;
  68. if (expr_type.IsReferenceType && !((TypeParameterSpec)target_type).IsReferenceType)
  69. return new BoxedCast (expr, target_type);
  70. return new ClassCast (expr, target_type);
  71. }
  72. }
  73. return null;
  74. }
  75. //
  76. // LAMESPEC: From T to dynamic type because it's like T to object
  77. //
  78. if (target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
  79. if (expr == null)
  80. return EmptyExpression.Null;
  81. if (expr_type.IsReferenceType)
  82. return new ClassCast (expr, target_type);
  83. return new BoxedCast (expr, target_type);
  84. }
  85. //
  86. // From T to its effective base class C
  87. // From T to any base class of C (it cannot contain dynamic or be of dynamic type)
  88. // From T to any interface implemented by C
  89. //
  90. var base_type = expr_type.GetEffectiveBase ();
  91. if (base_type == target_type || TypeSpec.IsBaseClass (base_type, target_type, false) || base_type.ImplementsInterface (target_type, true)) {
  92. if (expr == null)
  93. return EmptyExpression.Null;
  94. if (expr_type.IsReferenceType)
  95. return new ClassCast (expr, target_type);
  96. return new BoxedCast (expr, target_type);
  97. }
  98. if (target_type.IsInterface && expr_type.IsConvertibleToInterface (target_type)) {
  99. if (expr == null)
  100. return EmptyExpression.Null;
  101. if (expr_type.IsReferenceType)
  102. return new ClassCast (expr, target_type);
  103. return new BoxedCast (expr, target_type);
  104. }
  105. return null;
  106. }
  107. static Expression ExplicitTypeParameterConversion (Expression source, TypeSpec source_type, TypeSpec target_type)
  108. {
  109. var target_tp = target_type as TypeParameterSpec;
  110. if (target_tp != null) {
  111. if (target_tp.TypeArguments != null) {
  112. foreach (var targ in target_tp.TypeArguments) {
  113. if (!TypeSpecComparer.Override.IsEqual (source_type, targ))
  114. continue;
  115. return source == null ? EmptyExpression.Null : new ClassCast (source, target_type);
  116. }
  117. }
  118. /*
  119. if (target_tp.Interfaces != null) {
  120. foreach (TypeSpec iface in target_tp.Interfaces) {
  121. if (!TypeManager.IsGenericParameter (iface))
  122. continue;
  123. if (TypeManager.IsSubclassOf (source_type, iface))
  124. return source == null ? EmptyExpression.Null : new ClassCast (source, target_type, true);
  125. }
  126. }
  127. */
  128. return null;
  129. }
  130. if (target_type.IsInterface)
  131. return source == null ? EmptyExpression.Null : new ClassCast (source, target_type, true);
  132. return null;
  133. }
  134. public static Expression ImplicitReferenceConversion (Expression expr, TypeSpec target_type, bool explicit_cast)
  135. {
  136. TypeSpec expr_type = expr.Type;
  137. if (expr_type.Kind == MemberKind.TypeParameter)
  138. return ImplicitTypeParameterConversion (expr, (TypeParameterSpec) expr.Type, target_type);
  139. //
  140. // from the null type to any reference-type.
  141. //
  142. NullLiteral nl = expr as NullLiteral;
  143. if (nl != null) {
  144. return nl.ConvertImplicitly (target_type);
  145. }
  146. if (ImplicitReferenceConversionExists (expr_type, target_type)) {
  147. //
  148. // Avoid wrapping implicitly convertible reference type
  149. //
  150. if (!explicit_cast)
  151. return expr;
  152. return EmptyCast.Create (expr, target_type);
  153. }
  154. return null;
  155. }
  156. //
  157. // Implicit reference conversions
  158. //
  159. public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type)
  160. {
  161. return ImplicitReferenceConversionExists (expr_type, target_type, true);
  162. }
  163. public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type, bool refOnlyTypeParameter)
  164. {
  165. // It's here only to speed things up
  166. if (target_type.IsStruct)
  167. return false;
  168. switch (expr_type.Kind) {
  169. case MemberKind.TypeParameter:
  170. return ImplicitTypeParameterConversion (null, (TypeParameterSpec) expr_type, target_type) != null &&
  171. (!refOnlyTypeParameter || TypeSpec.IsReferenceType (expr_type));
  172. case MemberKind.Class:
  173. //
  174. // From any class-type to dynamic (+object to speed up common path)
  175. //
  176. if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
  177. return true;
  178. if (target_type.IsClass) {
  179. //
  180. // Identity conversion, including dynamic erasure
  181. //
  182. if (TypeSpecComparer.IsEqual (expr_type, target_type))
  183. return true;
  184. //
  185. // From any class-type S to any class-type T, provided S is derived from T
  186. //
  187. return TypeSpec.IsBaseClass (expr_type, target_type, true);
  188. }
  189. //
  190. // From any class-type S to any interface-type T, provided S implements T
  191. //
  192. if (target_type.IsInterface)
  193. return expr_type.ImplementsInterface (target_type, true);
  194. return false;
  195. case MemberKind.ArrayType:
  196. //
  197. // Identity array conversion
  198. //
  199. if (expr_type == target_type)
  200. return true;
  201. //
  202. // From any array-type to System.Array
  203. //
  204. switch (target_type.BuiltinType) {
  205. case BuiltinTypeSpec.Type.Array:
  206. case BuiltinTypeSpec.Type.Object:
  207. case BuiltinTypeSpec.Type.Dynamic:
  208. return true;
  209. }
  210. var expr_type_array = (ArrayContainer) expr_type;
  211. var target_type_array = target_type as ArrayContainer;
  212. //
  213. // From an array-type S to an array-type of type T
  214. //
  215. if (target_type_array != null && expr_type_array.Rank == target_type_array.Rank) {
  216. //
  217. // Both SE and TE are reference-types. TE check is defered
  218. // to ImplicitReferenceConversionExists
  219. //
  220. TypeSpec expr_element_type = expr_type_array.Element;
  221. if (!TypeSpec.IsReferenceType (expr_element_type))
  222. return false;
  223. //
  224. // An implicit reference conversion exists from SE to TE
  225. //
  226. return ImplicitReferenceConversionExists (expr_element_type, target_type_array.Element);
  227. }
  228. //
  229. // From any array-type to the interfaces it implements
  230. //
  231. if (target_type.IsInterface) {
  232. if (expr_type.ImplementsInterface (target_type, false))
  233. return true;
  234. // from an array-type of type T to IList<T>
  235. if (ArrayToIList (expr_type_array, target_type, false))
  236. return true;
  237. }
  238. return false;
  239. case MemberKind.Delegate:
  240. //
  241. // From any delegate-type to System.Delegate (and its base types)
  242. //
  243. switch (target_type.BuiltinType) {
  244. case BuiltinTypeSpec.Type.Delegate:
  245. case BuiltinTypeSpec.Type.MulticastDelegate:
  246. case BuiltinTypeSpec.Type.Object:
  247. case BuiltinTypeSpec.Type.Dynamic:
  248. return true;
  249. }
  250. //
  251. // Identity conversion, including dynamic erasure
  252. //
  253. if (TypeSpecComparer.IsEqual (expr_type, target_type))
  254. return true;
  255. //
  256. // From any delegate-type to the interfaces it implements
  257. // From any reference-type to an delegate type if is variance-convertible
  258. //
  259. return expr_type.ImplementsInterface (target_type, false) || TypeSpecComparer.Variant.IsEqual (expr_type, target_type);
  260. case MemberKind.Interface:
  261. //
  262. // Identity conversion, including dynamic erasure
  263. //
  264. if (TypeSpecComparer.IsEqual (expr_type, target_type))
  265. return true;
  266. //
  267. // From any interface type S to interface-type T
  268. // From any reference-type to an interface if is variance-convertible
  269. //
  270. if (target_type.IsInterface)
  271. return TypeSpecComparer.Variant.IsEqual (expr_type, target_type) || expr_type.ImplementsInterface (target_type, true);
  272. return target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
  273. case MemberKind.InternalCompilerType:
  274. //
  275. // from the null literal to any reference-type.
  276. //
  277. if (expr_type == InternalType.NullLiteral) {
  278. // Exlude internal compiler types
  279. if (target_type.Kind == MemberKind.InternalCompilerType)
  280. return target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
  281. return TypeSpec.IsReferenceType (target_type);
  282. }
  283. //
  284. // Implicit dynamic conversion
  285. //
  286. if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
  287. switch (target_type.Kind) {
  288. case MemberKind.ArrayType:
  289. case MemberKind.Class:
  290. case MemberKind.Delegate:
  291. case MemberKind.Interface:
  292. case MemberKind.TypeParameter:
  293. return true;
  294. }
  295. // dynamic to __arglist
  296. if (target_type == InternalType.Arglist)
  297. return true;
  298. return false;
  299. }
  300. break;
  301. }
  302. return false;
  303. }
  304. public static Expression ImplicitBoxingConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
  305. {
  306. switch (target_type.BuiltinType) {
  307. //
  308. // From any non-nullable-value-type to the type object and dynamic
  309. //
  310. case BuiltinTypeSpec.Type.Object:
  311. case BuiltinTypeSpec.Type.Dynamic:
  312. //
  313. // From any non-nullable-value-type to the type System.ValueType
  314. //
  315. case BuiltinTypeSpec.Type.ValueType:
  316. //
  317. // No ned to check for nullable type as underlying type is always convertible
  318. //
  319. if (!TypeSpec.IsValueType (expr_type))
  320. return null;
  321. return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
  322. case BuiltinTypeSpec.Type.Enum:
  323. //
  324. // From any enum-type to the type System.Enum.
  325. //
  326. if (expr_type.IsEnum)
  327. return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
  328. break;
  329. }
  330. //
  331. // From a nullable-type to a reference type, if a boxing conversion exists from
  332. // the underlying type to the reference type
  333. //
  334. if (expr_type.IsNullableType) {
  335. if (!TypeSpec.IsReferenceType (target_type))
  336. return null;
  337. var res = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);
  338. // "cast" underlying type to target type to emit correct InvalidCastException when
  339. // underlying hierarchy changes without recompilation
  340. if (res != null && expr != null)
  341. res = new UnboxCast (res, target_type);
  342. return res;
  343. }
  344. //
  345. // A value type has a boxing conversion to an interface type I if it has a boxing conversion
  346. // to an interface or delegate type I0 and I0 is variance-convertible to I
  347. //
  348. if (target_type.IsInterface && TypeSpec.IsValueType (expr_type) && expr_type.ImplementsInterface (target_type, true)) {
  349. return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
  350. }
  351. return null;
  352. }
  353. public static Expression ImplicitNulableConversion (ResolveContext ec, Expression expr, TypeSpec target_type)
  354. {
  355. TypeSpec expr_type = expr.Type;
  356. //
  357. // From null to any nullable type
  358. //
  359. if (expr_type == InternalType.NullLiteral)
  360. return ec == null ? EmptyExpression.Null : Nullable.LiftedNull.Create (target_type, expr.Location);
  361. // S -> T?
  362. TypeSpec t_el = Nullable.NullableInfo.GetUnderlyingType (target_type);
  363. // S? -> T?
  364. if (expr_type.IsNullableType)
  365. expr_type = Nullable.NullableInfo.GetUnderlyingType (expr_type);
  366. //
  367. // Predefined implicit identity or implicit numeric conversion
  368. // has to exist between underlying type S and underlying type T
  369. //
  370. // conversion exists only mode
  371. if (ec == null) {
  372. if (TypeSpecComparer.IsEqual (expr_type, t_el))
  373. return EmptyExpression.Null;
  374. if (expr is Constant)
  375. return ((Constant) expr).ConvertImplicitly (t_el);
  376. return ImplicitNumericConversion (null, expr_type, t_el);
  377. }
  378. Expression unwrap;
  379. if (expr_type != expr.Type)
  380. unwrap = Nullable.Unwrap.Create (expr);
  381. else
  382. unwrap = expr;
  383. Expression conv = unwrap;
  384. if (!TypeSpecComparer.IsEqual (expr_type, t_el)) {
  385. if (conv is Constant)
  386. conv = ((Constant)conv).ConvertImplicitly (t_el);
  387. else
  388. conv = ImplicitNumericConversion (conv, expr_type, t_el);
  389. if (conv == null)
  390. return null;
  391. }
  392. if (expr_type != expr.Type)
  393. return new Nullable.Lifted (conv, unwrap, target_type).Resolve (ec);
  394. return Nullable.Wrap.Create (conv, target_type);
  395. }
  396. /// <summary>
  397. /// Implicit Numeric Conversions.
  398. ///
  399. /// expr is the expression to convert, returns a new expression of type
  400. /// target_type or null if an implicit conversion is not possible.
  401. /// </summary>
  402. public static Expression ImplicitNumericConversion (Expression expr, TypeSpec target_type)
  403. {
  404. return ImplicitNumericConversion (expr, expr.Type, target_type);
  405. }
  406. public static bool ImplicitNumericConversionExists (TypeSpec expr_type, TypeSpec target_type)
  407. {
  408. return ImplicitNumericConversion (null, expr_type, target_type) != null;
  409. }
  410. static Expression ImplicitNumericConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
  411. {
  412. switch (expr_type.BuiltinType) {
  413. case BuiltinTypeSpec.Type.SByte:
  414. //
  415. // From sbyte to short, int, long, float, double, decimal
  416. //
  417. switch (target_type.BuiltinType) {
  418. case BuiltinTypeSpec.Type.Int:
  419. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
  420. case BuiltinTypeSpec.Type.Long:
  421. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
  422. case BuiltinTypeSpec.Type.Double:
  423. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
  424. case BuiltinTypeSpec.Type.Float:
  425. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
  426. case BuiltinTypeSpec.Type.Short:
  427. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
  428. case BuiltinTypeSpec.Type.Decimal:
  429. return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
  430. }
  431. break;
  432. case BuiltinTypeSpec.Type.Byte:
  433. //
  434. // From byte to short, ushort, int, uint, long, ulong, float, double, decimal
  435. //
  436. switch (target_type.BuiltinType) {
  437. case BuiltinTypeSpec.Type.Int:
  438. case BuiltinTypeSpec.Type.UInt:
  439. case BuiltinTypeSpec.Type.Short:
  440. case BuiltinTypeSpec.Type.UShort:
  441. return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
  442. case BuiltinTypeSpec.Type.ULong:
  443. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
  444. case BuiltinTypeSpec.Type.Long:
  445. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
  446. case BuiltinTypeSpec.Type.Float:
  447. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
  448. case BuiltinTypeSpec.Type.Double:
  449. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
  450. case BuiltinTypeSpec.Type.Decimal:
  451. return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
  452. }
  453. break;
  454. case BuiltinTypeSpec.Type.Short:
  455. //
  456. // From short to int, long, float, double, decimal
  457. //
  458. switch (target_type.BuiltinType) {
  459. case BuiltinTypeSpec.Type.Int:
  460. return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
  461. case BuiltinTypeSpec.Type.Long:
  462. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
  463. case BuiltinTypeSpec.Type.Double:
  464. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
  465. case BuiltinTypeSpec.Type.Float:
  466. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
  467. case BuiltinTypeSpec.Type.Decimal:
  468. return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
  469. }
  470. break;
  471. case BuiltinTypeSpec.Type.UShort:
  472. //
  473. // From ushort to int, uint, long, ulong, float, double, decimal
  474. //
  475. switch (target_type.BuiltinType) {
  476. case BuiltinTypeSpec.Type.Int:
  477. case BuiltinTypeSpec.Type.UInt:
  478. return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
  479. case BuiltinTypeSpec.Type.ULong:
  480. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
  481. case BuiltinTypeSpec.Type.Long:
  482. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
  483. case BuiltinTypeSpec.Type.Double:
  484. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
  485. case BuiltinTypeSpec.Type.Float:
  486. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
  487. case BuiltinTypeSpec.Type.Decimal:
  488. return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
  489. }
  490. break;
  491. case BuiltinTypeSpec.Type.Int:
  492. //
  493. // From int to long, float, double, decimal
  494. //
  495. switch (target_type.BuiltinType) {
  496. case BuiltinTypeSpec.Type.Long:
  497. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
  498. case BuiltinTypeSpec.Type.Double:
  499. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
  500. case BuiltinTypeSpec.Type.Float:
  501. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
  502. case BuiltinTypeSpec.Type.Decimal:
  503. return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
  504. }
  505. break;
  506. case BuiltinTypeSpec.Type.UInt:
  507. //
  508. // From uint to long, ulong, float, double, decimal
  509. //
  510. switch (target_type.BuiltinType) {
  511. case BuiltinTypeSpec.Type.Long:
  512. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
  513. case BuiltinTypeSpec.Type.ULong:
  514. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
  515. case BuiltinTypeSpec.Type.Double:
  516. return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8);
  517. case BuiltinTypeSpec.Type.Float:
  518. return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4);
  519. case BuiltinTypeSpec.Type.Decimal:
  520. return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
  521. }
  522. break;
  523. case BuiltinTypeSpec.Type.Long:
  524. //
  525. // From long to float, double, decimal
  526. //
  527. switch (target_type.BuiltinType) {
  528. case BuiltinTypeSpec.Type.Double:
  529. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
  530. case BuiltinTypeSpec.Type.Float:
  531. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
  532. case BuiltinTypeSpec.Type.Decimal:
  533. return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
  534. }
  535. break;
  536. case BuiltinTypeSpec.Type.ULong:
  537. //
  538. // From ulong to float, double, decimal
  539. //
  540. switch (target_type.BuiltinType) {
  541. case BuiltinTypeSpec.Type.Double:
  542. return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8);
  543. case BuiltinTypeSpec.Type.Float:
  544. return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4);
  545. case BuiltinTypeSpec.Type.Decimal:
  546. return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
  547. }
  548. break;
  549. case BuiltinTypeSpec.Type.Char:
  550. //
  551. // From char to ushort, int, uint, long, ulong, float, double, decimal
  552. //
  553. switch (target_type.BuiltinType) {
  554. case BuiltinTypeSpec.Type.UShort:
  555. case BuiltinTypeSpec.Type.Int:
  556. case BuiltinTypeSpec.Type.UInt:
  557. return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type);
  558. case BuiltinTypeSpec.Type.ULong:
  559. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
  560. case BuiltinTypeSpec.Type.Long:
  561. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
  562. case BuiltinTypeSpec.Type.Float:
  563. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
  564. case BuiltinTypeSpec.Type.Double:
  565. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
  566. case BuiltinTypeSpec.Type.Decimal:
  567. return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type);
  568. }
  569. break;
  570. case BuiltinTypeSpec.Type.Float:
  571. //
  572. // float to double
  573. //
  574. if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double)
  575. return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
  576. break;
  577. }
  578. return null;
  579. }
  580. //
  581. // Full version of implicit conversion
  582. //
  583. public static bool ImplicitConversionExists (ResolveContext ec, Expression expr, TypeSpec target_type)
  584. {
  585. if (ImplicitStandardConversionExists (expr, target_type))
  586. return true;
  587. if (expr.Type == InternalType.AnonymousMethod) {
  588. if (!target_type.IsDelegate && !target_type.IsExpressionTreeType)
  589. return false;
  590. AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
  591. return ame.ImplicitStandardConversionExists (ec, target_type);
  592. }
  593. if (expr.eclass == ExprClass.MethodGroup) {
  594. if (target_type.IsDelegate && ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1) {
  595. MethodGroupExpr mg = expr as MethodGroupExpr;
  596. if (mg != null)
  597. return DelegateCreation.ImplicitStandardConversionExists (ec, mg, target_type);
  598. }
  599. return false;
  600. }
  601. // Conversion from __arglist to System.ArgIterator
  602. if (expr.Type == InternalType.Arglist)
  603. return target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec;
  604. return UserDefinedConversion (ec, expr, target_type, true, true, Location.Null) != null;
  605. }
  606. //
  607. // Implicit standard conversion (only core conversions are used here)
  608. //
  609. public static bool ImplicitStandardConversionExists (Expression expr, TypeSpec target_type)
  610. {
  611. //
  612. // Identity conversions
  613. // Implicit numeric conversions
  614. // Implicit nullable conversions
  615. // Implicit reference conversions
  616. // Boxing conversions
  617. // Implicit constant expression conversions
  618. // Implicit conversions involving type parameters
  619. //
  620. TypeSpec expr_type = expr.Type;
  621. if (expr_type == target_type)
  622. return true;
  623. if (target_type.IsNullableType)
  624. return ImplicitNulableConversion (null, expr, target_type) != null;
  625. if (ImplicitNumericConversion (null, expr_type, target_type) != null)
  626. return true;
  627. if (ImplicitReferenceConversionExists (expr_type, target_type, false))
  628. return true;
  629. if (ImplicitBoxingConversion (null, expr_type, target_type) != null)
  630. return true;
  631. //
  632. // Implicit Constant Expression Conversions
  633. //
  634. if (expr is IntConstant){
  635. int value = ((IntConstant) expr).Value;
  636. switch (target_type.BuiltinType) {
  637. case BuiltinTypeSpec.Type.SByte:
  638. if (value >= SByte.MinValue && value <= SByte.MaxValue)
  639. return true;
  640. break;
  641. case BuiltinTypeSpec.Type.Byte:
  642. if (value >= 0 && value <= Byte.MaxValue)
  643. return true;
  644. break;
  645. case BuiltinTypeSpec.Type.Short:
  646. if (value >= Int16.MinValue && value <= Int16.MaxValue)
  647. return true;
  648. break;
  649. case BuiltinTypeSpec.Type.UShort:
  650. if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
  651. return true;
  652. break;
  653. case BuiltinTypeSpec.Type.UInt:
  654. if (value >= 0)
  655. return true;
  656. break;
  657. case BuiltinTypeSpec.Type.ULong:
  658. //
  659. // we can optimize this case: a positive int32
  660. // always fits on a uint64. But we need an opcode
  661. // to do it.
  662. //
  663. if (value >= 0)
  664. return true;
  665. break;
  666. }
  667. }
  668. if (expr is LongConstant && target_type.BuiltinType == BuiltinTypeSpec.Type.ULong){
  669. //
  670. // Try the implicit constant expression conversion
  671. // from long to ulong, instead of a nice routine,
  672. // we just inline it
  673. //
  674. long v = ((LongConstant) expr).Value;
  675. if (v >= 0)
  676. return true;
  677. }
  678. if (expr is IntegralConstant && target_type.IsEnum) {
  679. var i = (IntegralConstant) expr;
  680. //
  681. // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
  682. //
  683. // An implicit enumeration conversion permits the decimal-integer-literal 0
  684. // to be converted to any enum-type and to any nullable-type whose underlying
  685. // type is an enum-type
  686. //
  687. return i.IsZeroInteger;
  688. }
  689. //
  690. // Implicit dynamic conversion for remaining value types. It should probably
  691. // go somewhere else
  692. //
  693. if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
  694. switch (target_type.Kind) {
  695. case MemberKind.Struct:
  696. case MemberKind.Enum:
  697. return true;
  698. }
  699. return false;
  700. }
  701. //
  702. // In an unsafe context implicit conversions is extended to include
  703. //
  704. // From any pointer-type to the type void*
  705. // From the null literal to any pointer-type.
  706. //
  707. // LAMESPEC: The specification claims this conversion is allowed in implicit conversion but
  708. // in reality implicit standard conversion uses it
  709. //
  710. if (target_type.IsPointer && expr.Type.IsPointer && ((PointerContainer) target_type).Element.Kind == MemberKind.Void)
  711. return true;
  712. //
  713. // Struct identity conversion, including dynamic erasure
  714. //
  715. if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type))
  716. return true;
  717. return false;
  718. }
  719. /// <summary>
  720. /// Finds "most encompassed type" according to the spec (13.4.2)
  721. /// amongst the methods in the MethodGroupExpr
  722. /// </summary>
  723. public static TypeSpec FindMostEncompassedType (IList<TypeSpec> types)
  724. {
  725. TypeSpec best = null;
  726. EmptyExpression expr;
  727. foreach (TypeSpec t in types) {
  728. if (best == null) {
  729. best = t;
  730. continue;
  731. }
  732. expr = new EmptyExpression (t);
  733. if (ImplicitStandardConversionExists (expr, best))
  734. best = t;
  735. }
  736. expr = new EmptyExpression (best);
  737. foreach (TypeSpec t in types) {
  738. if (best == t)
  739. continue;
  740. if (!ImplicitStandardConversionExists (expr, t)) {
  741. best = null;
  742. break;
  743. }
  744. }
  745. return best;
  746. }
  747. //
  748. // Finds the most encompassing type (type into which all other
  749. // types can convert to) amongst the types in the given set
  750. //
  751. static TypeSpec FindMostEncompassingType (IList<TypeSpec> types)
  752. {
  753. if (types.Count == 0)
  754. return null;
  755. if (types.Count == 1)
  756. return types [0];
  757. TypeSpec best = null;
  758. for (int i = 0; i < types.Count; ++i) {
  759. int ii = 0;
  760. for (; ii < types.Count; ++ii) {
  761. if (ii == i)
  762. continue;
  763. var expr = new EmptyExpression (types[ii]);
  764. if (!ImplicitStandardConversionExists (expr, types [i])) {
  765. ii = 0;
  766. break;
  767. }
  768. }
  769. if (ii == 0)
  770. continue;
  771. if (best == null) {
  772. best = types[i];
  773. continue;
  774. }
  775. // Indicates multiple best types
  776. return InternalType.FakeInternalType;
  777. }
  778. return best;
  779. }
  780. //
  781. // Finds the most specific source Sx according to the rules of the spec (13.4.4)
  782. // by making use of FindMostEncomp* methods. Applies the correct rules separately
  783. // for explicit and implicit conversion operators.
  784. //
  785. static TypeSpec FindMostSpecificSource (List<MethodSpec> list, TypeSpec sourceType, Expression source, bool apply_explicit_conv_rules)
  786. {
  787. TypeSpec[] src_types_set = null;
  788. //
  789. // Try exact match first, if any operator converts from S then Sx = S
  790. //
  791. for (int i = 0; i < list.Count; ++i) {
  792. TypeSpec param_type = list [i].Parameters.Types [0];
  793. if (param_type == sourceType)
  794. return param_type;
  795. if (src_types_set == null)
  796. src_types_set = new TypeSpec [list.Count];
  797. src_types_set [i] = param_type;
  798. }
  799. //
  800. // Explicit Conv rules
  801. //
  802. if (apply_explicit_conv_rules) {
  803. var candidate_set = new List<TypeSpec> ();
  804. foreach (TypeSpec param_type in src_types_set){
  805. if (ImplicitStandardConversionExists (source, param_type))
  806. candidate_set.Add (param_type);
  807. }
  808. if (candidate_set.Count != 0)
  809. return FindMostEncompassedType (candidate_set);
  810. }
  811. //
  812. // Final case
  813. //
  814. if (apply_explicit_conv_rules)
  815. return FindMostEncompassingType (src_types_set);
  816. else
  817. return FindMostEncompassedType (src_types_set);
  818. }
  819. /// <summary>
  820. /// Finds the most specific target Tx according to section 13.4.4
  821. /// </summary>
  822. static public TypeSpec FindMostSpecificTarget (IList<MethodSpec> list,
  823. TypeSpec target, bool apply_explicit_conv_rules)
  824. {
  825. List<TypeSpec> tgt_types_set = null;
  826. //
  827. // If any operator converts to T then Tx = T
  828. //
  829. foreach (var mi in list){
  830. TypeSpec ret_type = mi.ReturnType;
  831. if (ret_type == target)
  832. return ret_type;
  833. if (tgt_types_set == null) {
  834. tgt_types_set = new List<TypeSpec> (list.Count);
  835. } else if (tgt_types_set.Contains (ret_type)) {
  836. continue;
  837. }
  838. tgt_types_set.Add (ret_type);
  839. }
  840. //
  841. // Explicit conv rules
  842. //
  843. if (apply_explicit_conv_rules) {
  844. var candidate_set = new List<TypeSpec> ();
  845. foreach (TypeSpec ret_type in tgt_types_set) {
  846. var expr = new EmptyExpression (ret_type);
  847. if (ImplicitStandardConversionExists (expr, target))
  848. candidate_set.Add (ret_type);
  849. }
  850. if (candidate_set.Count != 0)
  851. return FindMostEncompassingType (candidate_set);
  852. }
  853. //
  854. // Okay, final case !
  855. //
  856. if (apply_explicit_conv_rules)
  857. return FindMostEncompassedType (tgt_types_set);
  858. else
  859. return FindMostEncompassingType (tgt_types_set);
  860. }
  861. /// <summary>
  862. /// User-defined Implicit conversions
  863. /// </summary>
  864. static public Expression ImplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc)
  865. {
  866. return UserDefinedConversion (ec, source, target, true, false, loc);
  867. }
  868. /// <summary>
  869. /// User-defined Explicit conversions
  870. /// </summary>
  871. static Expression ExplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc)
  872. {
  873. return UserDefinedConversion (ec, source, target, false, false, loc);
  874. }
  875. static void FindApplicableUserDefinedConversionOperators (IList<MemberSpec> operators, Expression source, TypeSpec target, bool implicitOnly, ref List<MethodSpec> candidates)
  876. {
  877. if (source.Type.IsInterface) {
  878. // Neither A nor B are interface-types
  879. return;
  880. }
  881. // For a conversion operator to be applicable, it must be possible
  882. // to perform a standard conversion from the source type to
  883. // the operand type of the operator, and it must be possible
  884. // to perform a standard conversion from the result type of
  885. // the operator to the target type.
  886. Expression texpr = null;
  887. foreach (MethodSpec op in operators) {
  888. // Can be null because MemberCache.GetUserOperator does not resize the array
  889. if (op == null)
  890. continue;
  891. var t = op.Parameters.Types[0];
  892. if (source.Type != t && !ImplicitStandardConversionExists (source, t)) {
  893. if (implicitOnly)
  894. continue;
  895. if (!ImplicitStandardConversionExists (new EmptyExpression (t), source.Type))
  896. continue;
  897. }
  898. t = op.ReturnType;
  899. if (t.IsInterface)
  900. continue;
  901. if (target != t) {
  902. if (t.IsNullableType)
  903. t = Nullable.NullableInfo.GetUnderlyingType (t);
  904. if (!ImplicitStandardConversionExists (new EmptyExpression (t), target)) {
  905. if (implicitOnly)
  906. continue;
  907. if (texpr == null)
  908. texpr = new EmptyExpression (target);
  909. if (!ImplicitStandardConversionExists (texpr, t))
  910. continue;
  911. }
  912. }
  913. if (candidates == null)
  914. candidates = new List<MethodSpec> ();
  915. candidates.Add (op);
  916. }
  917. }
  918. //
  919. // User-defined conversions
  920. //
  921. static Expression UserDefinedConversion (ResolveContext ec, Expression source, TypeSpec target, bool implicitOnly, bool probingOnly, Location loc)
  922. {
  923. List<MethodSpec> candidates = null;
  924. //
  925. // If S or T are nullable types, source_type and target_type are their underlying types
  926. // otherwise source_type and target_type are equal to S and T respectively.
  927. //
  928. TypeSpec source_type = source.Type;
  929. TypeSpec target_type = target;
  930. Expression source_type_expr;
  931. if (source_type.IsNullableType) {
  932. // No unwrapping conversion S? -> T for non-reference types
  933. if (implicitOnly && !TypeSpec.IsReferenceType (target_type) && !target_type.IsNullableType) {
  934. source_type_expr = source;
  935. } else {
  936. source_type_expr = Nullable.Unwrap.Create (source);
  937. source_type = source_type_expr.Type;
  938. }
  939. } else {
  940. source_type_expr = source;
  941. }
  942. if (target_type.IsNullableType)
  943. target_type = Nullable.NullableInfo.GetUnderlyingType (target_type);
  944. // Only these containers can contain a user defined implicit or explicit operators
  945. const MemberKind user_conversion_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.TypeParameter;
  946. if ((source_type.Kind & user_conversion_kinds) != 0 && source_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
  947. bool declared_only = source_type.IsStruct;
  948. var operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Implicit, declared_only);
  949. if (operators != null) {
  950. FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates);
  951. }
  952. if (!implicitOnly) {
  953. operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Explicit, declared_only);
  954. if (operators != null) {
  955. FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates);
  956. }
  957. }
  958. }
  959. if ((target.Kind & user_conversion_kinds) != 0 && target_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
  960. bool declared_only = target.IsStruct || implicitOnly;
  961. var operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Implicit, declared_only);
  962. if (operators != null) {
  963. FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates);
  964. }
  965. if (!implicitOnly) {
  966. operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Explicit, declared_only);
  967. if (operators != null) {
  968. FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates);
  969. }
  970. }
  971. }
  972. if (candidates == null)
  973. return null;
  974. //
  975. // Find the most specific conversion operator
  976. //
  977. MethodSpec most_specific_operator;
  978. TypeSpec s_x, t_x;
  979. if (candidates.Count == 1) {
  980. most_specific_operator = candidates[0];
  981. s_x = most_specific_operator.Parameters.Types[0];
  982. t_x = most_specific_operator.ReturnType;
  983. } else {
  984. //
  985. // Pass original source type to find the best match against input type and
  986. // not the unwrapped expression
  987. //
  988. s_x = FindMostSpecificSource (candidates, source.Type, source_type_expr, !implicitOnly);
  989. if (s_x == null)
  990. return null;
  991. t_x = FindMostSpecificTarget (candidates, target, !implicitOnly);
  992. if (t_x == null)
  993. return null;
  994. most_specific_operator = null;
  995. for (int i = 0; i < candidates.Count; ++i) {
  996. if (candidates[i].ReturnType == t_x && candidates[i].Parameters.Types[0] == s_x) {
  997. most_specific_operator = candidates[i];
  998. break;
  999. }
  1000. }
  1001. if (most_specific_operator == null) {
  1002. //
  1003. // Unless running in probing more
  1004. //
  1005. if (!probingOnly) {
  1006. MethodSpec ambig_arg = null;
  1007. foreach (var candidate in candidates) {
  1008. if (candidate.ReturnType == t_x)
  1009. most_specific_operator = candidate;
  1010. else if (candidate.Parameters.Types[0] == s_x)
  1011. ambig_arg = candidate;
  1012. }
  1013. ec.Report.Error (457, loc,
  1014. "Ambiguous user defined operators `{0}' and `{1}' when converting from `{2}' to `{3}'",
  1015. ambig_arg.GetSignatureForError (), most_specific_operator.GetSignatureForError (),
  1016. source.Type.GetSignatureForError (), target.GetSignatureForError ());
  1017. }
  1018. return ErrorExpression.Instance;
  1019. }
  1020. }
  1021. //
  1022. // Convert input type when it's different to best operator argument
  1023. //
  1024. if (s_x != source_type) {
  1025. var c = source as Constant;
  1026. if (c != null) {
  1027. source = c.Reduce (ec, s_x);
  1028. if (source == null)
  1029. c = null;
  1030. }
  1031. if (c == null) {
  1032. source = implicitOnly ?
  1033. ImplicitConversionStandard (ec, source_type_expr, s_x, loc) :
  1034. ExplicitConversionStandard (ec, source_type_expr, s_x, loc);
  1035. }
  1036. } else {
  1037. source = source_type_expr;
  1038. }
  1039. source = new UserCast (most_specific_operator, source, loc).Resolve (ec);
  1040. //
  1041. // Convert result type when it's different to best operator return type
  1042. //
  1043. if (t_x != target_type) {
  1044. //
  1045. // User operator is of T?, no need to lift it
  1046. //
  1047. if (t_x == target && t_x.IsNullableType)
  1048. return source;
  1049. source = implicitOnly ?
  1050. ImplicitConversionStandard (ec, source, target_type, loc) :
  1051. ExplicitConversionStandard (ec, source, target_type, loc);
  1052. if (source == null)
  1053. return null;
  1054. }
  1055. //
  1056. // Source expression is of nullable type, lift the result in the case it's null and
  1057. // not nullable/lifted user operator is used
  1058. //
  1059. if (source_type_expr is Nullable.Unwrap && !s_x.IsNullableType && (TypeSpec.IsReferenceType (target) || target_type != target))
  1060. source = new Nullable.Lifted (source, source_type_expr, target).Resolve (ec);
  1061. else if (target_type != target)
  1062. source = Nullable.Wrap.Create (source, target);
  1063. return source;
  1064. }
  1065. /// <summary>
  1066. /// Converts implicitly the resolved expression `expr' into the
  1067. /// `target_type'. It returns a new expression that can be used
  1068. /// in a context that expects a `target_type'.
  1069. /// </summary>
  1070. static public Expression ImplicitConversion (ResolveContext ec, Expression expr,
  1071. TypeSpec target_type, Location loc)
  1072. {
  1073. Expression e;
  1074. if (target_type == null)
  1075. throw new Exception ("Target type is null");
  1076. e = ImplicitConversionStandard (ec, expr, target_type, loc);
  1077. if (e != null)
  1078. return e;
  1079. e = ImplicitUserConversion (ec, expr, target_type, loc);
  1080. if (e != null)
  1081. return e;
  1082. return null;
  1083. }
  1084. /// <summary>
  1085. /// Attempts to apply the `Standard Implicit
  1086. /// Conversion' rules to the expression `expr' into
  1087. /// the `target_type'. It returns a new expression
  1088. /// that can be used in a context that expects a
  1089. /// `target_type'.
  1090. ///
  1091. /// This is different from `ImplicitConversion' in that the
  1092. /// user defined implicit conversions are excluded.
  1093. /// </summary>
  1094. static public Expression ImplicitConversionStandard (ResolveContext ec, Expression expr,
  1095. TypeSpec target_type, Location loc)
  1096. {
  1097. return ImplicitConversionStandard (ec, expr, target_type, loc, false);
  1098. }
  1099. static Expression ImplicitConversionStandard (ResolveContext ec, Expression expr, TypeSpec target_type, Location loc, bool explicit_cast)
  1100. {
  1101. if (expr.eclass == ExprClass.MethodGroup){
  1102. if (!target_type.IsDelegate){
  1103. return null;
  1104. }
  1105. //
  1106. // Only allow anonymous method conversions on post ISO_1
  1107. //
  1108. if (ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1){
  1109. MethodGroupExpr mg = expr as MethodGroupExpr;
  1110. if (mg != null)
  1111. return ImplicitDelegateCreation.Create (
  1112. ec, mg, target_type, loc);
  1113. }
  1114. }
  1115. TypeSpec expr_type = expr.Type;
  1116. Expression e;
  1117. if (expr_type == target_type) {
  1118. if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod)
  1119. return expr;
  1120. return null;
  1121. }
  1122. if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
  1123. switch (target_type.Kind) {
  1124. case MemberKind.ArrayType:
  1125. case MemberKind.Class:
  1126. if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object)
  1127. return EmptyCast.Create (expr, target_type);
  1128. goto case MemberKind.Struct;
  1129. case MemberKind.Struct:
  1130. case MemberKind.Delegate:
  1131. case MemberKind.Enum:
  1132. case MemberKind.Interface:
  1133. case MemberKind.TypeParameter:
  1134. Arguments args = new Arguments (1);
  1135. args.Add (new Argument (expr));
  1136. return new DynamicConversion (target_type, explicit_cast ? CSharpBinderFlags.ConvertExplicit : 0, args, loc).Resolve (ec);
  1137. }
  1138. return null;
  1139. }
  1140. if (target_type.IsNullableType)
  1141. return ImplicitNulableConversion (ec, expr, target_type);
  1142. //
  1143. // Attempt to do the implicit constant expression conversions
  1144. //
  1145. Constant c = expr as Constant;
  1146. if (c != null) {
  1147. try {
  1148. c = c.ConvertImplicitly (target_type);
  1149. } catch {
  1150. throw new InternalErrorException ("Conversion error", loc);
  1151. }
  1152. if (c != null)
  1153. return c;
  1154. }
  1155. e = ImplicitNumericConversion (expr, expr_type, target_type);
  1156. if (e != null)
  1157. return e;
  1158. e = ImplicitReferenceConversion (expr, target_type, explicit_cast);
  1159. if (e != null)
  1160. return e;
  1161. e = ImplicitBoxingConversion (expr, expr_type, target_type);
  1162. if (e != null)
  1163. return e;
  1164. if (expr is IntegralConstant && target_type.IsEnum){
  1165. var i = (IntegralConstant) expr;
  1166. //
  1167. // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0
  1168. //
  1169. // An implicit enumeration conversion permits the decimal-integer-literal 0
  1170. // to be converted to any enum-type and to any nullable-type whose underlying
  1171. // type is an enum-type
  1172. //
  1173. if (i.IsZeroInteger) {
  1174. // Recreate 0 literal to remove any collected conversions
  1175. return new EnumConstant (new IntLiteral (ec.BuiltinTypes, 0, i.Location), target_type);
  1176. }
  1177. }
  1178. if (ec.IsUnsafe) {
  1179. var target_pc = target_type as PointerContainer;
  1180. if (target_pc != null) {
  1181. if (expr_type.IsPointer) {
  1182. //
  1183. // Pointer types are same when they have same element types
  1184. //
  1185. if (expr_type == target_pc)
  1186. return expr;
  1187. if (target_pc.Element.Kind == MemberKind.Void)
  1188. return EmptyCast.Create (expr, target_type);
  1189. //return null;
  1190. }
  1191. if (expr_type == InternalType.NullLiteral)
  1192. return new NullPointer (target_type, loc);
  1193. }
  1194. }
  1195. if (expr_type == InternalType.AnonymousMethod){
  1196. AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
  1197. Expression am = ame.Compatible (ec, target_type);
  1198. if (am != null)
  1199. return am.Resolve (ec);
  1200. }
  1201. if (expr_type == InternalType.Arglist && target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec)
  1202. return expr;
  1203. //
  1204. // dynamic erasure conversion on value types
  1205. //
  1206. if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type))
  1207. return expr_type == target_type ? expr : EmptyCast.Create (expr, target_type);
  1208. return null;
  1209. }
  1210. /// <summary>
  1211. /// Attempts to implicitly convert `source' into `target_type', using
  1212. /// ImplicitConversion. If there is no implicit conversion, then
  1213. /// an error is signaled
  1214. /// </summary>
  1215. static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source,
  1216. TypeSpec target_type, Location loc)
  1217. {
  1218. Expression e = ImplicitConversion (ec, source, target_type, loc);
  1219. if (e != null)
  1220. return e;
  1221. source.Error_ValueCannotBeConverted (ec, target_type, false);
  1222. return null;
  1223. }
  1224. /// <summary>
  1225. /// Performs the explicit numeric conversions
  1226. ///
  1227. /// There are a few conversions that are not part of the C# standard,
  1228. /// they were interim hacks in the C# compiler that were supposed to
  1229. /// become explicit operators in the UIntPtr class and IntPtr class,
  1230. /// but for historical reasons it did not happen, so the C# compiler
  1231. /// ended up with these special hacks.
  1232. ///
  1233. /// See bug 59800 for details.
  1234. ///
  1235. /// The conversion are:
  1236. /// UIntPtr->SByte
  1237. /// UIntPtr->Int16
  1238. /// UIntPtr->Int32
  1239. /// IntPtr->UInt64
  1240. /// UInt64->IntPtr
  1241. /// SByte->UIntPtr
  1242. /// Int16->UIntPtr
  1243. ///
  1244. /// </summary>
  1245. public static Expression ExplicitNumericConversion (ResolveContext rc, Expression expr, TypeSpec target_type)
  1246. {
  1247. // Not all predefined explicit numeric conversion are
  1248. // defined here, for some of them (mostly IntPtr/UIntPtr) we
  1249. // defer to user-operator handling which is now perfect but
  1250. // works for now
  1251. //
  1252. // LAMESPEC: Undocumented IntPtr/UIntPtr conversions
  1253. // IntPtr -> uint uses int
  1254. // UIntPtr -> long uses ulong
  1255. //
  1256. switch (expr.Type.BuiltinType) {
  1257. case BuiltinTypeSpec.Type.SByte:
  1258. //
  1259. // From sbyte to byte, ushort, uint, ulong, char, uintptr
  1260. //
  1261. switch (target_type.BuiltinType) {
  1262. case BuiltinTypeSpec.Type.Byte:
  1263. return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1);
  1264. case BuiltinTypeSpec.Type.UShort:
  1265. return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2);
  1266. case BuiltinTypeSpec.Type.UInt:
  1267. return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4);
  1268. case BuiltinTypeSpec.Type.ULong:
  1269. return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8);
  1270. case BuiltinTypeSpec.Type.Char:
  1271. return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH);
  1272. // One of the built-in conversions that belonged in the class library
  1273. case BuiltinTypeSpec.Type.UIntPtr:
  1274. return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I1_U8), target_type, target_type, true);
  1275. }
  1276. break;
  1277. case BuiltinTypeSpec.Type.Byte:
  1278. //
  1279. // From byte to sbyte and char
  1280. //
  1281. switch (target_type.BuiltinType) {
  1282. case BuiltinTypeSpec.Type.SByte:
  1283. return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1);
  1284. case BuiltinTypeSpec.Type.Char:
  1285. return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH);
  1286. }
  1287. break;
  1288. case BuiltinTypeSpec.Type.Short:
  1289. //
  1290. // From short to sbyte, byte, ushort, uint, ulong, char, uintptr
  1291. //
  1292. switch (target_type.BuiltinType) {
  1293. case BuiltinTypeSpec.Type.SByte:
  1294. return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1);
  1295. case BuiltinTypeSpec.Type.Byte:
  1296. return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1);
  1297. case BuiltinTypeSpec.Type.UShort:
  1298. return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2);
  1299. case BuiltinTypeSpec.Type.UInt:
  1300. return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4);
  1301. case BuiltinTypeSpec.Type.ULong:
  1302. return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8);
  1303. case BuiltinTypeSpec.Type.Char:
  1304. return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH);
  1305. // One of the built-in conversions that belonged in the class library
  1306. case BuiltinTypeSpec.Type.UIntPtr:
  1307. return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true);
  1308. }
  1309. break;
  1310. case BuiltinTypeSpec.Type.UShort:
  1311. //
  1312. // From ushort to sbyte, byte, short, char
  1313. //
  1314. switch (target_type.BuiltinType) {
  1315. case BuiltinTypeSpec.Type.SByte:
  1316. return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1);
  1317. case BuiltinTypeSpec.Type.Byte:
  1318. return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1);
  1319. case BuiltinTypeSpec.Type.Short:
  1320. return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2);
  1321. case BuiltinTypeSpec.Type.Char:
  1322. return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH);
  1323. }
  1324. break;
  1325. case BuiltinTypeSpec.Type.Int:
  1326. //
  1327. // From int to sbyte, byte, short, ushort, uint, ulong, char, uintptr
  1328. //
  1329. switch (target_type.BuiltinType) {
  1330. case BuiltinTypeSpec.Type.SByte:
  1331. return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1);
  1332. case BuiltinTypeSpec.Type.Byte:
  1333. return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1);
  1334. case BuiltinTypeSpec.Type.Short:
  1335. return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2);
  1336. case BuiltinT

Large files files are truncated, but you can click here to view the full file