PageRenderTime 60ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 1ms

/src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs

http://github.com/icsharpcode/SharpDevelop
C# | 6442 lines | 4510 code | 1065 blank | 867 comment | 1305 complexity | 09d7c15b599589235347866a4446af12 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CPL-1.0, LGPL-2.1

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

  1. //
  2. // ecore.cs: Core of the Expression representation for the intermediate tree.
  3. //
  4. // Author:
  5. // Miguel de Icaza (miguel@ximian.com)
  6. // Marek Safar (marek.safar@seznam.cz)
  7. //
  8. // Copyright 2001, 2002, 2003 Ximian, Inc.
  9. // Copyright 2003-2008 Novell, Inc.
  10. // Copyright 2011 Xamarin Inc.
  11. //
  12. //
  13. using System;
  14. using System.Collections.Generic;
  15. using System.Text;
  16. using SLE = System.Linq.Expressions;
  17. using System.Linq;
  18. #if STATIC
  19. using IKVM.Reflection;
  20. using IKVM.Reflection.Emit;
  21. #else
  22. using System.Reflection;
  23. using System.Reflection.Emit;
  24. #endif
  25. namespace Mono.CSharp {
  26. /// <remarks>
  27. /// The ExprClass class contains the is used to pass the
  28. /// classification of an expression (value, variable, namespace,
  29. /// type, method group, property access, event access, indexer access,
  30. /// nothing).
  31. /// </remarks>
  32. public enum ExprClass : byte {
  33. Unresolved = 0,
  34. Value,
  35. Variable,
  36. Namespace,
  37. Type,
  38. TypeParameter,
  39. MethodGroup,
  40. PropertyAccess,
  41. EventAccess,
  42. IndexerAccess,
  43. Nothing,
  44. }
  45. /// <remarks>
  46. /// This is used to tell Resolve in which types of expressions we're
  47. /// interested.
  48. /// </remarks>
  49. [Flags]
  50. public enum ResolveFlags {
  51. // Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess.
  52. VariableOrValue = 1,
  53. // Returns a type expression.
  54. Type = 1 << 1,
  55. // Returns a method group.
  56. MethodGroup = 1 << 2,
  57. TypeParameter = 1 << 3,
  58. // Mask of all the expression class flags.
  59. MaskExprClass = VariableOrValue | Type | MethodGroup | TypeParameter,
  60. }
  61. //
  62. // This is just as a hint to AddressOf of what will be done with the
  63. // address.
  64. [Flags]
  65. public enum AddressOp {
  66. Store = 1,
  67. Load = 2,
  68. LoadStore = 3
  69. };
  70. /// <summary>
  71. /// This interface is implemented by variables
  72. /// </summary>
  73. public interface IMemoryLocation {
  74. /// <summary>
  75. /// The AddressOf method should generate code that loads
  76. /// the address of the object and leaves it on the stack.
  77. ///
  78. /// The `mode' argument is used to notify the expression
  79. /// of whether this will be used to read from the address or
  80. /// write to the address.
  81. ///
  82. /// This is just a hint that can be used to provide good error
  83. /// reporting, and should have no other side effects.
  84. /// </summary>
  85. void AddressOf (EmitContext ec, AddressOp mode);
  86. }
  87. //
  88. // An expressions resolved as a direct variable reference
  89. //
  90. public interface IVariableReference : IFixedExpression
  91. {
  92. bool IsHoisted { get; }
  93. string Name { get; }
  94. VariableInfo VariableInfo { get; }
  95. void SetHasAddressTaken ();
  96. }
  97. //
  98. // Implemented by an expression which could be or is always
  99. // fixed
  100. //
  101. public interface IFixedExpression
  102. {
  103. bool IsFixed { get; }
  104. }
  105. public interface IExpressionCleanup
  106. {
  107. void EmitCleanup (EmitContext ec);
  108. }
  109. /// <remarks>
  110. /// Base class for expressions
  111. /// </remarks>
  112. public abstract class Expression {
  113. public ExprClass eclass;
  114. protected TypeSpec type;
  115. protected Location loc;
  116. public TypeSpec Type {
  117. get { return type; }
  118. set { type = value; }
  119. }
  120. public virtual bool IsSideEffectFree {
  121. get {
  122. return false;
  123. }
  124. }
  125. public Location Location {
  126. get { return loc; }
  127. }
  128. public virtual bool IsNull {
  129. get {
  130. return false;
  131. }
  132. }
  133. //
  134. // Returns true when the expression during Emit phase breaks stack
  135. // by using await expression
  136. //
  137. public virtual bool ContainsEmitWithAwait ()
  138. {
  139. return false;
  140. }
  141. /// <summary>
  142. /// Performs semantic analysis on the Expression
  143. /// </summary>
  144. ///
  145. /// <remarks>
  146. /// The Resolve method is invoked to perform the semantic analysis
  147. /// on the node.
  148. ///
  149. /// The return value is an expression (it can be the
  150. /// same expression in some cases) or a new
  151. /// expression that better represents this node.
  152. ///
  153. /// For example, optimizations of Unary (LiteralInt)
  154. /// would return a new LiteralInt with a negated
  155. /// value.
  156. ///
  157. /// If there is an error during semantic analysis,
  158. /// then an error should be reported (using Report)
  159. /// and a null value should be returned.
  160. ///
  161. /// There are two side effects expected from calling
  162. /// Resolve(): the the field variable "eclass" should
  163. /// be set to any value of the enumeration
  164. /// `ExprClass' and the type variable should be set
  165. /// to a valid type (this is the type of the
  166. /// expression).
  167. /// </remarks>
  168. protected abstract Expression DoResolve (ResolveContext rc);
  169. public virtual Expression DoResolveLValue (ResolveContext rc, Expression right_side)
  170. {
  171. return null;
  172. }
  173. //
  174. // This is used if the expression should be resolved as a type or namespace name.
  175. // the default implementation fails.
  176. //
  177. public virtual TypeSpec ResolveAsType (IMemberContext mc)
  178. {
  179. ResolveContext ec = new ResolveContext (mc);
  180. Expression e = Resolve (ec);
  181. if (e != null)
  182. e.Error_UnexpectedKind (ec, ResolveFlags.Type, loc);
  183. return null;
  184. }
  185. public static void ErrorIsInaccesible (IMemberContext rc, string member, Location loc)
  186. {
  187. rc.Module.Compiler.Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", member);
  188. }
  189. public void Error_ExpressionMustBeConstant (ResolveContext rc, Location loc, string e_name)
  190. {
  191. rc.Report.Error (133, loc, "The expression being assigned to `{0}' must be constant", e_name);
  192. }
  193. public void Error_ConstantCanBeInitializedWithNullOnly (ResolveContext rc, TypeSpec type, Location loc, string name)
  194. {
  195. rc.Report.Error (134, loc, "A constant `{0}' of reference type `{1}' can only be initialized with null",
  196. name, TypeManager.CSharpName (type));
  197. }
  198. public static void Error_InvalidExpressionStatement (Report Report, Location loc)
  199. {
  200. Report.Error (201, loc, "Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement");
  201. }
  202. public void Error_InvalidExpressionStatement (BlockContext ec)
  203. {
  204. Error_InvalidExpressionStatement (ec.Report, loc);
  205. }
  206. public static void Error_VoidInvalidInTheContext (Location loc, Report Report)
  207. {
  208. Report.Error (1547, loc, "Keyword `void' cannot be used in this context");
  209. }
  210. public virtual void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
  211. {
  212. Error_ValueCannotBeConvertedCore (ec, loc, target, expl);
  213. }
  214. protected void Error_ValueCannotBeConvertedCore (ResolveContext ec, Location loc, TypeSpec target, bool expl)
  215. {
  216. // The error was already reported as CS1660
  217. if (type == InternalType.AnonymousMethod || type == InternalType.ErrorType)
  218. return;
  219. string from_type = type.GetSignatureForError ();
  220. string to_type = target.GetSignatureForError ();
  221. if (from_type == to_type) {
  222. from_type = type.GetSignatureForErrorIncludingAssemblyName ();
  223. to_type = target.GetSignatureForErrorIncludingAssemblyName ();
  224. }
  225. if (expl) {
  226. ec.Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
  227. from_type, to_type);
  228. return;
  229. }
  230. ec.Report.DisableReporting ();
  231. bool expl_exists = Convert.ExplicitConversion (ec, this, target, Location.Null) != null;
  232. ec.Report.EnableReporting ();
  233. if (expl_exists) {
  234. ec.Report.Error (266, loc,
  235. "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
  236. from_type, to_type);
  237. } else {
  238. ec.Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'",
  239. from_type, to_type);
  240. }
  241. }
  242. public void Error_TypeArgumentsCannotBeUsed (IMemberContext context, MemberSpec member, int arity, Location loc)
  243. {
  244. // Better message for possible generic expressions
  245. if (member != null && (member.Kind & MemberKind.GenericMask) != 0) {
  246. var report = context.Module.Compiler.Report;
  247. report.SymbolRelatedToPreviousError (member);
  248. if (member is TypeSpec)
  249. member = ((TypeSpec) member).GetDefinition ();
  250. else
  251. member = ((MethodSpec) member).GetGenericMethodDefinition ();
  252. string name = member.Kind == MemberKind.Method ? "method" : "type";
  253. if (member.IsGeneric) {
  254. report.Error (305, loc, "Using the generic {0} `{1}' requires `{2}' type argument(s)",
  255. name, member.GetSignatureForError (), member.Arity.ToString ());
  256. } else {
  257. report.Error (308, loc, "The non-generic {0} `{1}' cannot be used with the type arguments",
  258. name, member.GetSignatureForError ());
  259. }
  260. } else {
  261. Error_TypeArgumentsCannotBeUsed (context, ExprClassName, GetSignatureForError (), loc);
  262. }
  263. }
  264. public void Error_TypeArgumentsCannotBeUsed (IMemberContext context, string exprType, string name, Location loc)
  265. {
  266. context.Module.Compiler.Report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments",
  267. exprType, name);
  268. }
  269. protected virtual void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name)
  270. {
  271. Error_TypeDoesNotContainDefinition (ec, loc, type, name);
  272. }
  273. public static void Error_TypeDoesNotContainDefinition (ResolveContext ec, Location loc, TypeSpec type, string name)
  274. {
  275. ec.Report.SymbolRelatedToPreviousError (type);
  276. ec.Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
  277. TypeManager.CSharpName (type), name);
  278. }
  279. public virtual void Error_ValueAssignment (ResolveContext rc, Expression rhs)
  280. {
  281. if (rhs == EmptyExpression.LValueMemberAccess || rhs == EmptyExpression.LValueMemberOutAccess) {
  282. rc.Report.SymbolRelatedToPreviousError (type);
  283. if (rc.CurrentInitializerVariable != null) {
  284. rc.Report.Error (1918, loc, "Members of value type `{0}' cannot be assigned using a property `{1}' object initializer",
  285. type.GetSignatureForError (), GetSignatureForError ());
  286. } else {
  287. rc.Report.Error (1612, loc, "Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable",
  288. GetSignatureForError ());
  289. }
  290. } else {
  291. rc.Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer");
  292. }
  293. }
  294. protected void Error_VoidPointerOperation (ResolveContext rc)
  295. {
  296. rc.Report.Error (242, loc, "The operation in question is undefined on void pointers");
  297. }
  298. public ResolveFlags ExprClassToResolveFlags {
  299. get {
  300. switch (eclass) {
  301. case ExprClass.Type:
  302. case ExprClass.Namespace:
  303. return ResolveFlags.Type;
  304. case ExprClass.MethodGroup:
  305. return ResolveFlags.MethodGroup;
  306. case ExprClass.TypeParameter:
  307. return ResolveFlags.TypeParameter;
  308. case ExprClass.Value:
  309. case ExprClass.Variable:
  310. case ExprClass.PropertyAccess:
  311. case ExprClass.EventAccess:
  312. case ExprClass.IndexerAccess:
  313. return ResolveFlags.VariableOrValue;
  314. default:
  315. throw new InternalErrorException (loc.ToString () + " " + GetType () + " ExprClass is Invalid after resolve");
  316. }
  317. }
  318. }
  319. public virtual string GetSignatureForError ()
  320. {
  321. return type.GetDefinition ().GetSignatureForError ();
  322. }
  323. /// <summary>
  324. /// Resolves an expression and performs semantic analysis on it.
  325. /// </summary>
  326. ///
  327. /// <remarks>
  328. /// Currently Resolve wraps DoResolve to perform sanity
  329. /// checking and assertion checking on what we expect from Resolve.
  330. /// </remarks>
  331. public Expression Resolve (ResolveContext ec, ResolveFlags flags)
  332. {
  333. if (eclass != ExprClass.Unresolved)
  334. return this;
  335. Expression e;
  336. try {
  337. e = DoResolve (ec);
  338. if (e == null)
  339. return null;
  340. if ((flags & e.ExprClassToResolveFlags) == 0) {
  341. e.Error_UnexpectedKind (ec, flags, loc);
  342. return null;
  343. }
  344. if (e.type == null)
  345. throw new InternalErrorException ("Expression `{0}' didn't set its type in DoResolve", e.GetType ());
  346. return e;
  347. } catch (Exception ex) {
  348. if (loc.IsNull || ec.Module.Compiler.Settings.DebugFlags > 0 || ex is CompletionResult || ec.Report.IsDisabled || ex is FatalException)
  349. throw;
  350. ec.Report.Error (584, loc, "Internal compiler error: {0}", ex.Message);
  351. return ErrorExpression.Instance; // TODO: Add location
  352. }
  353. }
  354. /// <summary>
  355. /// Resolves an expression and performs semantic analysis on it.
  356. /// </summary>
  357. public Expression Resolve (ResolveContext rc)
  358. {
  359. return Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
  360. }
  361. /// <summary>
  362. /// Resolves an expression for LValue assignment
  363. /// </summary>
  364. ///
  365. /// <remarks>
  366. /// Currently ResolveLValue wraps DoResolveLValue to perform sanity
  367. /// checking and assertion checking on what we expect from Resolve
  368. /// </remarks>
  369. public Expression ResolveLValue (ResolveContext ec, Expression right_side)
  370. {
  371. int errors = ec.Report.Errors;
  372. bool out_access = right_side == EmptyExpression.OutAccess;
  373. Expression e = DoResolveLValue (ec, right_side);
  374. if (e != null && out_access && !(e is IMemoryLocation)) {
  375. // FIXME: There's no problem with correctness, the 'Expr = null' handles that.
  376. // Enabling this 'throw' will "only" result in deleting useless code elsewhere,
  377. //throw new InternalErrorException ("ResolveLValue didn't return an IMemoryLocation: " +
  378. // e.GetType () + " " + e.GetSignatureForError ());
  379. e = null;
  380. }
  381. if (e == null) {
  382. if (errors == ec.Report.Errors) {
  383. if (out_access)
  384. ec.Report.Error (1510, loc, "A ref or out argument must be an assignable variable");
  385. else
  386. Error_ValueAssignment (ec, right_side);
  387. }
  388. return null;
  389. }
  390. if (e.eclass == ExprClass.Unresolved)
  391. throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve");
  392. if ((e.type == null) && !(e is GenericTypeExpr))
  393. throw new Exception ("Expression " + e + " did not set its type after Resolve");
  394. return e;
  395. }
  396. public virtual void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
  397. {
  398. rc.Module.Compiler.Report.Error (182, loc,
  399. "An attribute argument must be a constant expression, typeof expression or array creation expression");
  400. }
  401. /// <summary>
  402. /// Emits the code for the expression
  403. /// </summary>
  404. ///
  405. /// <remarks>
  406. /// The Emit method is invoked to generate the code
  407. /// for the expression.
  408. /// </remarks>
  409. public abstract void Emit (EmitContext ec);
  410. // Emit code to branch to @target if this expression is equivalent to @on_true.
  411. // The default implementation is to emit the value, and then emit a brtrue or brfalse.
  412. // Subclasses can provide more efficient implementations, but those MUST be equivalent,
  413. // including the use of conditional branches. Note also that a branch MUST be emitted
  414. public virtual void EmitBranchable (EmitContext ec, Label target, bool on_true)
  415. {
  416. Emit (ec);
  417. ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
  418. }
  419. // Emit this expression for its side effects, not for its value.
  420. // The default implementation is to emit the value, and then throw it away.
  421. // Subclasses can provide more efficient implementations, but those MUST be equivalent
  422. public virtual void EmitSideEffect (EmitContext ec)
  423. {
  424. Emit (ec);
  425. ec.Emit (OpCodes.Pop);
  426. }
  427. //
  428. // Emits the expression into temporary field variable. The method
  429. // should be used for await expressions only
  430. //
  431. public virtual Expression EmitToField (EmitContext ec)
  432. {
  433. //
  434. // This is the await prepare Emit method. When emitting code like
  435. // a + b we emit code like
  436. //
  437. // a.Emit ()
  438. // b.Emit ()
  439. // Opcodes.Add
  440. //
  441. // For await a + await b we have to interfere the flow to keep the
  442. // stack clean because await yields from the expression. The emit
  443. // then changes to
  444. //
  445. // a = a.EmitToField () // a is changed to temporary field access
  446. // b = b.EmitToField ()
  447. // a.Emit ()
  448. // b.Emit ()
  449. // Opcodes.Add
  450. //
  451. //
  452. // The idea is to emit expression and leave the stack empty with
  453. // result value still available.
  454. //
  455. // Expressions should override this default implementation when
  456. // optimized version can be provided (e.g. FieldExpr)
  457. //
  458. //
  459. // We can optimize for side-effect free expressions, they can be
  460. // emitted out of order
  461. //
  462. if (IsSideEffectFree)
  463. return this;
  464. bool needs_temporary = ContainsEmitWithAwait ();
  465. if (!needs_temporary)
  466. ec.EmitThis ();
  467. // Emit original code
  468. var field = EmitToFieldSource (ec);
  469. if (field == null) {
  470. //
  471. // Store the result to temporary field when we
  472. // cannot load `this' directly
  473. //
  474. field = ec.GetTemporaryField (type);
  475. if (needs_temporary) {
  476. //
  477. // Create temporary local (we cannot load `this' before Emit)
  478. //
  479. var temp = ec.GetTemporaryLocal (type);
  480. ec.Emit (OpCodes.Stloc, temp);
  481. ec.EmitThis ();
  482. ec.Emit (OpCodes.Ldloc, temp);
  483. field.EmitAssignFromStack (ec);
  484. ec.FreeTemporaryLocal (temp, type);
  485. } else {
  486. field.EmitAssignFromStack (ec);
  487. }
  488. }
  489. return field;
  490. }
  491. protected virtual FieldExpr EmitToFieldSource (EmitContext ec)
  492. {
  493. //
  494. // Default implementation calls Emit method
  495. //
  496. Emit (ec);
  497. return null;
  498. }
  499. protected static void EmitExpressionsList (EmitContext ec, List<Expression> expressions)
  500. {
  501. if (ec.HasSet (BuilderContext.Options.AsyncBody)) {
  502. bool contains_await = false;
  503. for (int i = 1; i < expressions.Count; ++i) {
  504. if (expressions[i].ContainsEmitWithAwait ()) {
  505. contains_await = true;
  506. break;
  507. }
  508. }
  509. if (contains_await) {
  510. for (int i = 0; i < expressions.Count; ++i) {
  511. expressions[i] = expressions[i].EmitToField (ec);
  512. }
  513. }
  514. }
  515. for (int i = 0; i < expressions.Count; ++i) {
  516. expressions[i].Emit (ec);
  517. }
  518. }
  519. /// <summary>
  520. /// Protected constructor. Only derivate types should
  521. /// be able to be created
  522. /// </summary>
  523. protected Expression ()
  524. {
  525. }
  526. /// <summary>
  527. /// Returns a fully formed expression after a MemberLookup
  528. /// </summary>
  529. ///
  530. static Expression ExprClassFromMemberInfo (MemberSpec spec, Location loc)
  531. {
  532. if (spec is EventSpec)
  533. return new EventExpr ((EventSpec) spec, loc);
  534. if (spec is ConstSpec)
  535. return new ConstantExpr ((ConstSpec) spec, loc);
  536. if (spec is FieldSpec)
  537. return new FieldExpr ((FieldSpec) spec, loc);
  538. if (spec is PropertySpec)
  539. return new PropertyExpr ((PropertySpec) spec, loc);
  540. if (spec is TypeSpec)
  541. return new TypeExpression (((TypeSpec) spec), loc);
  542. return null;
  543. }
  544. public static MethodSpec ConstructorLookup (ResolveContext rc, TypeSpec type, ref Arguments args, Location loc)
  545. {
  546. var ctors = MemberCache.FindMembers (type, Constructor.ConstructorName, true);
  547. if (ctors == null) {
  548. rc.Report.SymbolRelatedToPreviousError (type);
  549. if (type.IsStruct) {
  550. // Report meaningful error for struct as they always have default ctor in C# context
  551. OverloadResolver.Error_ConstructorMismatch (rc, type, args == null ? 0 : args.Count, loc);
  552. } else {
  553. rc.Report.Error (143, loc, "The class `{0}' has no constructors defined",
  554. type.GetSignatureForError ());
  555. }
  556. return null;
  557. }
  558. var r = new OverloadResolver (ctors, OverloadResolver.Restrictions.NoBaseMembers, loc);
  559. if (!rc.HasSet (ResolveContext.Options.BaseInitializer)) {
  560. r.InstanceQualifier = new ConstructorInstanceQualifier (type);
  561. }
  562. return r.ResolveMember<MethodSpec> (rc, ref args);
  563. }
  564. [Flags]
  565. public enum MemberLookupRestrictions
  566. {
  567. None = 0,
  568. InvocableOnly = 1,
  569. ExactArity = 1 << 2,
  570. ReadAccess = 1 << 3
  571. }
  572. //
  573. // Lookup type `queried_type' for code in class `container_type' with a qualifier of
  574. // `qualifier_type' or null to lookup members in the current class.
  575. //
  576. public static Expression MemberLookup (IMemberContext rc, bool errorMode, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc)
  577. {
  578. var members = MemberCache.FindMembers (queried_type, name, false);
  579. if (members == null)
  580. return null;
  581. MemberSpec non_method = null;
  582. MemberSpec ambig_non_method = null;
  583. do {
  584. for (int i = 0; i < members.Count; ++i) {
  585. var member = members[i];
  586. // HACK: for events because +=/-= can appear at same class only, should use OverrideToBase there
  587. if ((member.Modifiers & Modifiers.OVERRIDE) != 0 && member.Kind != MemberKind.Event)
  588. continue;
  589. if ((member.Modifiers & Modifiers.BACKING_FIELD) != 0)
  590. continue;
  591. if ((arity > 0 || (restrictions & MemberLookupRestrictions.ExactArity) != 0) && member.Arity != arity)
  592. continue;
  593. if (!errorMode) {
  594. if (!member.IsAccessible (rc))
  595. continue;
  596. //
  597. // With runtime binder we can have a situation where queried type is inaccessible
  598. // because it came via dynamic object, the check about inconsisted accessibility
  599. // had no effect as the type was unknown during compilation
  600. //
  601. // class A {
  602. // private class N { }
  603. //
  604. // public dynamic Foo ()
  605. // {
  606. // return new N ();
  607. // }
  608. // }
  609. //
  610. if (rc.Module.Compiler.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc))
  611. continue;
  612. }
  613. if ((restrictions & MemberLookupRestrictions.InvocableOnly) != 0) {
  614. if (member is MethodSpec)
  615. return new MethodGroupExpr (members, queried_type, loc);
  616. if (!Invocation.IsMemberInvocable (member))
  617. continue;
  618. }
  619. if (non_method == null || member is MethodSpec || non_method.IsNotCSharpCompatible) {
  620. non_method = member;
  621. } else if (!errorMode && !member.IsNotCSharpCompatible) {
  622. ambig_non_method = member;
  623. }
  624. }
  625. if (non_method != null) {
  626. if (ambig_non_method != null && rc != null) {
  627. var report = rc.Module.Compiler.Report;
  628. report.SymbolRelatedToPreviousError (non_method);
  629. report.SymbolRelatedToPreviousError (ambig_non_method);
  630. report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
  631. non_method.GetSignatureForError (), ambig_non_method.GetSignatureForError ());
  632. }
  633. if (non_method is MethodSpec)
  634. return new MethodGroupExpr (members, queried_type, loc);
  635. return ExprClassFromMemberInfo (non_method, loc);
  636. }
  637. if (members[0].DeclaringType.BaseType == null)
  638. members = null;
  639. else
  640. members = MemberCache.FindMembers (members[0].DeclaringType.BaseType, name, false);
  641. } while (members != null);
  642. return null;
  643. }
  644. protected virtual void Error_NegativeArrayIndex (ResolveContext ec, Location loc)
  645. {
  646. throw new NotImplementedException ();
  647. }
  648. public virtual void Error_OperatorCannotBeApplied (ResolveContext rc, Location loc, string oper, TypeSpec t)
  649. {
  650. if (t == InternalType.ErrorType)
  651. return;
  652. rc.Report.Error (23, loc, "The `{0}' operator cannot be applied to operand of type `{1}'",
  653. oper, t.GetSignatureForError ());
  654. }
  655. protected void Error_PointerInsideExpressionTree (ResolveContext ec)
  656. {
  657. ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
  658. }
  659. /// <summary>
  660. /// Returns an expression that can be used to invoke operator true
  661. /// on the expression if it exists.
  662. /// </summary>
  663. protected static Expression GetOperatorTrue (ResolveContext ec, Expression e, Location loc)
  664. {
  665. return GetOperatorTrueOrFalse (ec, e, true, loc);
  666. }
  667. /// <summary>
  668. /// Returns an expression that can be used to invoke operator false
  669. /// on the expression if it exists.
  670. /// </summary>
  671. protected static Expression GetOperatorFalse (ResolveContext ec, Expression e, Location loc)
  672. {
  673. return GetOperatorTrueOrFalse (ec, e, false, loc);
  674. }
  675. static Expression GetOperatorTrueOrFalse (ResolveContext ec, Expression e, bool is_true, Location loc)
  676. {
  677. var op = is_true ? Operator.OpType.True : Operator.OpType.False;
  678. var methods = MemberCache.GetUserOperator (e.type, op, false);
  679. if (methods == null)
  680. return null;
  681. Arguments arguments = new Arguments (1);
  682. arguments.Add (new Argument (e));
  683. var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc);
  684. var oper = res.ResolveOperator (ec, ref arguments);
  685. if (oper == null)
  686. return null;
  687. return new UserOperatorCall (oper, arguments, null, loc);
  688. }
  689. public virtual string ExprClassName
  690. {
  691. get {
  692. switch (eclass){
  693. case ExprClass.Unresolved:
  694. return "Unresolved";
  695. case ExprClass.Value:
  696. return "value";
  697. case ExprClass.Variable:
  698. return "variable";
  699. case ExprClass.Namespace:
  700. return "namespace";
  701. case ExprClass.Type:
  702. return "type";
  703. case ExprClass.MethodGroup:
  704. return "method group";
  705. case ExprClass.PropertyAccess:
  706. return "property access";
  707. case ExprClass.EventAccess:
  708. return "event access";
  709. case ExprClass.IndexerAccess:
  710. return "indexer access";
  711. case ExprClass.Nothing:
  712. return "null";
  713. case ExprClass.TypeParameter:
  714. return "type parameter";
  715. }
  716. throw new Exception ("Should not happen");
  717. }
  718. }
  719. /// <summary>
  720. /// Reports that we were expecting `expr' to be of class `expected'
  721. /// </summary>
  722. public void Error_UnexpectedKind (IMemberContext ctx, Expression memberExpr, string expected, string was, Location loc)
  723. {
  724. var name = memberExpr.GetSignatureForError ();
  725. ctx.Module.Compiler.Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected", name, was, expected);
  726. }
  727. public virtual void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc)
  728. {
  729. string [] valid = new string [4];
  730. int count = 0;
  731. if ((flags & ResolveFlags.VariableOrValue) != 0) {
  732. valid [count++] = "variable";
  733. valid [count++] = "value";
  734. }
  735. if ((flags & ResolveFlags.Type) != 0)
  736. valid [count++] = "type";
  737. if ((flags & ResolveFlags.MethodGroup) != 0)
  738. valid [count++] = "method group";
  739. if (count == 0)
  740. valid [count++] = "unknown";
  741. StringBuilder sb = new StringBuilder (valid [0]);
  742. for (int i = 1; i < count - 1; i++) {
  743. sb.Append ("', `");
  744. sb.Append (valid [i]);
  745. }
  746. if (count > 1) {
  747. sb.Append ("' or `");
  748. sb.Append (valid [count - 1]);
  749. }
  750. ec.Report.Error (119, loc,
  751. "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ());
  752. }
  753. public static void UnsafeError (ResolveContext ec, Location loc)
  754. {
  755. UnsafeError (ec.Report, loc);
  756. }
  757. public static void UnsafeError (Report Report, Location loc)
  758. {
  759. Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
  760. }
  761. //
  762. // Converts `source' to an int, uint, long or ulong.
  763. //
  764. protected Expression ConvertExpressionToArrayIndex (ResolveContext ec, Expression source)
  765. {
  766. var btypes = ec.BuiltinTypes;
  767. if (source.type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
  768. Arguments args = new Arguments (1);
  769. args.Add (new Argument (source));
  770. return new DynamicConversion (btypes.Int, CSharpBinderFlags.ConvertArrayIndex, args, loc).Resolve (ec);
  771. }
  772. Expression converted;
  773. using (ec.Set (ResolveContext.Options.CheckedScope)) {
  774. converted = Convert.ImplicitConversion (ec, source, btypes.Int, source.loc);
  775. if (converted == null)
  776. converted = Convert.ImplicitConversion (ec, source, btypes.UInt, source.loc);
  777. if (converted == null)
  778. converted = Convert.ImplicitConversion (ec, source, btypes.Long, source.loc);
  779. if (converted == null)
  780. converted = Convert.ImplicitConversion (ec, source, btypes.ULong, source.loc);
  781. if (converted == null) {
  782. source.Error_ValueCannotBeConverted (ec, btypes.Int, false);
  783. return null;
  784. }
  785. }
  786. //
  787. // Only positive constants are allowed at compile time
  788. //
  789. Constant c = converted as Constant;
  790. if (c != null && c.IsNegative)
  791. Error_NegativeArrayIndex (ec, source.loc);
  792. // No conversion needed to array index
  793. if (converted.Type.BuiltinType == BuiltinTypeSpec.Type.Int)
  794. return converted;
  795. return new ArrayIndexCast (converted, btypes.Int).Resolve (ec);
  796. }
  797. //
  798. // Derived classes implement this method by cloning the fields that
  799. // could become altered during the Resolve stage
  800. //
  801. // Only expressions that are created for the parser need to implement
  802. // this.
  803. //
  804. protected virtual void CloneTo (CloneContext clonectx, Expression target)
  805. {
  806. throw new NotImplementedException (
  807. String.Format (
  808. "CloneTo not implemented for expression {0}", this.GetType ()));
  809. }
  810. //
  811. // Clones an expression created by the parser.
  812. //
  813. // We only support expressions created by the parser so far, not
  814. // expressions that have been resolved (many more classes would need
  815. // to implement CloneTo).
  816. //
  817. // This infrastructure is here merely for Lambda expressions which
  818. // compile the same code using different type values for the same
  819. // arguments to find the correct overload
  820. //
  821. public virtual Expression Clone (CloneContext clonectx)
  822. {
  823. Expression cloned = (Expression) MemberwiseClone ();
  824. CloneTo (clonectx, cloned);
  825. return cloned;
  826. }
  827. //
  828. // Implementation of expression to expression tree conversion
  829. //
  830. public abstract Expression CreateExpressionTree (ResolveContext ec);
  831. protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, Arguments args)
  832. {
  833. return CreateExpressionFactoryCall (ec, name, null, args, loc);
  834. }
  835. protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args)
  836. {
  837. return CreateExpressionFactoryCall (ec, name, typeArguments, args, loc);
  838. }
  839. public static Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args, Location loc)
  840. {
  841. return new Invocation (new MemberAccess (CreateExpressionTypeExpression (ec, loc), name, typeArguments, loc), args);
  842. }
  843. protected static TypeExpr CreateExpressionTypeExpression (ResolveContext ec, Location loc)
  844. {
  845. var t = ec.Module.PredefinedTypes.Expression.Resolve ();
  846. if (t == null)
  847. return null;
  848. return new TypeExpression (t, loc);
  849. }
  850. //
  851. // Implemented by all expressions which support conversion from
  852. // compiler expression to invokable runtime expression. Used by
  853. // dynamic C# binder.
  854. //
  855. public virtual SLE.Expression MakeExpression (BuilderContext ctx)
  856. {
  857. throw new NotImplementedException ("MakeExpression for " + GetType ());
  858. }
  859. public virtual object Accept (StructuralVisitor visitor)
  860. {
  861. return visitor.Visit (this);
  862. }
  863. }
  864. /// <summary>
  865. /// This is just a base class for expressions that can
  866. /// appear on statements (invocations, object creation,
  867. /// assignments, post/pre increment and decrement). The idea
  868. /// being that they would support an extra Emition interface that
  869. /// does not leave a result on the stack.
  870. /// </summary>
  871. public abstract class ExpressionStatement : Expression {
  872. public ExpressionStatement ResolveStatement (BlockContext ec)
  873. {
  874. Expression e = Resolve (ec);
  875. if (e == null)
  876. return null;
  877. ExpressionStatement es = e as ExpressionStatement;
  878. if (es == null)
  879. Error_InvalidExpressionStatement (ec);
  880. if (ec.CurrentAnonymousMethod is AsyncInitializer && !(e is Assign) &&
  881. (e.Type.IsGenericTask || e.Type == ec.Module.PredefinedTypes.Task.TypeSpec)) {
  882. ec.Report.Warning (4014, 1, e.Location,
  883. "The statement is not awaited and execution of current method continues before the call is completed. Consider using `await' operator");
  884. }
  885. return es;
  886. }
  887. /// <summary>
  888. /// Requests the expression to be emitted in a `statement'
  889. /// context. This means that no new value is left on the
  890. /// stack after invoking this method (constrasted with
  891. /// Emit that will always leave a value on the stack).
  892. /// </summary>
  893. public abstract void EmitStatement (EmitContext ec);
  894. public override void EmitSideEffect (EmitContext ec)
  895. {
  896. EmitStatement (ec);
  897. }
  898. }
  899. /// <summary>
  900. /// This kind of cast is used to encapsulate the child
  901. /// whose type is child.Type into an expression that is
  902. /// reported to return "return_type". This is used to encapsulate
  903. /// expressions which have compatible types, but need to be dealt
  904. /// at higher levels with.
  905. ///
  906. /// For example, a "byte" expression could be encapsulated in one
  907. /// of these as an "unsigned int". The type for the expression
  908. /// would be "unsigned int".
  909. ///
  910. /// </summary>
  911. public abstract class TypeCast : Expression
  912. {
  913. protected readonly Expression child;
  914. protected TypeCast (Expression child, TypeSpec return_type)
  915. {
  916. eclass = child.eclass;
  917. loc = child.Location;
  918. type = return_type;
  919. this.child = child;
  920. }
  921. public Expression Child {
  922. get {
  923. return child;
  924. }
  925. }
  926. public override bool ContainsEmitWithAwait ()
  927. {
  928. return child.ContainsEmitWithAwait ();
  929. }
  930. public override Expression CreateExpressionTree (ResolveContext ec)
  931. {
  932. Arguments args = new Arguments (2);
  933. args.Add (new Argument (child.CreateExpressionTree (ec)));
  934. args.Add (new Argument (new TypeOf (type, loc)));
  935. if (type.IsPointer || child.Type.IsPointer)
  936. Error_PointerInsideExpressionTree (ec);
  937. return CreateExpressionFactoryCall (ec, ec.HasSet (ResolveContext.Options.CheckedScope) ? "ConvertChecked" : "Convert", args);
  938. }
  939. protected override Expression DoResolve (ResolveContext ec)
  940. {
  941. // This should never be invoked, we are born in fully
  942. // initialized state.
  943. return this;
  944. }
  945. public override void Emit (EmitContext ec)
  946. {
  947. child.Emit (ec);
  948. }
  949. public override SLE.Expression MakeExpression (BuilderContext ctx)
  950. {
  951. #if STATIC
  952. return base.MakeExpression (ctx);
  953. #else
  954. return ctx.HasSet (BuilderContext.Options.CheckedScope) ?
  955. SLE.Expression.ConvertChecked (child.MakeExpression (ctx), type.GetMetaInfo ()) :
  956. SLE.Expression.Convert (child.MakeExpression (ctx), type.GetMetaInfo ());
  957. #endif
  958. }
  959. protected override void CloneTo (CloneContext clonectx, Expression t)
  960. {
  961. // Nothing to clone
  962. }
  963. public override bool IsNull {
  964. get { return child.IsNull; }
  965. }
  966. }
  967. public class EmptyCast : TypeCast {
  968. EmptyCast (Expression child, TypeSpec target_type)
  969. : base (child, target_type)
  970. {
  971. }
  972. public static Expression Create (Expression child, TypeSpec type)
  973. {
  974. Constant c = child as Constant;
  975. if (c != null)
  976. return new EmptyConstantCast (c, type);
  977. EmptyCast e = child as EmptyCast;
  978. if (e != null)
  979. return new EmptyCast (e.child, type);
  980. return new EmptyCast (child, type);
  981. }
  982. public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
  983. {
  984. child.EmitBranchable (ec, label, on_true);
  985. }
  986. public override void EmitSideEffect (EmitContext ec)
  987. {
  988. child.EmitSideEffect (ec);
  989. }
  990. }
  991. //
  992. // Used for predefined type user operator (no obsolete check, etc.)
  993. //
  994. public class OperatorCast : TypeCast
  995. {
  996. readonly MethodSpec conversion_operator;
  997. public OperatorCast (Expression expr, TypeSpec target_type)
  998. : this (expr, target_type, target_type, false)
  999. {
  1000. }
  1001. public OperatorCast (Expression expr, TypeSpec target_type, bool find_explicit)
  1002. : this (expr, target_type, target_type, find_explicit)
  1003. {
  1004. }
  1005. public OperatorCast (Expression expr, TypeSpec declaringType, TypeSpec returnType, bool isExplicit)
  1006. : base (expr, returnType)
  1007. {
  1008. var op = isExplicit ? Operator.OpType.Explicit : Operator.OpType.Implicit;
  1009. var mi = MemberCache.GetUserOperator (declaringType, op, true);
  1010. if (mi != null) {
  1011. foreach (MethodSpec oper in mi) {
  1012. if (oper.ReturnType != returnType)
  1013. continue;
  1014. if (oper.Parameters.Types[0] == expr.Type) {
  1015. conversion_operator = oper;
  1016. return;
  1017. }
  1018. }
  1019. }
  1020. throw new InternalErrorException ("Missing predefined user operator between `{0}' and `{1}'",
  1021. returnType.GetSignatureForError (), expr.Type.GetSignatureForError ());
  1022. }
  1023. public override void Emit (EmitContext ec)
  1024. {
  1025. child.Emit (ec);
  1026. ec.Emit (OpCodes.Call, conversion_operator);
  1027. }
  1028. }
  1029. //
  1030. // Constant specialization of EmptyCast.
  1031. // We need to special case this since an empty cast of
  1032. // a constant is still a constant.
  1033. //
  1034. public class EmptyConstantCast : Constant
  1035. {
  1036. public readonly Constant child;
  1037. public EmptyConstantCast (Constant child, TypeSpec type)
  1038. : base (child.Location)
  1039. {
  1040. if (child == null)
  1041. throw new ArgumentNullException ("child");
  1042. this.child = child;
  1043. this.eclass = child.eclass;
  1044. this.type = type;
  1045. }
  1046. public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
  1047. {
  1048. if (child.Type == target_type)
  1049. return child;
  1050. // FIXME: check that 'type' can be converted to 'target_type' first
  1051. return child.ConvertExplicitly (in_checked_context, target_type);
  1052. }
  1053. public override Expression CreateExpressionTree (ResolveContext ec)
  1054. {
  1055. Arguments args = Arguments.CreateForExpressionTree (ec, null,
  1056. child.CreateExpressionTree (ec),
  1057. new TypeOf (type, loc));
  1058. if (type.IsPointer)
  1059. Error_PointerInsideExpressionTree (ec);
  1060. return CreateExpressionFactoryCall (ec, "Convert", args);
  1061. }
  1062. public override bool IsDefaultValue {
  1063. get { return child.IsDefaultValue; }
  1064. }
  1065. public override bool IsNegative {
  1066. get { return child.IsNegative; }
  1067. }
  1068. public override bool IsNull {
  1069. get { return child.IsNull; }
  1070. }
  1071. public override bool IsOneInteger {
  1072. get { return child.IsOneInteger; }
  1073. }
  1074. public override bool IsSideEffectFree {
  1075. get {
  1076. return child.IsSideEffectFree;
  1077. }
  1078. }
  1079. public override bool IsZeroInteger {
  1080. get { return child.IsZeroInteger; }
  1081. }
  1082. public override void Emit (EmitContext ec)
  1083. {
  1084. child.Emit (ec);
  1085. }
  1086. public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
  1087. {
  1088. child.EmitBranchable (ec, label, on_true);
  1089. // Only to make verifier happy
  1090. if (TypeManager.IsGenericParameter (type) && child.IsNull)
  1091. ec.Emit (OpCodes.Unbox_Any, type);
  1092. }
  1093. public override void EmitSideEffect (EmitContext ec)
  1094. {
  1095. child.EmitSideEffect (ec);
  1096. }
  1097. public override object GetValue ()
  1098. {
  1099. return child.GetValue ();
  1100. }
  1101. public override string GetValueAsLiteral ()
  1102. {
  1103. return child.GetValueAsLiteral ();
  1104. }
  1105. public override long GetValueAsLong ()
  1106. {
  1107. return child.GetValueAsLong ();
  1108. }
  1109. public override Constant ConvertImplicitly (TypeSpec target_type)
  1110. {
  1111. if (type == target_type)
  1112. return this;
  1113. // FIXME: Do we need to check user conversions?
  1114. if (!Convert.ImplicitStandardConversionExists (this, target_type))
  1115. return null;
  1116. return child.ConvertImplicitly (target_type);
  1117. }
  1118. }
  1119. /// <summary>
  1120. /// This class is used to wrap literals which belong inside Enums
  1121. /// </summary>
  1122. public class EnumConstant : Constant
  1123. {
  1124. public Constant Child;
  1125. public EnumConstant (Constant child, TypeSpec enum_type)
  1126. : base (child.Location)
  1127. {
  1128. this.Child = child;
  1129. this.eclass = ExprClass.Value;
  1130. this.type = enum_type;
  1131. }
  1132. protected EnumConstant (Location loc)
  1133. : base (loc)
  1134. {
  1135. }
  1136. public override void Emit (EmitContext ec)
  1137. {
  1138. Child.Emit (ec);
  1139. }
  1140. public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
  1141. {
  1142. Child.EncodeAttributeValue (rc, enc, Child.Type);
  1143. }
  1144. public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
  1145. {
  1146. Child.EmitBranchable (ec, label, on_true);
  1147. }
  1148. public override void EmitSideEffect (EmitContext ec)
  1149. {
  1150. Child.EmitSideEffect (ec);
  1151. }
  1152. public override string GetSignatureForError()
  1153. {
  1154. return TypeManager.CSharpName (Type);
  1155. }
  1156. public override object GetValue ()
  1157. {
  1158. return Child.GetValue ();
  1159. }
  1160. #if !STATIC
  1161. public override object GetTypedValue ()
  1162. {
  1163. //
  1164. // The method can be used in dynamic context only (on closed types)
  1165. //
  1166. // System.Enum.ToObject cannot be called on dynamic types
  1167. // EnumBuilder has to be used, but we cannot use EnumBuilder
  1168. // because it does not properly support generics
  1169. //
  1170. return System.Enum.ToObject (type.GetMetaInfo (), Child.GetValue ());
  1171. }
  1172. #endif
  1173. public override string GetValueAsLiteral ()
  1174. {
  1175. return Child.GetValueAsLiteral ();
  1176. }
  1177. public override long GetValueAsLong ()
  1178. {
  1179. return Child.GetValueAsLong ();
  1180. }
  1181. public EnumConstant Increment()
  1182. {
  1183. return new EnumConstant (((IntegralConstant) Child).Increment (), type);
  1184. }
  1185. public override bool IsDefaultValue {
  1186. get {
  1187. return Child.IsDefaultValue;
  1188. }
  1189. }
  1190. public override bool IsSideEffectFree {
  1191. get {
  1192. return Child.IsSideEffectFree;
  1193. }
  1194. }
  1195. public override bool IsZeroInteger {
  1196. get { return Child.IsZeroInteger; }
  1197. }
  1198. public override bool IsNegative {
  1199. get {
  1200. return Child.IsNegative;
  1201. }
  1202. }
  1203. public override Constant ConvertExplicitly(bool in_checked_context, TypeSpec target_type)
  1204. {
  1205. if (Child.Type == target_type)
  1206. return Child;
  1207. return Child.ConvertExplicitly (in_checked_context, target_type);
  1208. }
  1209. public override Constant ConvertImplicitly (TypeSpec type)
  1210. {
  1211. if (this.type == type) {
  1212. return this;
  1213. }
  1214. if (!Convert.ImplicitStandardConversionExists (this, type)){
  1215. return null;
  1216. }
  1217. return Child.ConvertImplicitly (type);
  1218. }
  1219. }
  1220. /// <summary>
  1221. /// This kind of cast is used to encapsulate Value Types in objects.
  1222. ///
  1223. /// The effect of it is to box the value type emitted by the previous
  1224. /// operation.
  1225. /// </summary>
  1226. public class BoxedCast : TypeCast {
  1227. public BoxedCast (Expression expr, TypeSpec target_type)
  1228. : base (expr, target_type)
  1229. {
  1230. eclass = ExprClass.Value;
  1231. }
  1232. protected override Expression DoResolve (ResolveContext ec)
  1233. {
  1234. // This should never be invoked, we are born in fully
  1235. // initialized state.
  1236. return this;
  1237. }
  1238. public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
  1239. {
  1240. // Only boxing to object type is supported
  1241. if (targetType.BuiltinType != BuiltinTypeSpec.Type.Object) {
  1242. base.EncodeAttributeValue (rc, enc, targetType);
  1243. return;
  1244. }
  1245. enc.Encode (child.Type);
  1246. child.EncodeAttributeValue (rc, enc, child.Type);
  1247. }
  1248. public override void Emit (EmitContext ec)
  1249. {
  1250. base.Emit (ec);
  1251. ec.Emit (OpCodes.Box, child.Type);
  1252. }
  1253. public override void EmitSideEffect (EmitContext ec)
  1254. {
  1255. // boxing is side-effectful, since it involves runtime checks, except when boxing to Object or ValueType
  1256. // so, we need to emit the box+pop instructions in most cases
  1257. if (child.Type.IsStruct &&
  1258. (type.BuiltinType == BuiltinTypeSpec.Type.Object || type.BuiltinType == BuiltinTypeSpec.Type.ValueType))
  1259. child.EmitSideEffect (ec);
  1260. else
  1261. base.EmitSideEffect (ec);
  1262. }
  1263. }
  1264. public class UnboxCast : TypeCast {
  1265. public UnboxCast (Expression expr, TypeSpec return_type)
  1266. : base (expr, return_type)
  1267. {
  1268. }
  1269. protected override Expression DoResolve (ResolveContext ec)
  1270. {
  1271. // This should never be invoked, we are born in fully
  1272. // initialized state.
  1273. return this;
  1274. }
  1275. public override void Emit (EmitContext ec)
  1276. {
  1277. base.Emit (ec);
  1278. ec.Emit (OpCodes.Unbox_Any, type);
  1279. }
  1280. }
  1281. /// <summary>
  1282. /// This is used to perform explicit numeric conversions.
  1283. ///
  1284. /// Explicit numeric conversions might trigger exceptions in a checked
  1285. /// context, so they should generate the conv.ovf opcodes instead of
  1286. /// conv opcodes.
  1287. /// </summary>
  1288. public class ConvCast : TypeCast {
  1289. public enum Mode : byte {
  1290. I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
  1291. U1_I1, U1_CH,
  1292. I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
  1293. U2_I1, U2_U1, U2_I2, U2_CH,
  1294. I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
  1295. U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
  1296. I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH, I8_I,
  1297. U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH, U8_I,
  1298. CH_I1, CH_U1, CH_I2,
  1299. R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
  1300. R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4,
  1301. I_I8,
  1302. }
  1303. Mode mode;
  1304. public ConvCast (Expression child, TypeSpec return_type, Mode m)
  1305. : base (child, return_type)
  1306. {
  1307. mode = m;
  1308. }
  1309. protected override Expression DoResolve (ResolveContext ec)
  1310. {
  1311. // This should never be invoked, we are born in fully
  1312. // initialized state.
  1313. return this;
  1314. }
  1315. public override string ToString ()
  1316. {
  1317. return String.Format ("ConvCast ({0}, {1})", mode, child);
  1318. }
  1319. public override void Emit (EmitContext ec)
  1320. {
  1321. base.Emit (ec);
  1322. if (ec.HasSet (EmitContext.Options.CheckedScope)) {
  1323. switch (mode){
  1324. case Mode.I1_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
  1325. case Mode.I1_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
  1326. case Mode.I1_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
  1327. case Mode.I1_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
  1328. case Mode.I1_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
  1329. case Mode.U1_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
  1330. case Mode.U1_CH: /* nothing */ break;
  1331. case Mode.I2_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
  1332. case Mode.I2_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
  1333. case Mode.I2_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
  1334. case Mode.I2_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
  1335. case Mode.I2_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
  1336. case Mode.I2_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
  1337. case Mode.U2_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
  1338. case Mode.U2_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break;
  1339. case Mode.U2_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break;
  1340. case Mode.U2_CH: /* nothing */ break;
  1341. case Mode.I4_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
  1342. case Mode.I4_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
  1343. case Mode.I4_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break;
  1344. case Mode.I4_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
  1345. case Mode.I4_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
  1346. case Mode.I4_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
  1347. case Mode.I4_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
  1348. case Mode.U4_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
  1349. case Mode.U4_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break;
  1350. case Mode.U4_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break;
  1351. case Mode.U4_U2: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break;
  1352. case Mode.U4_I4: ec.Emit (OpCodes.Conv_Ovf_I4_Un); break;
  1353. case Mode.U4_CH: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break;
  1354. case Mode.I8_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
  1355. case Mode.I8_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
  1356. case Mode.I8_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break;
  1357. case Mode.I8_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
  1358. case Mode.I8_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break;
  1359. case Mode.I8_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
  1360. case Mode.I8_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
  1361. case Mode.I8_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
  1362. case Mode.I8_I: ec.Emit (OpCodes.Conv_Ovf_U); break;
  1363. case Mode.U8_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
  1364. case Mode.U8_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break;
  1365. case Mode.U8_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break;
  1366. case Mode.U8_U2: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break;
  1367. case Mode.U8_I4: ec.Emit (OpCodes.Conv_Ovf_I4_Un); break;
  1368. case Mode.U8_U4: ec.Emit (OpCodes.Conv_Ovf_U4_Un); break;
  1369. case Mode.U8_I8: ec.Emit (OpCodes.Conv_Ovf_I8_Un); break;
  1370. case Mode.U8_CH: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break;
  1371. case Mode.U8_I: ec.Emit (OpCodes.Conv_Ovf_U_Un); break;
  1372. case Mode.CH_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
  1373. case Mode.CH_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break;
  1374. case Mode.CH_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break;
  1375. case Mode.R4_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
  1376. case Mode.R4_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
  1377. case Mode.R4_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break;
  1378. case Mode.R4_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
  1379. case Mode.R4_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break;
  1380. case Mode.R4_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
  1381. case Mode.R4_I8: ec.Emit (OpCodes.Conv_Ovf_I8); break;
  1382. case Mode.R4_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
  1383. case Mode.R4_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
  1384. case Mode.R8_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
  1385. case Mode.R8_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
  1386. case Mode.R8_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break;
  1387. case Mode.R8_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
  1388. case Mode.R8_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break;
  1389. case Mode.R8_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
  1390. case Mode.R8_I8: ec.Emit (OpCodes.Conv_Ovf_I8); break;
  1391. case Mode.R8_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
  1392. case Mode.R8_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
  1393. case Mode.R8_R4: ec.Emit (OpCodes.Conv_R4); break;
  1394. case Mode.I_I8: ec.Emit (OpCodes.Conv_Ovf_I8_Un); break;
  1395. }
  1396. } else {
  1397. switch (mode){
  1398. case Mode.I1_U1: ec.Emit (OpCodes.Conv_U1); break;
  1399. case Mode.I1_U2: ec.Emit (OpCodes.Conv_U2); break;
  1400. case Mode.I1_U4: ec.Emit (OpCodes.Conv_U4); break;
  1401. case Mode.I1_U8: ec.Emit (OpCodes.Conv_I8); break;
  1402. case Mode.I1_CH: ec.Emit (OpCodes.Conv_U2); break;
  1403. case Mode.U1_I1: ec.Emit (OpCodes.Conv_I1); break;
  1404. case Mode.U1_CH: ec.Emit (OpCodes.Conv_U2); break;
  1405. case Mode.I2_I1: ec.Emit (OpCodes.Conv_I1); break;
  1406. case Mode.I2_U1: ec.Emit (OpCodes.Conv_U1); break;
  1407. case Mode.I2_U2: ec.Emit (OpCodes.Conv_U2); break;
  1408. case Mode.I2_U4: ec.Emit (OpCodes.Conv_U4); break;
  1409. case Mode.I2_U8: ec.Emit (OpCodes.Conv_I8); break;
  1410. case Mode.I2_CH: ec.Emit (OpCodes.Conv_U2); break;
  1411. case Mode.U2_I1: ec.Emit (OpCodes.Conv_I1); break;
  1412. case Mode.U2_U1: ec.Emit (OpCodes.Conv_U1); break;
  1413. case Mode.U2_I2: ec.Emit (OpCodes.Conv_I2); break;
  1414. case Mode.U2_CH: /* nothing */ break;
  1415. case Mode.I4_I1: ec.Emit (OpCodes.Conv_I1); break;
  1416. case Mode.I4_U1: ec.Emit (OpCodes.Conv_U1); break;
  1417. case Mode.I4_I2: ec.Emit (OpCodes.Conv_I2); break;

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