PageRenderTime 127ms CodeModel.GetById 22ms app.highlight 81ms RepoModel.GetById 1ms app.codeStats 2ms

/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs

http://github.com/icsharpcode/ILSpy
C# | 7426 lines | 5229 code | 1239 blank | 958 comment | 1580 complexity | 88c35216da27541d98926645c583efa9 MD5 | raw file

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@gmail.com)
   7//
   8// Copyright 2001, 2002, 2003 Ximian, Inc.
   9// Copyright 2003-2008 Novell, Inc.
  10// Copyright 2011-2012 Xamarin Inc.
  11//
  12//
  13
  14using System;
  15using System.Collections.Generic;
  16using System.Text;
  17using SLE = System.Linq.Expressions;
  18using System.Linq;
  19
  20#if STATIC
  21using IKVM.Reflection;
  22using IKVM.Reflection.Emit;
  23#else
  24using System.Reflection;
  25using System.Reflection.Emit;
  26#endif
  27
  28namespace Mono.CSharp {
  29
  30	/// <remarks>
  31	///   The ExprClass class contains the is used to pass the 
  32	///   classification of an expression (value, variable, namespace,
  33	///   type, method group, property access, event access, indexer access,
  34	///   nothing).
  35	/// </remarks>
  36	public enum ExprClass : byte {
  37		Unresolved	= 0,
  38		
  39		Value,
  40		Variable,
  41		Namespace,
  42		Type,
  43		TypeParameter,
  44		MethodGroup,
  45		PropertyAccess,
  46		EventAccess,
  47		IndexerAccess,
  48		Nothing, 
  49	}
  50
  51	/// <remarks>
  52	///   This is used to tell Resolve in which types of expressions we're
  53	///   interested.
  54	/// </remarks>
  55	[Flags]
  56	public enum ResolveFlags {
  57		// Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess.
  58		VariableOrValue		= 1,
  59
  60		// Returns a type expression.
  61		Type			= 1 << 1,
  62
  63		// Returns a method group.
  64		MethodGroup		= 1 << 2,
  65
  66		TypeParameter	= 1 << 3,
  67
  68		// Mask of all the expression class flags.
  69		MaskExprClass = VariableOrValue | Type | MethodGroup | TypeParameter,
  70	}
  71
  72	//
  73	// This is just as a hint to AddressOf of what will be done with the
  74	// address.
  75	[Flags]
  76	public enum AddressOp {
  77		Store = 1,
  78		Load  = 2,
  79		LoadStore = 3
  80	};
  81	
  82	/// <summary>
  83	///   This interface is implemented by variables
  84	/// </summary>
  85	public interface IMemoryLocation {
  86		/// <summary>
  87		///   The AddressOf method should generate code that loads
  88		///   the address of the object and leaves it on the stack.
  89		///
  90		///   The `mode' argument is used to notify the expression
  91		///   of whether this will be used to read from the address or
  92		///   write to the address.
  93		///
  94		///   This is just a hint that can be used to provide good error
  95		///   reporting, and should have no other side effects. 
  96		/// </summary>
  97		void AddressOf (EmitContext ec, AddressOp mode);
  98	}
  99
 100	//
 101	// An expressions resolved as a direct variable reference
 102	//
 103	public interface IVariableReference : IFixedExpression
 104	{
 105		bool IsHoisted { get; }
 106		string Name { get; }
 107		VariableInfo VariableInfo { get; }
 108
 109		void SetHasAddressTaken ();
 110	}
 111
 112	//
 113	// Implemented by an expression which could be or is always
 114	// fixed
 115	//
 116	public interface IFixedExpression
 117	{
 118		bool IsFixed { get; }
 119	}
 120
 121	public interface IExpressionCleanup
 122	{
 123		void EmitCleanup (EmitContext ec);
 124	}
 125
 126	/// <remarks>
 127	///   Base class for expressions
 128	/// </remarks>
 129	public abstract class Expression {
 130		public ExprClass eclass;
 131		protected TypeSpec type;
 132		protected Location loc;
 133		
 134		public TypeSpec Type {
 135			get { return type; }
 136			set { type = value; }
 137		}
 138
 139		public virtual bool IsSideEffectFree {
 140			get {
 141				return false;
 142			}
 143		}
 144
 145		public Location Location {
 146			get { return loc; }
 147		}
 148
 149		public virtual bool IsNull {
 150			get {
 151				return false;
 152			}
 153		}
 154
 155		//
 156		// Used to workaround parser limitation where we cannot get
 157		// start of statement expression location
 158		//
 159		public virtual Location StartLocation {
 160			get {
 161				return loc;
 162			}
 163		}
 164
 165		public virtual MethodGroupExpr CanReduceLambda (AnonymousMethodBody body)
 166		{
 167			//
 168			// Return method-group expression when the expression can be used as
 169			// lambda replacement. A good example is array sorting where instead of
 170			// code like
 171			//
 172			//  Array.Sort (s, (a, b) => String.Compare (a, b));
 173			//
 174			// we can use method group directly
 175			//
 176			//  Array.Sort (s, String.Compare);
 177			//
 178			// Correct overload will be used because we do the reduction after
 179			// best candidate was found.
 180			//
 181			return null;
 182		}
 183
 184		//
 185		// Returns true when the expression during Emit phase breaks stack
 186		// by using await expression
 187		//
 188		public virtual bool ContainsEmitWithAwait ()
 189		{
 190			return false;
 191		}
 192
 193		/// <summary>
 194		///   Performs semantic analysis on the Expression
 195		/// </summary>
 196		///
 197		/// <remarks>
 198		///   The Resolve method is invoked to perform the semantic analysis
 199		///   on the node.
 200		///
 201		///   The return value is an expression (it can be the
 202		///   same expression in some cases) or a new
 203		///   expression that better represents this node.
 204		///   
 205		///   For example, optimizations of Unary (LiteralInt)
 206		///   would return a new LiteralInt with a negated
 207		///   value.
 208		///   
 209		///   If there is an error during semantic analysis,
 210		///   then an error should be reported (using Report)
 211		///   and a null value should be returned.
 212		///   
 213		///   There are two side effects expected from calling
 214		///   Resolve(): the the field variable "eclass" should
 215		///   be set to any value of the enumeration
 216		///   `ExprClass' and the type variable should be set
 217		///   to a valid type (this is the type of the
 218		///   expression).
 219		/// </remarks>
 220		protected abstract Expression DoResolve (ResolveContext rc);
 221
 222		public virtual Expression DoResolveLValue (ResolveContext rc, Expression right_side)
 223		{
 224			return null;
 225		}
 226
 227		//
 228		// This is used if the expression should be resolved as a type or namespace name.
 229		// the default implementation fails.   
 230		//
 231		public virtual TypeSpec ResolveAsType (IMemberContext mc, bool allowUnboundTypeArguments = false)
 232		{
 233			ResolveContext ec = new ResolveContext (mc);
 234			Expression e = Resolve (ec);
 235			if (e != null)
 236				e.Error_UnexpectedKind (ec, ResolveFlags.Type, loc);
 237
 238			return null;
 239		}
 240
 241		public static void ErrorIsInaccesible (IMemberContext rc, string member, Location loc)
 242		{
 243			rc.Module.Compiler.Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", member);
 244		}
 245
 246		public void Error_ExpressionMustBeConstant (ResolveContext rc, Location loc, string e_name)
 247		{
 248			rc.Report.Error (133, loc, "The expression being assigned to `{0}' must be constant", e_name);
 249		}
 250
 251		public void Error_ConstantCanBeInitializedWithNullOnly (ResolveContext rc, TypeSpec type, Location loc, string name)
 252		{
 253			rc.Report.Error (134, loc, "A constant `{0}' of reference type `{1}' can only be initialized with null",
 254				name, type.GetSignatureForError ());
 255		}
 256
 257		protected virtual void Error_InvalidExpressionStatement (Report report, Location loc)
 258		{
 259			report.Error (201, loc, "Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement");
 260		}
 261		
 262		public void Error_InvalidExpressionStatement (BlockContext bc)
 263		{
 264			Error_InvalidExpressionStatement (bc.Report, loc);
 265		}
 266
 267		public void Error_InvalidExpressionStatement (Report report)
 268		{
 269			Error_InvalidExpressionStatement (report, loc);
 270		}
 271
 272		public static void Error_VoidInvalidInTheContext (Location loc, Report Report)
 273		{
 274			Report.Error (1547, loc, "Keyword `void' cannot be used in this context");
 275		}
 276
 277		public virtual void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
 278		{
 279			Error_ValueCannotBeConvertedCore (ec, loc, target, expl);
 280		}
 281
 282		protected void Error_ValueCannotBeConvertedCore (ResolveContext ec, Location loc, TypeSpec target, bool expl)
 283		{
 284			// The error was already reported as CS1660
 285			if (type == InternalType.AnonymousMethod)
 286				return;
 287
 288			if (type == InternalType.ErrorType || target == InternalType.ErrorType)
 289				return;
 290
 291			string from_type = type.GetSignatureForError ();
 292			string to_type = target.GetSignatureForError ();
 293			if (from_type == to_type) {
 294				from_type = type.GetSignatureForErrorIncludingAssemblyName ();
 295				to_type = target.GetSignatureForErrorIncludingAssemblyName ();
 296			}
 297
 298			if (expl) {
 299				ec.Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
 300					from_type, to_type);
 301				return;
 302			}
 303
 304			ec.Report.DisableReporting ();
 305			bool expl_exists = Convert.ExplicitConversion (ec, this, target, Location.Null) != null;
 306			ec.Report.EnableReporting ();
 307
 308			if (expl_exists) {
 309				ec.Report.Error (266, loc,
 310					"Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
 311					from_type, to_type);
 312			} else {
 313				ec.Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'",
 314					from_type, to_type);
 315			}
 316		}
 317
 318		public void Error_TypeArgumentsCannotBeUsed (IMemberContext context, MemberSpec member, Location loc)
 319		{
 320			// Better message for possible generic expressions
 321			if (member != null && (member.Kind & MemberKind.GenericMask) != 0) {
 322				var report = context.Module.Compiler.Report;
 323				report.SymbolRelatedToPreviousError (member);
 324				if (member is TypeSpec)
 325					member = ((TypeSpec) member).GetDefinition ();
 326				else
 327					member = ((MethodSpec) member).GetGenericMethodDefinition ();
 328
 329				string name = member.Kind == MemberKind.Method ? "method" : "type";
 330				if (member.IsGeneric) {
 331					report.Error (305, loc, "Using the generic {0} `{1}' requires `{2}' type argument(s)",
 332						name, member.GetSignatureForError (), member.Arity.ToString ());
 333				} else {
 334					report.Error (308, loc, "The non-generic {0} `{1}' cannot be used with the type arguments",
 335						name, member.GetSignatureForError ());
 336				}
 337			} else {
 338				Error_TypeArgumentsCannotBeUsed (context, ExprClassName, GetSignatureForError (), loc);
 339			}
 340		}
 341
 342		public static void Error_TypeArgumentsCannotBeUsed (IMemberContext context, string exprType, string name, Location loc)
 343		{
 344			context.Module.Compiler.Report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments",
 345				exprType, name);
 346		}
 347
 348		protected virtual void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name)
 349		{
 350			Error_TypeDoesNotContainDefinition (ec, loc, type, name);
 351		}
 352
 353		public static void Error_TypeDoesNotContainDefinition (ResolveContext ec, Location loc, TypeSpec type, string name)
 354		{
 355			ec.Report.SymbolRelatedToPreviousError (type);
 356			ec.Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
 357				type.GetSignatureForError (), name);
 358		}
 359
 360		public virtual void Error_ValueAssignment (ResolveContext rc, Expression rhs)
 361		{
 362			if (rhs == EmptyExpression.LValueMemberAccess || rhs == EmptyExpression.LValueMemberOutAccess) {
 363				// Already reported as CS1612
 364			} else if (rhs == EmptyExpression.OutAccess) {
 365				rc.Report.Error (1510, loc, "A ref or out argument must be an assignable variable");
 366			} else {
 367				rc.Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer");
 368			}
 369		}
 370
 371		protected void Error_VoidPointerOperation (ResolveContext rc)
 372		{
 373			rc.Report.Error (242, loc, "The operation in question is undefined on void pointers");
 374		}
 375
 376		public static void Warning_UnreachableExpression (ResolveContext rc, Location loc)
 377		{
 378			rc.Report.Warning (429, 4, loc, "Unreachable expression code detected");
 379		}
 380
 381		public ResolveFlags ExprClassToResolveFlags {
 382			get {
 383				switch (eclass) {
 384				case ExprClass.Type:
 385				case ExprClass.Namespace:
 386					return ResolveFlags.Type;
 387					
 388				case ExprClass.MethodGroup:
 389					return ResolveFlags.MethodGroup;
 390					
 391				case ExprClass.TypeParameter:
 392					return ResolveFlags.TypeParameter;
 393					
 394				case ExprClass.Value:
 395				case ExprClass.Variable:
 396				case ExprClass.PropertyAccess:
 397				case ExprClass.EventAccess:
 398				case ExprClass.IndexerAccess:
 399					return ResolveFlags.VariableOrValue;
 400					
 401				default:
 402					throw new InternalErrorException (loc.ToString () + " " +  GetType () + " ExprClass is Invalid after resolve");
 403				}
 404			}
 405		}
 406
 407		//
 408		// Implements identical simple name and type-name resolution
 409		//
 410		public Expression ProbeIdenticalTypeName (ResolveContext rc, Expression left, SimpleName name)
 411		{
 412			var t = left.Type;
 413			if (t.Kind == MemberKind.InternalCompilerType || t is ElementTypeSpec || t.Arity > 0)
 414				return left;
 415
 416			// In a member access of the form E.I, if E is a single identifier, and if the meaning of E as a simple-name is
 417			// a constant, field, property, local variable, or parameter with the same type as the meaning of E as a type-name
 418
 419			if (left is MemberExpr || left is VariableReference) {
 420				var identical_type = rc.LookupNamespaceOrType (name.Name, 0, LookupMode.Probing, loc) as TypeExpr;
 421				if (identical_type != null && identical_type.Type == left.Type)
 422					return identical_type;
 423			}
 424
 425			return left;
 426		}
 427
 428		public virtual string GetSignatureForError ()
 429		{
 430			return type.GetDefinition ().GetSignatureForError ();
 431		}
 432
 433		public static bool IsNeverNull (Expression expr)
 434		{
 435			if (expr is This || expr is New || expr is ArrayCreation || expr is DelegateCreation || expr is ConditionalMemberAccess)
 436				return true;
 437
 438			var c = expr as Constant;
 439			if (c != null)
 440				return !c.IsNull;
 441
 442			var tc = expr as TypeCast;
 443			if (tc != null)
 444				return IsNeverNull (tc.Child);
 445
 446			return false;
 447		}
 448
 449		protected static bool IsNullPropagatingValid (TypeSpec type)
 450		{
 451			switch (type.Kind) {
 452			case MemberKind.Struct:
 453				return type.IsNullableType;
 454			case MemberKind.Enum:
 455			case MemberKind.Void:
 456			case MemberKind.PointerType:
 457				return false;
 458			case MemberKind.InternalCompilerType:
 459				return type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
 460			default:
 461				return true;
 462			}
 463		}
 464
 465		public virtual bool HasConditionalAccess ()
 466		{
 467			return false;
 468		}
 469
 470		protected static TypeSpec LiftMemberType (ResolveContext rc, TypeSpec type)
 471		{
 472			return TypeSpec.IsValueType (type) && !type.IsNullableType ?
 473				Nullable.NullableInfo.MakeType (rc.Module, type) :
 474				type;
 475		}
 476	       
 477		/// <summary>
 478		///   Resolves an expression and performs semantic analysis on it.
 479		/// </summary>
 480		///
 481		/// <remarks>
 482		///   Currently Resolve wraps DoResolve to perform sanity
 483		///   checking and assertion checking on what we expect from Resolve.
 484		/// </remarks>
 485		public Expression Resolve (ResolveContext ec, ResolveFlags flags)
 486		{
 487			if (eclass != ExprClass.Unresolved) {
 488				if ((flags & ExprClassToResolveFlags) == 0) {
 489					Error_UnexpectedKind (ec, flags, loc);
 490					return null;
 491				}
 492
 493				return this;
 494			}
 495			
 496			Expression e;
 497			try {
 498				e = DoResolve (ec);
 499
 500				if (e == null)
 501					return null;
 502
 503				if ((flags & e.ExprClassToResolveFlags) == 0) {
 504					e.Error_UnexpectedKind (ec, flags, loc);
 505					return null;
 506				}
 507
 508				if (e.type == null)
 509					throw new InternalErrorException ("Expression `{0}' didn't set its type in DoResolve", e.GetType ());
 510
 511				return e;
 512			} catch (Exception ex) {
 513				if (loc.IsNull || ec.Module.Compiler.Settings.BreakOnInternalError || ex is CompletionResult || ec.Report.IsDisabled || ex is FatalException ||
 514					ec.Report.Printer is NullReportPrinter)
 515					throw;
 516
 517				ec.Report.Error (584, loc, "Internal compiler error: {0}", ex.Message);
 518				return ErrorExpression.Instance;	// TODO: Add location
 519			}
 520		}
 521
 522		/// <summary>
 523		///   Resolves an expression and performs semantic analysis on it.
 524		/// </summary>
 525		public Expression Resolve (ResolveContext rc)
 526		{
 527			return Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
 528		}
 529
 530		/// <summary>
 531		///   Resolves an expression for LValue assignment
 532		/// </summary>
 533		///
 534		/// <remarks>
 535		///   Currently ResolveLValue wraps DoResolveLValue to perform sanity
 536		///   checking and assertion checking on what we expect from Resolve
 537		/// </remarks>
 538		public Expression ResolveLValue (ResolveContext ec, Expression right_side)
 539		{
 540			int errors = ec.Report.Errors;
 541			bool out_access = right_side == EmptyExpression.OutAccess;
 542
 543			Expression e = DoResolveLValue (ec, right_side);
 544
 545			if (e != null && out_access && !(e is IMemoryLocation)) {
 546				// FIXME: There's no problem with correctness, the 'Expr = null' handles that.
 547				//        Enabling this 'throw' will "only" result in deleting useless code elsewhere,
 548
 549				//throw new InternalErrorException ("ResolveLValue didn't return an IMemoryLocation: " +
 550				//				  e.GetType () + " " + e.GetSignatureForError ());
 551				e = null;
 552			}
 553
 554			if (e == null) {
 555				if (errors == ec.Report.Errors) {
 556					Error_ValueAssignment (ec, right_side);
 557				}
 558				return null;
 559			}
 560
 561			if (e.eclass == ExprClass.Unresolved)
 562				throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve");
 563
 564			if ((e.type == null) && !(e is GenericTypeExpr))
 565				throw new Exception ("Expression " + e + " did not set its type after Resolve");
 566
 567			return e;
 568		}
 569
 570		public Constant ResolveLabelConstant (ResolveContext rc)
 571		{
 572			var expr = Resolve (rc);
 573			if (expr == null)
 574				return null;
 575
 576			Constant c = expr as Constant;
 577			if (c == null) {
 578				if (expr.type != InternalType.ErrorType)
 579					rc.Report.Error (150, expr.StartLocation, "A constant value is expected");
 580
 581				return null;
 582			}
 583
 584			return c;
 585		}
 586
 587		public virtual void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
 588		{
 589			if (Attribute.IsValidArgumentType (parameterType)) {
 590				rc.Module.Compiler.Report.Error (182, loc,
 591					"An attribute argument must be a constant expression, typeof expression or array creation expression");
 592			} else {
 593				rc.Module.Compiler.Report.Error (181, loc,
 594					"Attribute constructor parameter has type `{0}', which is not a valid attribute parameter type",
 595					targetType.GetSignatureForError ());
 596			}
 597		}
 598
 599		/// <summary>
 600		///   Emits the code for the expression
 601		/// </summary>
 602		///
 603		/// <remarks>
 604		///   The Emit method is invoked to generate the code
 605		///   for the expression.  
 606		/// </remarks>
 607		public abstract void Emit (EmitContext ec);
 608
 609
 610		// Emit code to branch to @target if this expression is equivalent to @on_true.
 611		// The default implementation is to emit the value, and then emit a brtrue or brfalse.
 612		// Subclasses can provide more efficient implementations, but those MUST be equivalent,
 613		// including the use of conditional branches.  Note also that a branch MUST be emitted
 614		public virtual void EmitBranchable (EmitContext ec, Label target, bool on_true)
 615		{
 616			Emit (ec);
 617			ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
 618		}
 619
 620		// Emit this expression for its side effects, not for its value.
 621		// The default implementation is to emit the value, and then throw it away.
 622		// Subclasses can provide more efficient implementations, but those MUST be equivalent
 623		public virtual void EmitSideEffect (EmitContext ec)
 624		{
 625			Emit (ec);
 626			ec.Emit (OpCodes.Pop);
 627		}
 628
 629		//
 630		// Emits the expression into temporary field variable. The method
 631		// should be used for await expressions only
 632		//
 633		public virtual Expression EmitToField (EmitContext ec)
 634		{
 635			//
 636			// This is the await prepare Emit method. When emitting code like
 637			// a + b we emit code like
 638			//
 639			// a.Emit ()
 640			// b.Emit ()
 641			// Opcodes.Add
 642			//
 643			// For await a + await b we have to interfere the flow to keep the
 644			// stack clean because await yields from the expression. The emit
 645			// then changes to
 646			//
 647			// a = a.EmitToField ()	// a is changed to temporary field access
 648			// b = b.EmitToField ()
 649			// a.Emit ()
 650			// b.Emit ()
 651			// Opcodes.Add
 652			//
 653			//
 654			// The idea is to emit expression and leave the stack empty with
 655			// result value still available.
 656			//
 657			// Expressions should override this default implementation when
 658			// optimized version can be provided (e.g. FieldExpr)
 659			//
 660			//
 661			// We can optimize for side-effect free expressions, they can be
 662			// emitted out of order
 663			//
 664			if (IsSideEffectFree)
 665				return this;
 666
 667			bool needs_temporary = ContainsEmitWithAwait ();
 668			if (!needs_temporary)
 669				ec.EmitThis ();
 670
 671			// Emit original code
 672			var field = EmitToFieldSource (ec);
 673			if (field == null) {
 674				//
 675				// Store the result to temporary field when we
 676				// cannot load `this' directly
 677				//
 678				field = ec.GetTemporaryField (type);
 679				if (needs_temporary) {
 680					//
 681					// Create temporary local (we cannot load `this' before Emit)
 682					//
 683					var temp = ec.GetTemporaryLocal (type);
 684					ec.Emit (OpCodes.Stloc, temp);
 685
 686					ec.EmitThis ();
 687					ec.Emit (OpCodes.Ldloc, temp);
 688					field.EmitAssignFromStack (ec);
 689
 690					ec.FreeTemporaryLocal (temp, type);
 691				} else {
 692					field.EmitAssignFromStack (ec);
 693				}
 694			}
 695
 696			return field;
 697		}
 698
 699		protected virtual FieldExpr EmitToFieldSource (EmitContext ec)
 700		{
 701			//
 702			// Default implementation calls Emit method
 703			//
 704			Emit (ec);
 705			return null;
 706		}
 707
 708		protected static void EmitExpressionsList (EmitContext ec, List<Expression> expressions)
 709		{
 710			if (ec.HasSet (BuilderContext.Options.AsyncBody)) {
 711				bool contains_await = false;
 712
 713				for (int i = 1; i < expressions.Count; ++i) {
 714					if (expressions[i].ContainsEmitWithAwait ()) {
 715						contains_await = true;
 716						break;
 717					}
 718				}
 719
 720				if (contains_await) {
 721					for (int i = 0; i < expressions.Count; ++i) {
 722						expressions[i] = expressions[i].EmitToField (ec);
 723					}
 724				}
 725			}
 726
 727			for (int i = 0; i < expressions.Count; ++i) {
 728				expressions[i].Emit (ec);
 729			}
 730		}
 731
 732		/// <summary>
 733		///   Protected constructor.  Only derivate types should
 734		///   be able to be created
 735		/// </summary>
 736
 737		protected Expression ()
 738		{
 739		}
 740
 741		/// <summary>
 742		///   Returns a fully formed expression after a MemberLookup
 743		/// </summary>
 744		/// 
 745		static Expression ExprClassFromMemberInfo (MemberSpec spec, Location loc)
 746		{
 747			if (spec is EventSpec)
 748				return new EventExpr ((EventSpec) spec, loc);
 749			if (spec is ConstSpec)
 750				return new ConstantExpr ((ConstSpec) spec, loc);
 751			if (spec is FieldSpec)
 752				return new FieldExpr ((FieldSpec) spec, loc);
 753			if (spec is PropertySpec)
 754				return new PropertyExpr ((PropertySpec) spec, loc);
 755			if (spec is TypeSpec)
 756				return new TypeExpression (((TypeSpec) spec), loc);
 757
 758			return null;
 759		}
 760
 761		public static MethodSpec ConstructorLookup (ResolveContext rc, TypeSpec type, ref Arguments args, Location loc)
 762		{
 763			var ctors = MemberCache.FindMembers (type, Constructor.ConstructorName, true);
 764			if (ctors == null) {
 765				switch (type.Kind) {
 766				case MemberKind.Struct:
 767					rc.Report.SymbolRelatedToPreviousError (type);
 768					// Report meaningful error for struct as they always have default ctor in C# context
 769					OverloadResolver.Error_ConstructorMismatch (rc, type, args == null ? 0 : args.Count, loc);
 770					break;
 771				case MemberKind.MissingType:
 772				case MemberKind.InternalCompilerType:
 773// LAMESPEC: dynamic is not really object
 774//					if (type.BuiltinType == BuiltinTypeSpec.Type.Object)
 775//						goto default;
 776					break;
 777				default:
 778					rc.Report.SymbolRelatedToPreviousError (type);
 779					rc.Report.Error (143, loc, "The class `{0}' has no constructors defined",
 780						type.GetSignatureForError ());
 781					break;
 782				}
 783
 784				return null;
 785			}
 786
 787			var r = new OverloadResolver (ctors, OverloadResolver.Restrictions.NoBaseMembers, loc);
 788			if (!rc.HasSet (ResolveContext.Options.BaseInitializer)) {
 789				r.InstanceQualifier = new ConstructorInstanceQualifier (type);
 790			}
 791
 792			return r.ResolveMember<MethodSpec> (rc, ref args);
 793		}
 794
 795		[Flags]
 796		public enum MemberLookupRestrictions
 797		{
 798			None = 0,
 799			InvocableOnly = 1,
 800			ExactArity = 1 << 2,
 801			ReadAccess = 1 << 3,
 802			EmptyArguments = 1 << 4,
 803			IgnoreArity = 1 << 5,
 804			IgnoreAmbiguity = 1 << 6
 805		}
 806
 807		//
 808		// Lookup type `queried_type' for code in class `container_type' with a qualifier of
 809		// `qualifier_type' or null to lookup members in the current class.
 810		//
 811		public static Expression MemberLookup (IMemberContext rc, bool errorMode, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc)
 812		{
 813			var members = MemberCache.FindMembers (queried_type, name, false);
 814			if (members == null)
 815				return null;
 816
 817			MemberSpec non_method = null;
 818			MemberSpec ambig_non_method = null;
 819			do {
 820				for (int i = 0; i < members.Count; ++i) {
 821					var member = members[i];
 822
 823					// HACK: for events because +=/-= can appear at same class only, should use OverrideToBase there
 824					if ((member.Modifiers & Modifiers.OVERRIDE) != 0 && member.Kind != MemberKind.Event)
 825						continue;
 826
 827					if ((member.Modifiers & Modifiers.BACKING_FIELD) != 0 || member.Kind == MemberKind.Operator)
 828						continue;
 829
 830					if ((arity > 0 || (restrictions & MemberLookupRestrictions.ExactArity) != 0) && member.Arity != arity)
 831						continue;
 832
 833					if (!errorMode) {
 834						if (!member.IsAccessible (rc))
 835							continue;
 836
 837						//
 838						// With runtime binder we can have a situation where queried type is inaccessible
 839						// because it came via dynamic object, the check about inconsisted accessibility
 840						// had no effect as the type was unknown during compilation
 841						//
 842						// class A {
 843						//		private class N { }
 844						//
 845						//		public dynamic Foo ()
 846						//		{
 847						//			return new N ();
 848						//		}
 849						//	}
 850						//
 851						if (rc.Module.Compiler.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc))
 852							continue;
 853					}
 854
 855					if ((restrictions & MemberLookupRestrictions.InvocableOnly) != 0) {
 856						if (member is MethodSpec) {
 857							//
 858							// Interface members that are hidden by class members are removed from the set. This
 859							// step only has an effect if T is a type parameter and T has both an effective base 
 860							// class other than object and a non-empty effective interface set
 861							//
 862							var tps = queried_type as TypeParameterSpec;
 863							if (tps != null && tps.HasTypeConstraint)
 864								members = RemoveHiddenTypeParameterMethods (members);
 865
 866							return new MethodGroupExpr (members, queried_type, loc);
 867						}
 868
 869						if (!Invocation.IsMemberInvocable (member))
 870							continue;
 871					}
 872
 873					if (non_method == null || member is MethodSpec || non_method.IsNotCSharpCompatible) {
 874						non_method = member;
 875					} else if (!errorMode && !member.IsNotCSharpCompatible) {
 876						//
 877						// Interface members that are hidden by class members are removed from the set when T is a type parameter and
 878						// T has both an effective base class other than object and a non-empty effective interface set.
 879						//
 880						// The spec has more complex rules but we simply remove all members declared in an interface declaration.
 881						//
 882						var tps = queried_type as TypeParameterSpec;
 883						if (tps != null && tps.HasTypeConstraint) {
 884							if (non_method.DeclaringType.IsClass && member.DeclaringType.IsInterface)
 885								continue;
 886
 887							if (non_method.DeclaringType.IsInterface && member.DeclaringType.IsInterface) {
 888								non_method = member;
 889								continue;
 890							}
 891						}
 892
 893						ambig_non_method = member;
 894					}
 895				}
 896
 897				if (non_method != null) {
 898					if (ambig_non_method != null && rc != null && (restrictions & MemberLookupRestrictions.IgnoreAmbiguity) == 0) {
 899						var report = rc.Module.Compiler.Report;
 900						report.SymbolRelatedToPreviousError (non_method);
 901						report.SymbolRelatedToPreviousError (ambig_non_method);
 902						report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
 903							non_method.GetSignatureForError (), ambig_non_method.GetSignatureForError ());
 904					}
 905
 906					if (non_method is MethodSpec)
 907						return new MethodGroupExpr (members, queried_type, loc);
 908
 909					return ExprClassFromMemberInfo (non_method, loc);
 910				}
 911
 912				if (members[0].DeclaringType.BaseType == null)
 913					members = null;
 914				else
 915					members = MemberCache.FindMembers (members[0].DeclaringType.BaseType, name, false);
 916
 917			} while (members != null);
 918
 919			return null;
 920		}
 921
 922		static IList<MemberSpec> RemoveHiddenTypeParameterMethods (IList<MemberSpec> members)
 923		{
 924			if (members.Count < 2)
 925				return members;
 926
 927			//
 928			// If M is a method, then all non-method members declared in an interface declaration
 929			// are removed from the set, and all methods with the same signature as M declared in
 930			// an interface declaration are removed from the set
 931			//
 932
 933			bool copied = false;
 934			for (int i = 0; i < members.Count; ++i) {
 935				var method = members[i] as MethodSpec;
 936				if (method == null) {
 937					if (!copied) {
 938						copied = true;
 939						members = new List<MemberSpec> (members);
 940					} 
 941					
 942					members.RemoveAt (i--);
 943					continue;
 944				}
 945
 946				if (!method.DeclaringType.IsInterface)
 947					continue;
 948
 949				for (int ii = 0; ii < members.Count; ++ii) {
 950					var candidate = members[ii] as MethodSpec;
 951					if (candidate == null || !candidate.DeclaringType.IsClass)
 952						continue;
 953
 954					if (!TypeSpecComparer.Override.IsEqual (candidate.Parameters, method.Parameters))
 955						continue;
 956
 957					if (!copied) {
 958						copied = true;
 959						members = new List<MemberSpec> (members);
 960					}
 961
 962					members.RemoveAt (i--);
 963					break;
 964				}
 965			}
 966
 967			return members;
 968		}
 969
 970		protected virtual void Error_NegativeArrayIndex (ResolveContext ec, Location loc)
 971		{
 972			throw new NotImplementedException ();
 973		}
 974
 975		public virtual void Error_OperatorCannotBeApplied (ResolveContext rc, Location loc, string oper, TypeSpec t)
 976		{
 977			if (t == InternalType.ErrorType)
 978				return;
 979
 980			rc.Report.Error (23, loc, "The `{0}' operator cannot be applied to operand of type `{1}'",
 981				oper, t.GetSignatureForError ());
 982		}
 983
 984		protected void Error_PointerInsideExpressionTree (ResolveContext ec)
 985		{
 986			ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
 987		}
 988
 989		protected void Error_NullShortCircuitInsideExpressionTree (ResolveContext rc)
 990		{
 991			rc.Report.Error (8072, loc, "An expression tree cannot contain a null propagating operator");
 992		}
 993
 994		public virtual void FlowAnalysis (FlowAnalysisContext fc)
 995		{
 996		}
 997
 998		//
 999		// Special version of flow analysis for expressions which can return different
1000		// on-true and on-false result. Used by &&, ||, ?: expressions
1001		//
1002		public virtual void FlowAnalysisConditional (FlowAnalysisContext fc)
1003		{
1004			FlowAnalysis (fc);
1005			fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment;
1006		}
1007
1008		/// <summary>
1009		///   Returns an expression that can be used to invoke operator true
1010		///   on the expression if it exists.
1011		/// </summary>
1012		protected static Expression GetOperatorTrue (ResolveContext ec, Expression e, Location loc)
1013		{
1014			return GetOperatorTrueOrFalse (ec, e, true, loc);
1015		}
1016
1017		/// <summary>
1018		///   Returns an expression that can be used to invoke operator false
1019		///   on the expression if it exists.
1020		/// </summary>
1021		protected static Expression GetOperatorFalse (ResolveContext ec, Expression e, Location loc)
1022		{
1023			return GetOperatorTrueOrFalse (ec, e, false, loc);
1024		}
1025
1026		static Expression GetOperatorTrueOrFalse (ResolveContext ec, Expression e, bool is_true, Location loc)
1027		{
1028			var op = is_true ? Operator.OpType.True : Operator.OpType.False;
1029			var methods = MemberCache.GetUserOperator (e.type, op, false);
1030			if (methods == null)
1031				return null;
1032
1033			Arguments arguments = new Arguments (1);
1034			arguments.Add (new Argument (e));
1035
1036			var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc);
1037			var oper = res.ResolveOperator (ec, ref arguments);
1038
1039			if (oper == null)
1040				return null;
1041
1042			return new UserOperatorCall (oper, arguments, null, loc);
1043		}
1044		
1045		public virtual string ExprClassName
1046		{
1047			get {
1048				switch (eclass){
1049				case ExprClass.Unresolved:
1050					return "Unresolved";
1051				case ExprClass.Value:
1052					return "value";
1053				case ExprClass.Variable:
1054					return "variable";
1055				case ExprClass.Namespace:
1056					return "namespace";
1057				case ExprClass.Type:
1058					return "type";
1059				case ExprClass.MethodGroup:
1060					return "method group";
1061				case ExprClass.PropertyAccess:
1062					return "property access";
1063				case ExprClass.EventAccess:
1064					return "event access";
1065				case ExprClass.IndexerAccess:
1066					return "indexer access";
1067				case ExprClass.Nothing:
1068					return "null";
1069				case ExprClass.TypeParameter:
1070					return "type parameter";
1071				}
1072				throw new Exception ("Should not happen");
1073			}
1074		}
1075		
1076		/// <summary>
1077		///   Reports that we were expecting `expr' to be of class `expected'
1078		/// </summary>
1079		public static void Error_UnexpectedKind (IMemberContext ctx, Expression memberExpr, string expected, string was, Location loc)
1080		{
1081			var name = memberExpr.GetSignatureForError ();
1082
1083			ctx.Module.Compiler.Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected", name, was, expected);
1084		}
1085
1086		public virtual void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc)
1087		{
1088			string [] valid = new string [4];
1089			int count = 0;
1090
1091			if ((flags & ResolveFlags.VariableOrValue) != 0) {
1092				valid [count++] = "variable";
1093				valid [count++] = "value";
1094			}
1095
1096			if ((flags & ResolveFlags.Type) != 0)
1097				valid [count++] = "type";
1098
1099			if ((flags & ResolveFlags.MethodGroup) != 0)
1100				valid [count++] = "method group";
1101
1102			if (count == 0)
1103				valid [count++] = "unknown";
1104
1105			StringBuilder sb = new StringBuilder (valid [0]);
1106			for (int i = 1; i < count - 1; i++) {
1107				sb.Append ("', `");
1108				sb.Append (valid [i]);
1109			}
1110			if (count > 1) {
1111				sb.Append ("' or `");
1112				sb.Append (valid [count - 1]);
1113			}
1114
1115			ec.Report.Error (119, loc, 
1116				"Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ());
1117		}
1118		
1119		public static void UnsafeError (ResolveContext ec, Location loc)
1120		{
1121			UnsafeError (ec.Report, loc);
1122		}
1123
1124		public static void UnsafeError (Report Report, Location loc)
1125		{
1126			Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
1127		}
1128
1129		//
1130		// Converts `source' to an int, uint, long or ulong.
1131		//
1132		protected Expression ConvertExpressionToArrayIndex (ResolveContext ec, Expression source, bool pointerArray = false)
1133		{
1134			var btypes = ec.BuiltinTypes;
1135
1136			if (source.type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1137				Arguments args = new Arguments (1);
1138				args.Add (new Argument (source));
1139				return new DynamicConversion (btypes.Int, CSharpBinderFlags.ConvertArrayIndex, args, loc).Resolve (ec);
1140			}
1141
1142			Expression converted;
1143			
1144			using (ec.Set (ResolveContext.Options.CheckedScope)) {
1145				converted = Convert.ImplicitConversion (ec, source, btypes.Int, source.loc);
1146				if (converted == null)
1147					converted = Convert.ImplicitConversion (ec, source, btypes.UInt, source.loc);
1148				if (converted == null)
1149					converted = Convert.ImplicitConversion (ec, source, btypes.Long, source.loc);
1150				if (converted == null)
1151					converted = Convert.ImplicitConversion (ec, source, btypes.ULong, source.loc);
1152
1153				if (converted == null) {
1154					source.Error_ValueCannotBeConverted (ec, btypes.Int, false);
1155					return null;
1156				}
1157			}
1158
1159			if (pointerArray)
1160				return converted;
1161
1162			//
1163			// Only positive constants are allowed at compile time
1164			//
1165			Constant c = converted as Constant;
1166			if (c != null && c.IsNegative)
1167				Error_NegativeArrayIndex (ec, source.loc);
1168
1169			// No conversion needed to array index
1170			if (converted.Type.BuiltinType == BuiltinTypeSpec.Type.Int)
1171				return converted;
1172
1173			return new ArrayIndexCast (converted, btypes.Int).Resolve (ec);
1174		}
1175
1176		//
1177		// Derived classes implement this method by cloning the fields that
1178		// could become altered during the Resolve stage
1179		//
1180		// Only expressions that are created for the parser need to implement
1181		// this.
1182		//
1183		protected virtual void CloneTo (CloneContext clonectx, Expression target)
1184		{
1185			throw new NotImplementedException (
1186				String.Format (
1187					"CloneTo not implemented for expression {0}", this.GetType ()));
1188		}
1189
1190		//
1191		// Clones an expression created by the parser.
1192		//
1193		// We only support expressions created by the parser so far, not
1194		// expressions that have been resolved (many more classes would need
1195		// to implement CloneTo).
1196		//
1197		// This infrastructure is here merely for Lambda expressions which
1198		// compile the same code using different type values for the same
1199		// arguments to find the correct overload
1200		//
1201		public virtual Expression Clone (CloneContext clonectx)
1202		{
1203			Expression cloned = (Expression) MemberwiseClone ();
1204			CloneTo (clonectx, cloned);
1205
1206			return cloned;
1207		}
1208
1209		//
1210		// Implementation of expression to expression tree conversion
1211		//
1212		public abstract Expression CreateExpressionTree (ResolveContext ec);
1213
1214		protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, Arguments args)
1215		{
1216			return CreateExpressionFactoryCall (ec, name, null, args, loc);
1217		}
1218
1219		protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args)
1220		{
1221			return CreateExpressionFactoryCall (ec, name, typeArguments, args, loc);
1222		}
1223
1224		public static Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args, Location loc)
1225		{
1226			return new Invocation (new MemberAccess (CreateExpressionTypeExpression (ec, loc), name, typeArguments, loc), args);
1227		}
1228
1229		protected static TypeExpr CreateExpressionTypeExpression (ResolveContext ec, Location loc)
1230		{
1231			var t = ec.Module.PredefinedTypes.Expression.Resolve ();
1232			if (t == null)
1233				return null;
1234
1235			return new TypeExpression (t, loc);
1236		}
1237
1238		//
1239		// Implemented by all expressions which support conversion from
1240		// compiler expression to invokable runtime expression. Used by
1241		// dynamic C# binder.
1242		//
1243		public virtual SLE.Expression MakeExpression (BuilderContext ctx)
1244		{
1245			throw new NotImplementedException ("MakeExpression for " + GetType ());
1246		}
1247			
1248		public virtual object Accept (StructuralVisitor visitor)
1249		{
1250			return visitor.Visit (this);
1251		}
1252	}
1253
1254	/// <summary>
1255	///   This is just a base class for expressions that can
1256	///   appear on statements (invocations, object creation,
1257	///   assignments, post/pre increment and decrement).  The idea
1258	///   being that they would support an extra Emition interface that
1259	///   does not leave a result on the stack.
1260	/// </summary>
1261	public abstract class ExpressionStatement : Expression
1262	{
1263		public virtual void MarkReachable (Reachability rc)
1264		{
1265		}
1266
1267		public ExpressionStatement ResolveStatement (BlockContext ec)
1268		{
1269			Expression e = Resolve (ec);
1270			if (e == null)
1271				return null;
1272
1273			ExpressionStatement es = e as ExpressionStatement;
1274			if (es == null || e is AnonymousMethodBody)
1275				Error_InvalidExpressionStatement (ec);
1276
1277			//
1278			// This is quite expensive warning, try to limit the damage
1279			//
1280			if (MemberAccess.IsValidDotExpression (e.Type) && !(e is Assign || e is Await)) {
1281				WarningAsyncWithoutWait (ec, e);
1282			}
1283
1284			return es;
1285		}
1286
1287		static void WarningAsyncWithoutWait (BlockContext bc, Expression e)
1288		{
1289			if (bc.CurrentAnonymousMethod is AsyncInitializer) {
1290				var awaiter = new AwaitStatement.AwaitableMemberAccess (e) {
1291					ProbingMode = true
1292				};
1293
1294				//
1295				// Need to do full resolve because GetAwaiter can be extension method
1296				// available only in this context
1297				//
1298				var mg = awaiter.Resolve (bc) as MethodGroupExpr;
1299				if (mg == null)
1300					return;
1301
1302				var arguments = new Arguments (0);
1303				mg = mg.OverloadResolve (bc, ref arguments, null, OverloadResolver.Restrictions.ProbingOnly);
1304				if (mg == null)
1305					return;
1306
1307				//
1308				// Use same check rules as for real await
1309				//
1310				var awaiter_definition = bc.Module.GetAwaiter (mg.BestCandidateReturnType);
1311				if (!awaiter_definition.IsValidPattern || !awaiter_definition.INotifyCompletion)
1312					return;
1313
1314				bc.Report.Warning (4014, 1, e.Location,
1315					"The statement is not awaited and execution of current method continues before the call is completed. Consider using `await' operator");
1316				return;
1317			}
1318
1319			var inv = e as Invocation;
1320			if (inv != null && inv.MethodGroup != null && inv.MethodGroup.BestCandidate.IsAsync) {
1321				// The warning won't be reported for imported methods to maintain warning compatiblity with csc 
1322				bc.Report.Warning (4014, 1, e.Location,
1323					"The statement is not awaited and execution of current method continues before the call is completed. Consider using `await' operator or calling `Wait' method");
1324				return;
1325			}
1326		}
1327
1328		/// <summary>
1329		///   Requests the expression to be emitted in a `statement'
1330		///   context.  This means that no new value is left on the
1331		///   stack after invoking this method (constrasted with
1332		///   Emit that will always leave a value on the stack).
1333		/// </summary>
1334		public abstract void EmitStatement (EmitContext ec);
1335
1336		public override void EmitSideEffect (EmitContext ec)
1337		{
1338			EmitStatement (ec);
1339		}
1340	}
1341
1342	/// <summary>
1343	///   This kind of cast is used to encapsulate the child
1344	///   whose type is child.Type into an expression that is
1345	///   reported to return "return_type".  This is used to encapsulate
1346	///   expressions which have compatible types, but need to be dealt
1347	///   at higher levels with.
1348	///
1349	///   For example, a "byte" expression could be encapsulated in one
1350	///   of these as an "unsigned int".  The type for the expression
1351	///   would be "unsigned int".
1352	///
1353	/// </summary>
1354	public abstract class TypeCast : Expression
1355	{
1356		protected readonly Expression child;
1357
1358		protected TypeCast (Expression child, TypeSpec return_type)
1359		{
1360			eclass = child.eclass;
1361			loc = child.Location;
1362			type = return_type;
1363			this.child = child;
1364		}
1365
1366		public Expression Child {
1367			get {
1368				return child;
1369			}
1370		}
1371
1372		public override bool ContainsEmitWithAwait ()
1373		{
1374			return child.ContainsEmitWithAwait ();
1375		}
1376
1377		public override Expression CreateExpressionTree (ResolveContext ec)
1378		{
1379			Arguments args = new Arguments (2);
1380			args.Add (new Argument (child.CreateExpressionTree (ec)));
1381			args.Add (new Argument (new TypeOf (type, loc)));
1382
1383			if (type.IsPointer || child.Type.IsPointer)
1384				Error_PointerInsideExpressionTree (ec);
1385
1386			return CreateExpressionFactoryCall (ec, ec.HasSet (ResolveContext.Options.CheckedScope) ? "ConvertChecked" : "Convert", args);
1387		}
1388
1389		protected override Expression DoResolve (ResolveContext ec)
1390		{
1391			// This should never be invoked, we are born in fully
1392			// initialized state.
1393
1394			return this;
1395		}
1396
1397		public override void Emit (EmitContext ec)
1398		{
1399			child.Emit (ec);
1400		}
1401
1402		public override void FlowAnalysis (FlowAnalysisContext fc)
1403		{
1404			child.FlowAnalysis (fc);
1405		}
1406
1407		public override SLE.Expression MakeExpression (BuilderContext ctx)
1408		{
1409#if STATIC
1410			return base.MakeExpression (ctx);
1411#else
1412			return ctx.HasSet (BuilderContext.Options.CheckedScope) ?
1413				SLE.Expression.ConvertChecked (child.MakeExpression (ctx), type.GetMetaInfo ()) :
1414				SLE.Expression.Convert (child.MakeExpression (ctx), type.GetMetaInfo ());
1415#endif
1416		}
1417
1418		protected override void CloneTo (CloneContext clonectx, Expression t)
1419		{
1420			// Nothing to clone
1421		}
1422
1423		public override bool IsNull {
1424			get { return child.IsNull; }
1425		}
1426	}
1427
1428	public class EmptyCast : TypeCast {
1429		EmptyCast (Expression child, TypeSpec target_type)
1430			: base (child, target_type)
1431		{
1432		}
1433
1434		public static Expression Create (Expression child, TypeSpec type)
1435		{
1436			Constant c = child as Constant;
1437			if (c != null) {
1438				var enum_constant = c as EnumConstant;
1439				if (enum_constant != null)
1440					c = enum_constant.Child;
1441
1442				if (!(c is ReducedExpression.ReducedConstantExpression)) {
1443					if (c.Type == type)
1444						return c;
1445
1446					var res = c.ConvertImplicitly (type);
1447					if (res != null)
1448						return res;
1449				}
1450			}
1451
1452			EmptyCast e = child as EmptyCast;
1453			if (e != null)
1454				return new EmptyCast (e.child, type);
1455
1456			return new EmptyCast (child, type);
1457		}
1458
1459		public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
1460		{
1461			child.EmitBranchable (ec, label, on_true);
1462		}
1463
1464		public override void EmitSideEffect (EmitContext ec)
1465		{
1466			child.EmitSideEffect (ec);
1467		}
1468	}
1469
1470	//
1471	// Used for predefined type user operator (no obsolete check, etc.)
1472	//
1473	public class OperatorCast : TypeCast
1474	{
1475		readonly MethodSpec conversion_operator;
1476
1477		public OperatorCast (Expression expr, TypeSpec target_type)
1478			: this (expr, target_type, target_type, false)
1479		{
1480		}
1481		
1482		public OperatorCast (Expression expr, TypeSpec target_type, bool find_explicit)
1483			: this (expr, target_type, target_type, find_explicit)
1484		{
1485		}
1486		
1487		public OperatorCast (Expression expr, TypeSpec declaringType, TypeSpec returnType, bool isExplicit)
1488			: base (expr, returnType)
1489		{
1490			var op = isExplicit ? Operator.OpType.Explicit : Operator.OpType.Implicit;
1491			var mi = MemberCache.GetUserOperator (declaringType, op, true);
1492
1493			if (mi != null) {
1494				foreach (MethodSpec oper in mi) {
1495					if (oper.ReturnType != returnType)
1496						continue;
1497
1498					if (oper.Parameters.Types[0] == expr.Type) {
1499						conversion_operator = oper;
1500						return;
1501					}
1502				}
1503			}
1504
1505			throw new InternalErrorException ("Missing predefined user operator between `{0}' and `{1}'",
1506				returnType.GetSignatureForError (), expr.Type.GetSignatureForError ());
1507		}
1508
1509		public override void Emit (EmitContext ec)
1510		{
1511			child.Emit (ec);
1512			ec.Emit (OpCodes.Call, conversion_operator);
1513		}
1514	}
1515	
1516	//
1517	// Constant specialization of EmptyCast.
1518	// We need to special case this since an empty cast of
1519	// a constant is still a constant. 
1520	//
1521	public class EmptyConstantCast : Constant
1522	{
1523		public readonly Constant child;
1524
1525		public EmptyConstantCast (Constant child, TypeSpec type)
1526			: base (child.Location)
1527		{
1528			if (child == null)
1529				throw new ArgumentNullException ("child");
1530
1531			this.child = child;
1532			this.eclass = child.eclass;
1533			this.type = type;
1534		}
1535
1536		public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1537		{
1538			if (child.Type == target_type)
1539				return child;
1540
1541			// FIXME: check that 'type' can be converted to 'target_type' first
1542			return child.ConvertExplicitly (in_checked_context, target_type);
1543		}
1544
1545		public override Expression CreateExpressionTree (ResolveContext ec)
1546		{
1547			Arguments args = Arguments.CreateForExpressionTree (ec, null,
1548				child.CreateExpressionTree (ec),
1549				new TypeOf (type, loc));
1550
1551			if (type.IsPointer)
1552				Error_PointerInsideExpressionTree (ec);
1553
1554			return CreateExpressionFactoryCall (ec, "Convert", args);
1555		}
1556
1557		public override bool IsDefaultValue {
1558			get { return child.IsDefaultValue; }
1559		}
1560
1561		public override bool IsNegative {
1562			get { return child.IsNegative; }
1563		}
1564
1565		public override bool IsNull {
1566			get { return child.IsNull; }
1567		}
1568		
1569		public override bool IsOneInteger {
1570			get { return child.IsOneInteger; }
1571		}
1572
1573		public override bool IsSideEffectFree {
1574			get {
1575				return child.IsSideEffectFree;
1576			}
1577		}
1578
1579		public override bool IsZeroInteger {
1580			get { return child.IsZeroInteger; }
1581		}
1582
1583		public override void Emit (EmitContext ec)
1584		{
1585			child.Emit (ec);			
1586		}
1587
1588		public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
1589		{
1590			child.EmitBranchable (ec, label, on_true);
1591
1592			// Only to make verifier happy
1593			if (TypeManager.IsGenericParameter (type) && child.IsNull)
1594				ec.Emit (OpCodes.Unbox_Any, type);
1595		}
1596
1597		public override void EmitSideEffect (EmitContext ec)
1598		{
1599			child.EmitSideEffect (ec);
1600		}
1601
1602		public override object GetValue ()
1603		{
1604			return child.GetValue ();
1605		}
1606
1607		public override string GetValueAsLiteral ()
1608		{
1609			return child.GetValueAsLiteral ();
1610		}
1611
1612		public override long GetValueAsLong ()
1613		{
1614			return child.GetValueAsLong ();
1615		}
1616
1617		public override Constant ConvertImplicitly (TypeSpec target_type)
1618		{
1619			if (type == target_type)
1620				return this;
1621
1622			// FIXME: Do we need to check user conversions?
1623			if (!Convert.ImplicitStandardConversionExists (this, target_type))
1624				return null;
1625
1626			return child.ConvertImplicitly (target_type);
1627		}
1628	}
1629
1630	/// <summary>
1631	///  This class is used to wrap literals which belong inside Enums
1632	/// </summary>
1633	public class EnumConstant : Constant
1634	{
1635		public Constant Child;
1636
1637		public EnumConstant (Constant child, TypeSpec enum_type)
1638			: base (child.Location)
1639		{
1640			this.Child = child;
1641
1642			this.eclass = ExprClass.Value;
1643			this.type = enum_type;
1644		}
1645
1646		protected EnumConstant (Location loc)
1647			: base (loc)
1648		{
1649		}
1650
1651		public override void Emit (EmitContext ec)
1652		{
1653			Child.Emit (ec);
1654		}
1655
1656		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
1657		{
1658			Child.EncodeAttributeValue (rc, enc, Child.Type, parameterType);
1659		}
1660
1661		public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
1662		{
1663			Child.EmitBranchable (ec, label, on_true);
1664		}
1665
1666		public override void EmitSideEffect (EmitContext ec)
1667		{
1668			Child.EmitSideEffect (ec);
1669		}
1670
1671		public override string GetSignatureForError()
1672		{
1673			return Type.GetSignatureForError ();
1674		}
1675
1676		public override object GetValue ()
1677		{
1678			return Child.GetValue ();
1679		}
1680
1681#if !STATIC
1682		public override object GetTypedValue ()
1683		{
1684			//
1685			// The method can be used in dynamic context only (on closed types)
1686			//
1687			// System.Enum.ToObject cannot be called on dynamic types
1688			// EnumBuilder has to be used, but we cannot use EnumBuilder
1689			// because it does not properly support generics
1690			//
1691			return System.Enum.ToObject (type.GetMetaInfo (), Child.GetValue ());
1692		}
1693#endif
1694
1695		public override string GetValueAsLiteral ()
1696		{
1697			return Child.GetValueAsLiteral ();
1698		}
1699
1700		public override long GetValueAsLong ()
1701		{
1702			return Child.GetValueAsLong ();
1703		}
1704
1705		public EnumConstant Increment()
1706		{
1707			return new EnumConstant (((IntegralConstant) Child).Increment (), type);
1708		}
1709
1710		public override bool IsDefaultValue {
1711			get {
1712				return Child.IsDefaultValue;
1713			}
1714		}
1715
1716		public override bool IsSideEffectFree {
1717			get {
1718				return Child.IsSideEffectFree;
1719			}
1720		}
1721
1722		public override bool IsZeroInteger {
1723			get { return Child.IsZeroInteger; }
1724		}
1725
1726		public override bool IsNegative {
1727			get {
1728				return Child.IsNegative;
1729			}
1730		}
1731
1732		public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1733		{
1734			if (Child.Type == target_type)
1735				return Child;
1736
1737			return Child.ConvertExplicitly (in_checked_context, target_type);
1738		}
1739
1740		public override Constant ConvertImplicitly (TypeSpec type)
1741		{
1742			if (this.type == type) {
1743				return this;
1744			}
1745
1746			if (!Convert.ImplicitStandardConve

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