1 //
2 // expression.cs: Expression representation for the IL 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 Xamarin Inc.
11 //
12 
13 using System;
14 using System.Collections.Generic;
15 using System.Linq;
16 using SLE = System.Linq.Expressions;
17 using System.Text;
18 
19 #if STATIC
20 using MetaType = IKVM.Reflection.Type;
21 using IKVM.Reflection;
22 using IKVM.Reflection.Emit;
23 #else
24 using MetaType = System.Type;
25 using System.Reflection;
26 using System.Reflection.Emit;
27 #endif
28 
29 namespace Mono.CSharp
30 {
31 	//
32 	// This is an user operator expression, automatically created during
33 	// resolve phase
34 	//
35 	public class UserOperatorCall : Expression {
36 		protected readonly Arguments arguments;
37 		protected readonly MethodSpec oper;
38 		readonly Func<ResolveContext, Expression, Expression> expr_tree;
39 
UserOperatorCall(MethodSpec oper, Arguments args, Func<ResolveContext, Expression, Expression> expr_tree, Location loc)40 		public UserOperatorCall (MethodSpec oper, Arguments args, Func<ResolveContext, Expression, Expression> expr_tree, Location loc)
41 		{
42 			this.oper = oper;
43 			this.arguments = args;
44 			this.expr_tree = expr_tree;
45 
46 			type = oper.ReturnType;
47 			eclass = ExprClass.Value;
48 			this.loc = loc;
49 		}
50 
ContainsEmitWithAwait()51 		public override bool ContainsEmitWithAwait ()
52 		{
53 			return arguments.ContainsEmitWithAwait ();
54 		}
55 
CreateExpressionTree(ResolveContext ec)56 		public override Expression CreateExpressionTree (ResolveContext ec)
57 		{
58 			if (expr_tree != null)
59 				return expr_tree (ec, new TypeOfMethod (oper, loc));
60 
61 			Arguments args = Arguments.CreateForExpressionTree (ec, arguments,
62 				new NullLiteral (loc),
63 				new TypeOfMethod (oper, loc));
64 
65 			return CreateExpressionFactoryCall (ec, "Call", args);
66 		}
67 
CloneTo(CloneContext context, Expression target)68 		protected override void CloneTo (CloneContext context, Expression target)
69 		{
70 			// Nothing to clone
71 		}
72 
DoResolve(ResolveContext ec)73 		protected override Expression DoResolve (ResolveContext ec)
74 		{
75 			//
76 			// We are born fully resolved
77 			//
78 			return this;
79 		}
80 
Emit(EmitContext ec)81 		public override void Emit (EmitContext ec)
82 		{
83 			var call = new CallEmitter ();
84 			call.Emit (ec, oper, arguments, loc);
85 		}
86 
FlowAnalysis(FlowAnalysisContext fc)87 		public override void FlowAnalysis (FlowAnalysisContext fc)
88 		{
89 			arguments.FlowAnalysis (fc);
90 		}
91 
MakeExpression(BuilderContext ctx)92 		public override SLE.Expression MakeExpression (BuilderContext ctx)
93 		{
94 #if STATIC
95 			return base.MakeExpression (ctx);
96 #else
97 			return SLE.Expression.Call ((MethodInfo) oper.GetMetaInfo (), Arguments.MakeExpression (arguments, ctx));
98 #endif
99 		}
100 	}
101 
102 	public class ParenthesizedExpression : ShimExpression
103 	{
ParenthesizedExpression(Expression expr, Location loc)104 		public ParenthesizedExpression (Expression expr, Location loc)
105 			: base (expr)
106 		{
107 			this.loc = loc;
108 		}
109 
DoResolve(ResolveContext rc)110 		protected override Expression DoResolve (ResolveContext rc)
111 		{
112 			Expression res = null;
113 			using (rc.With (ResolveContext.Options.DontSetConditionalAccessReceiver, false)) {
114 				res = expr.Resolve (rc);
115 			}
116 
117 			var constant = res as Constant;
118 			if (constant != null && constant.IsLiteral) {
119 				if (res is NullLiteral)
120 					return res;
121 
122 				return Constant.CreateConstantFromValue (res.Type, constant.GetValue (), expr.Location);
123 			}
124 
125 			return res;
126 		}
127 
DoResolveLValue(ResolveContext ec, Expression right_side)128 		public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
129 		{
130 			return expr.DoResolveLValue (ec, right_side);
131 		}
132 
Accept(StructuralVisitor visitor)133 		public override object Accept (StructuralVisitor visitor)
134 		{
135 			return visitor.Visit (this);
136 		}
137 
HasConditionalAccess()138 		public override bool HasConditionalAccess ()
139 		{
140 			return false;
141 		}
142 	}
143 
144 	//
145 	//   Unary implements unary expressions.
146 	//
147 	public class Unary : Expression
148 	{
149 		public enum Operator : byte {
150 			UnaryPlus, UnaryNegation, LogicalNot, OnesComplement,
151 			AddressOf,  TOP
152 		}
153 
154 		public readonly Operator Oper;
155 		public Expression Expr;
156 		ConvCast.Mode enum_conversion;
157 
Unary(Operator op, Expression expr, Location loc)158 		public Unary (Operator op, Expression expr, Location loc)
159 		{
160 			Oper = op;
161 			Expr = expr;
162 			this.loc = loc;
163 		}
164 
165 		// <summary>
166 		//   This routine will attempt to simplify the unary expression when the
167 		//   argument is a constant.
168 		// </summary>
TryReduceConstant(ResolveContext ec, Constant constant)169 		Constant TryReduceConstant (ResolveContext ec, Constant constant)
170 		{
171 			var e = constant;
172 
173 			while (e is EmptyConstantCast)
174 				e = ((EmptyConstantCast) e).child;
175 
176 			if (e is SideEffectConstant) {
177 				Constant r = TryReduceConstant (ec, ((SideEffectConstant) e).value);
178 				return r == null ? null : new SideEffectConstant (r, e, r.Location);
179 			}
180 
181 			TypeSpec expr_type = e.Type;
182 
183 			switch (Oper){
184 			case Operator.UnaryPlus:
185 				// Unary numeric promotions
186 				switch (expr_type.BuiltinType) {
187 				case BuiltinTypeSpec.Type.Byte:
188 					return new IntConstant (ec.BuiltinTypes, ((ByteConstant) e).Value, e.Location);
189 				case BuiltinTypeSpec.Type.SByte:
190 					return new IntConstant (ec.BuiltinTypes, ((SByteConstant) e).Value, e.Location);
191 				case BuiltinTypeSpec.Type.Short:
192 					return new IntConstant (ec.BuiltinTypes, ((ShortConstant) e).Value, e.Location);
193 				case BuiltinTypeSpec.Type.UShort:
194 					return new IntConstant (ec.BuiltinTypes, ((UShortConstant) e).Value, e.Location);
195 				case BuiltinTypeSpec.Type.Char:
196 					return new IntConstant (ec.BuiltinTypes, ((CharConstant) e).Value, e.Location);
197 
198 				// Predefined operators
199 				case BuiltinTypeSpec.Type.Int:
200 				case BuiltinTypeSpec.Type.UInt:
201 				case BuiltinTypeSpec.Type.Long:
202 				case BuiltinTypeSpec.Type.ULong:
203 				case BuiltinTypeSpec.Type.Float:
204 				case BuiltinTypeSpec.Type.Double:
205 				case BuiltinTypeSpec.Type.Decimal:
206 					return e;
207 				}
208 
209 				return null;
210 
211 			case Operator.UnaryNegation:
212 				// Unary numeric promotions
213 				switch (expr_type.BuiltinType) {
214 				case BuiltinTypeSpec.Type.Byte:
215 					return new IntConstant (ec.BuiltinTypes, -((ByteConstant) e).Value, e.Location);
216 				case BuiltinTypeSpec.Type.SByte:
217 					return new IntConstant (ec.BuiltinTypes, -((SByteConstant) e).Value, e.Location);
218 				case BuiltinTypeSpec.Type.Short:
219 					return new IntConstant (ec.BuiltinTypes, -((ShortConstant) e).Value, e.Location);
220 				case BuiltinTypeSpec.Type.UShort:
221 					return new IntConstant (ec.BuiltinTypes, -((UShortConstant) e).Value, e.Location);
222 				case BuiltinTypeSpec.Type.Char:
223 					return new IntConstant (ec.BuiltinTypes, -((CharConstant) e).Value, e.Location);
224 
225 				// Predefined operators
226 				case BuiltinTypeSpec.Type.Int:
227 					int ivalue = ((IntConstant) e).Value;
228 					if (ivalue == int.MinValue) {
229 						if (ec.ConstantCheckState) {
230 							ConstantFold.Error_CompileTimeOverflow (ec, loc);
231 							return null;
232 						}
233 						return e;
234 					}
235 					return new IntConstant (ec.BuiltinTypes, -ivalue, e.Location);
236 
237 				case BuiltinTypeSpec.Type.Long:
238 					long lvalue = ((LongConstant) e).Value;
239 					if (lvalue == long.MinValue) {
240 						if (ec.ConstantCheckState) {
241 							ConstantFold.Error_CompileTimeOverflow (ec, loc);
242 							return null;
243 						}
244 						return e;
245 					}
246 					return new LongConstant (ec.BuiltinTypes, -lvalue, e.Location);
247 
248 				case BuiltinTypeSpec.Type.UInt:
249 					UIntLiteral uil = constant as UIntLiteral;
250 					if (uil != null) {
251 						if (uil.Value == int.MaxValue + (uint) 1)
252 							return new IntLiteral (ec.BuiltinTypes, int.MinValue, e.Location);
253 						return new LongLiteral (ec.BuiltinTypes, -uil.Value, e.Location);
254 					}
255 					return new LongConstant (ec.BuiltinTypes, -((UIntConstant) e).Value, e.Location);
256 
257 
258 				case BuiltinTypeSpec.Type.ULong:
259 					ULongLiteral ull = constant as ULongLiteral;
260 					if (ull != null && ull.Value == 9223372036854775808)
261 						return new LongLiteral (ec.BuiltinTypes, long.MinValue, e.Location);
262 					return null;
263 
264 				case BuiltinTypeSpec.Type.Float:
265 					FloatLiteral fl = constant as FloatLiteral;
266 					// For better error reporting
267 					if (fl != null)
268 						return new FloatLiteral (ec.BuiltinTypes, -fl.Value, e.Location);
269 
270 					return new FloatConstant (ec.BuiltinTypes, -((FloatConstant) e).Value, e.Location);
271 
272 				case BuiltinTypeSpec.Type.Double:
273 					DoubleLiteral dl = constant as DoubleLiteral;
274 					// For better error reporting
275 					if (dl != null)
276 						return new DoubleLiteral (ec.BuiltinTypes, -dl.Value, e.Location);
277 
278 					return new DoubleConstant (ec.BuiltinTypes, -((DoubleConstant) e).Value, e.Location);
279 
280 				case BuiltinTypeSpec.Type.Decimal:
281 					return new DecimalConstant (ec.BuiltinTypes, -((DecimalConstant) e).Value, e.Location);
282 				}
283 
284 				return null;
285 
286 			case Operator.LogicalNot:
287 				if (expr_type.BuiltinType != BuiltinTypeSpec.Type.Bool)
288 					return null;
289 
290 				bool b = (bool)e.GetValue ();
291 				return new BoolConstant (ec.BuiltinTypes, !b, e.Location);
292 
293 			case Operator.OnesComplement:
294 				// Unary numeric promotions
295 				switch (expr_type.BuiltinType) {
296 				case BuiltinTypeSpec.Type.Byte:
297 					return new IntConstant (ec.BuiltinTypes, ~((ByteConstant) e).Value, e.Location);
298 				case BuiltinTypeSpec.Type.SByte:
299 					return new IntConstant (ec.BuiltinTypes, ~((SByteConstant) e).Value, e.Location);
300 				case BuiltinTypeSpec.Type.Short:
301 					return new IntConstant (ec.BuiltinTypes, ~((ShortConstant) e).Value, e.Location);
302 				case BuiltinTypeSpec.Type.UShort:
303 					return new IntConstant (ec.BuiltinTypes, ~((UShortConstant) e).Value, e.Location);
304 				case BuiltinTypeSpec.Type.Char:
305 					return new IntConstant (ec.BuiltinTypes, ~((CharConstant) e).Value, e.Location);
306 
307 				// Predefined operators
308 				case BuiltinTypeSpec.Type.Int:
309 					return new IntConstant (ec.BuiltinTypes, ~((IntConstant)e).Value, e.Location);
310 				case BuiltinTypeSpec.Type.UInt:
311 					return new UIntConstant (ec.BuiltinTypes, ~((UIntConstant) e).Value, e.Location);
312 				case BuiltinTypeSpec.Type.Long:
313 					return new LongConstant (ec.BuiltinTypes, ~((LongConstant) e).Value, e.Location);
314 				case BuiltinTypeSpec.Type.ULong:
315 					return new ULongConstant (ec.BuiltinTypes, ~((ULongConstant) e).Value, e.Location);
316 				}
317 				if (e is EnumConstant) {
318 					var res = TryReduceConstant (ec, ((EnumConstant)e).Child);
319 					if (res != null) {
320 						//
321 						// Numeric promotion upgraded types to int but for enum constant
322 						// original underlying constant type is needed
323 						//
324 						if (res.Type.BuiltinType == BuiltinTypeSpec.Type.Int) {
325 							int v = ((IntConstant) res).Value;
326 							switch (((EnumConstant) e).Child.Type.BuiltinType) {
327 								case BuiltinTypeSpec.Type.UShort:
328 								res = new UShortConstant (ec.BuiltinTypes, (ushort) v, e.Location);
329 								break;
330 								case BuiltinTypeSpec.Type.Short:
331 								res = new ShortConstant (ec.BuiltinTypes, (short) v, e.Location);
332 								break;
333 								case BuiltinTypeSpec.Type.Byte:
334 								res = new ByteConstant (ec.BuiltinTypes, (byte) v, e.Location);
335 								break;
336 								case BuiltinTypeSpec.Type.SByte:
337 								res = new SByteConstant (ec.BuiltinTypes, (sbyte) v, e.Location);
338 								break;
339 							}
340 						}
341 
342 						res = new EnumConstant (res, expr_type);
343 					}
344 					return res;
345 				}
346 				return null;
347 			}
348 			throw new Exception ("Can not constant fold: " + Oper.ToString());
349 		}
350 
ResolveOperator(ResolveContext ec, Expression expr)351 		protected virtual Expression ResolveOperator (ResolveContext ec, Expression expr)
352 		{
353 			eclass = ExprClass.Value;
354 
355 			TypeSpec expr_type = expr.Type;
356 			Expression best_expr;
357 
358 			TypeSpec[] predefined = ec.BuiltinTypes.OperatorsUnary [(int) Oper];
359 
360 			//
361 			// Primitive types first
362 			//
363 			if (BuiltinTypeSpec.IsPrimitiveType (expr_type)) {
364 				best_expr = ResolvePrimitivePredefinedType (ec, expr, predefined);
365 				if (best_expr == null)
366 					return null;
367 
368 				type = best_expr.Type;
369 				Expr = best_expr;
370 				return this;
371 			}
372 
373 			//
374 			// E operator ~(E x);
375 			//
376 			if (Oper == Operator.OnesComplement && expr_type.IsEnum)
377 				return ResolveEnumOperator (ec, expr, predefined);
378 
379 			return ResolveUserType (ec, expr, predefined);
380 		}
381 
ResolveEnumOperator(ResolveContext ec, Expression expr, TypeSpec[] predefined)382 		protected virtual Expression ResolveEnumOperator (ResolveContext ec, Expression expr, TypeSpec[] predefined)
383 		{
384 			TypeSpec underlying_type = EnumSpec.GetUnderlyingType (expr.Type);
385 			Expression best_expr = ResolvePrimitivePredefinedType (ec, EmptyCast.Create (expr, underlying_type), predefined);
386 			if (best_expr == null)
387 				return null;
388 
389 			Expr = best_expr;
390 			enum_conversion = Binary.GetEnumResultCast (underlying_type);
391 			type = expr.Type;
392 			return EmptyCast.Create (this, type);
393 		}
394 
ContainsEmitWithAwait()395 		public override bool ContainsEmitWithAwait ()
396 		{
397 			return Expr.ContainsEmitWithAwait ();
398 		}
399 
CreateExpressionTree(ResolveContext ec)400 		public override Expression CreateExpressionTree (ResolveContext ec)
401 		{
402 			return CreateExpressionTree (ec, null);
403 		}
404 
CreateExpressionTree(ResolveContext ec, Expression user_op)405 		Expression CreateExpressionTree (ResolveContext ec, Expression user_op)
406 		{
407 			string method_name;
408 			switch (Oper) {
409 			case Operator.AddressOf:
410 				Error_PointerInsideExpressionTree (ec);
411 				return null;
412 			case Operator.UnaryNegation:
413 				if (ec.HasSet (ResolveContext.Options.CheckedScope) && user_op == null && !IsFloat (type))
414 					method_name = "NegateChecked";
415 				else
416 					method_name = "Negate";
417 				break;
418 			case Operator.OnesComplement:
419 			case Operator.LogicalNot:
420 				method_name = "Not";
421 				break;
422 			case Operator.UnaryPlus:
423 				method_name = "UnaryPlus";
424 				break;
425 			default:
426 				throw new InternalErrorException ("Unknown unary operator " + Oper.ToString ());
427 			}
428 
429 			Arguments args = new Arguments (2);
430 			args.Add (new Argument (Expr.CreateExpressionTree (ec)));
431 			if (user_op != null)
432 				args.Add (new Argument (user_op));
433 
434 			return CreateExpressionFactoryCall (ec, method_name, args);
435 		}
436 
CreatePredefinedOperatorsTable(BuiltinTypes types)437 		public static TypeSpec[][] CreatePredefinedOperatorsTable (BuiltinTypes types)
438 		{
439 			var predefined_operators = new TypeSpec[(int) Operator.TOP][];
440 
441 			//
442 			// 7.6.1 Unary plus operator
443 			//
444 			predefined_operators [(int) Operator.UnaryPlus] = new TypeSpec [] {
445 				types.Int, types.UInt,
446 				types.Long, types.ULong,
447 				types.Float, types.Double,
448 				types.Decimal
449 			};
450 
451 			//
452 			// 7.6.2 Unary minus operator
453 			//
454 			predefined_operators [(int) Operator.UnaryNegation] = new TypeSpec [] {
455 				types.Int,  types.Long,
456 				types.Float, types.Double,
457 				types.Decimal
458 			};
459 
460 			//
461 			// 7.6.3 Logical negation operator
462 			//
463 			predefined_operators [(int) Operator.LogicalNot] = new TypeSpec [] {
464 				types.Bool
465 			};
466 
467 			//
468 			// 7.6.4 Bitwise complement operator
469 			//
470 			predefined_operators [(int) Operator.OnesComplement] = new TypeSpec [] {
471 				types.Int, types.UInt,
472 				types.Long, types.ULong
473 			};
474 
475 			return predefined_operators;
476 		}
477 
478 		//
479 		// Unary numeric promotions
480 		//
DoNumericPromotion(ResolveContext rc, Operator op, Expression expr)481 		static Expression DoNumericPromotion (ResolveContext rc, Operator op, Expression expr)
482 		{
483 			TypeSpec expr_type = expr.Type;
484 			if (op == Operator.UnaryPlus || op == Operator.UnaryNegation || op == Operator.OnesComplement) {
485 				switch (expr_type.BuiltinType) {
486 				case BuiltinTypeSpec.Type.Byte:
487 				case BuiltinTypeSpec.Type.SByte:
488 				case BuiltinTypeSpec.Type.Short:
489 				case BuiltinTypeSpec.Type.UShort:
490 				case BuiltinTypeSpec.Type.Char:
491 					return Convert.ImplicitNumericConversion (expr, rc.BuiltinTypes.Int);
492 				}
493 			}
494 
495 			if (op == Operator.UnaryNegation && expr_type.BuiltinType == BuiltinTypeSpec.Type.UInt)
496 				return Convert.ImplicitNumericConversion (expr, rc.BuiltinTypes.Long);
497 
498 			return expr;
499 		}
500 
DoResolve(ResolveContext ec)501 		protected override Expression DoResolve (ResolveContext ec)
502 		{
503 			if (Oper == Operator.AddressOf) {
504 				return ResolveAddressOf (ec);
505 			}
506 
507 			Expr = Expr.Resolve (ec);
508 			if (Expr == null)
509 				return null;
510 
511 			if (Expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
512 				Arguments args = new Arguments (1);
513 				args.Add (new Argument (Expr));
514 				return new DynamicUnaryConversion (GetOperatorExpressionTypeName (), args, loc).Resolve (ec);
515 			}
516 
517 			if (Expr.Type.IsNullableType)
518 				return new Nullable.LiftedUnaryOperator (Oper, Expr, loc).Resolve (ec);
519 
520 			//
521 			// Attempt to use a constant folding operation.
522 			//
523 			Constant cexpr = Expr as Constant;
524 			if (cexpr != null) {
525 				cexpr = TryReduceConstant (ec, cexpr);
526 				if (cexpr != null)
527 					return cexpr;
528 			}
529 
530 			Expression expr = ResolveOperator (ec, Expr);
531 			if (expr == null)
532 				Error_OperatorCannotBeApplied (ec, loc, OperName (Oper), Expr.Type);
533 
534 			//
535 			// Reduce unary operator on predefined types
536 			//
537 			if (expr == this && Oper == Operator.UnaryPlus)
538 				return Expr;
539 
540 			return expr;
541 		}
542 
DoResolveLValue(ResolveContext ec, Expression right)543 		public override Expression DoResolveLValue (ResolveContext ec, Expression right)
544 		{
545 			return null;
546 		}
547 
Emit(EmitContext ec)548 		public override void Emit (EmitContext ec)
549 		{
550 			EmitOperator (ec, type);
551 		}
552 
EmitOperator(EmitContext ec, TypeSpec type)553 		protected void EmitOperator (EmitContext ec, TypeSpec type)
554 		{
555 			switch (Oper) {
556 			case Operator.UnaryPlus:
557 				Expr.Emit (ec);
558 				break;
559 
560 			case Operator.UnaryNegation:
561 				if (ec.HasSet (EmitContext.Options.CheckedScope) && !IsFloat (type)) {
562 					if (ec.HasSet (BuilderContext.Options.AsyncBody) && Expr.ContainsEmitWithAwait ())
563 						Expr = Expr.EmitToField (ec);
564 
565 					ec.EmitInt (0);
566 					if (type.BuiltinType == BuiltinTypeSpec.Type.Long)
567 						ec.Emit (OpCodes.Conv_U8);
568 					Expr.Emit (ec);
569 					ec.Emit (OpCodes.Sub_Ovf);
570 				} else {
571 					Expr.Emit (ec);
572 					ec.Emit (OpCodes.Neg);
573 				}
574 
575 				break;
576 
577 			case Operator.LogicalNot:
578 				Expr.Emit (ec);
579 				ec.EmitInt (0);
580 				ec.Emit (OpCodes.Ceq);
581 				break;
582 
583 			case Operator.OnesComplement:
584 				Expr.Emit (ec);
585 				ec.Emit (OpCodes.Not);
586 				break;
587 
588 			case Operator.AddressOf:
589 				((IMemoryLocation)Expr).AddressOf (ec, AddressOp.LoadStore);
590 				break;
591 
592 			default:
593 				throw new Exception ("This should not happen: Operator = "
594 						     + Oper.ToString ());
595 			}
596 
597 			//
598 			// Same trick as in Binary expression
599 			//
600 			if (enum_conversion != 0) {
601 				using (ec.With (BuilderContext.Options.CheckedScope, false)) {
602 					ConvCast.Emit (ec, enum_conversion);
603 				}
604 			}
605 		}
606 
EmitBranchable(EmitContext ec, Label target, bool on_true)607 		public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
608 		{
609 			if (Oper == Operator.LogicalNot)
610 				Expr.EmitBranchable (ec, target, !on_true);
611 			else
612 				base.EmitBranchable (ec, target, on_true);
613 		}
614 
EmitSideEffect(EmitContext ec)615 		public override void EmitSideEffect (EmitContext ec)
616 		{
617 			Expr.EmitSideEffect (ec);
618 		}
619 
Error_Ambiguous(ResolveContext rc, string oper, TypeSpec type, Location loc)620 		public static void Error_Ambiguous (ResolveContext rc, string oper, TypeSpec type, Location loc)
621 		{
622 			rc.Report.Error (35, loc, "Operator `{0}' is ambiguous on an operand of type `{1}'",
623 				oper, type.GetSignatureForError ());
624 		}
625 
FlowAnalysis(FlowAnalysisContext fc)626 		public override void FlowAnalysis (FlowAnalysisContext fc)
627 		{
628 			FlowAnalysis (fc, false);
629 		}
630 
FlowAnalysisConditional(FlowAnalysisContext fc)631 		public override void FlowAnalysisConditional (FlowAnalysisContext fc)
632 		{
633 			FlowAnalysis (fc, true);
634 		}
635 
FlowAnalysis(FlowAnalysisContext fc, bool conditional)636 		void FlowAnalysis (FlowAnalysisContext fc, bool conditional)
637 		{
638 			if (Oper == Operator.AddressOf) {
639 				var vr = Expr as VariableReference;
640 				if (vr != null && vr.VariableInfo != null)
641 					fc.SetVariableAssigned (vr.VariableInfo);
642 
643 				return;
644 			}
645 
646 			if (Oper == Operator.LogicalNot && conditional) {
647 				Expr.FlowAnalysisConditional (fc);
648 
649 				var temp = fc.DefiniteAssignmentOnTrue;
650 				fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse;
651 				fc.DefiniteAssignmentOnFalse = temp;
652 			} else {
653 				Expr.FlowAnalysis (fc);
654 			}
655 		}
656 
657 		//
658 		// Converts operator to System.Linq.Expressions.ExpressionType enum name
659 		//
GetOperatorExpressionTypeName()660 		string GetOperatorExpressionTypeName ()
661 		{
662 			switch (Oper) {
663 			case Operator.OnesComplement:
664 				return "OnesComplement";
665 			case Operator.LogicalNot:
666 				return "Not";
667 			case Operator.UnaryNegation:
668 				return "Negate";
669 			case Operator.UnaryPlus:
670 				return "UnaryPlus";
671 			default:
672 				throw new NotImplementedException ("Unknown express type operator " + Oper.ToString ());
673 			}
674 		}
675 
IsFloat(TypeSpec t)676 		static bool IsFloat (TypeSpec t)
677 		{
678 			return t.BuiltinType == BuiltinTypeSpec.Type.Double || t.BuiltinType == BuiltinTypeSpec.Type.Float;
679 		}
680 
681 		//
682 		// Returns a stringified representation of the Operator
683 		//
OperName(Operator oper)684 		public static string OperName (Operator oper)
685 		{
686 			switch (oper) {
687 			case Operator.UnaryPlus:
688 				return "+";
689 			case Operator.UnaryNegation:
690 				return "-";
691 			case Operator.LogicalNot:
692 				return "!";
693 			case Operator.OnesComplement:
694 				return "~";
695 			case Operator.AddressOf:
696 				return "&";
697 			}
698 
699 			throw new NotImplementedException (oper.ToString ());
700 		}
701 
MakeExpression(BuilderContext ctx)702 		public override SLE.Expression MakeExpression (BuilderContext ctx)
703 		{
704 			var expr = Expr.MakeExpression (ctx);
705 			bool is_checked = ctx.HasSet (BuilderContext.Options.CheckedScope);
706 
707 			switch (Oper) {
708 			case Operator.UnaryNegation:
709 				return is_checked ? SLE.Expression.NegateChecked (expr) : SLE.Expression.Negate (expr);
710 			case Operator.LogicalNot:
711 				return SLE.Expression.Not (expr);
712 			case Operator.OnesComplement:
713 				return SLE.Expression.OnesComplement (expr);
714 			default:
715 				throw new NotImplementedException (Oper.ToString ());
716 			}
717 		}
718 
ResolveAddressOf(ResolveContext ec)719 		Expression ResolveAddressOf (ResolveContext ec)
720 		{
721 			if (ec.CurrentIterator != null) {
722 				UnsafeInsideIteratorError (ec, loc);
723 			} else if (!ec.IsUnsafe) {
724 				UnsafeError (ec, loc);
725 			}
726 
727 			Expr = Expr.DoResolveLValue (ec, EmptyExpression.UnaryAddress);
728 			if (Expr == null || Expr.eclass != ExprClass.Variable) {
729 				ec.Report.Error (211, loc, "Cannot take the address of the given expression");
730 				return null;
731 			}
732 
733 			if (!TypeManager.VerifyUnmanaged (ec.Module, Expr.Type, loc)) {
734 				return null;
735 			}
736 
737 			IVariableReference vr = Expr as IVariableReference;
738 			bool is_fixed;
739 			if (vr != null) {
740 				is_fixed = vr.IsFixed;
741 				vr.SetHasAddressTaken ();
742 
743 				if (vr.IsHoisted && ec.CurrentIterator == null) {
744 					AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, vr, loc);
745 				}
746 			} else {
747 				IFixedExpression fe = Expr as IFixedExpression;
748 				is_fixed = fe != null && fe.IsFixed;
749 			}
750 
751 			if (!is_fixed && !ec.HasSet (ResolveContext.Options.FixedInitializerScope)) {
752 				ec.Report.Error (212, loc, "You can only take the address of unfixed expression inside of a fixed statement initializer");
753 			}
754 
755 			type = PointerContainer.MakeType (ec.Module, Expr.Type);
756 			eclass = ExprClass.Value;
757 			return this;
758 		}
759 
ResolvePrimitivePredefinedType(ResolveContext rc, Expression expr, TypeSpec[] predefined)760 		Expression ResolvePrimitivePredefinedType (ResolveContext rc, Expression expr, TypeSpec[] predefined)
761 		{
762 			expr = DoNumericPromotion (rc, Oper, expr);
763 			TypeSpec expr_type = expr.Type;
764 			foreach (TypeSpec t in predefined) {
765 				if (t == expr_type)
766 					return expr;
767 			}
768 			return null;
769 		}
770 
771 		//
772 		// Perform user-operator overload resolution
773 		//
ResolveUserOperator(ResolveContext ec, Expression expr)774 		protected virtual Expression ResolveUserOperator (ResolveContext ec, Expression expr)
775 		{
776 			CSharp.Operator.OpType op_type;
777 			switch (Oper) {
778 			case Operator.LogicalNot:
779 				op_type = CSharp.Operator.OpType.LogicalNot; break;
780 			case Operator.OnesComplement:
781 				op_type = CSharp.Operator.OpType.OnesComplement; break;
782 			case Operator.UnaryNegation:
783 				op_type = CSharp.Operator.OpType.UnaryNegation; break;
784 			case Operator.UnaryPlus:
785 				op_type = CSharp.Operator.OpType.UnaryPlus; break;
786 			default:
787 				throw new InternalErrorException (Oper.ToString ());
788 			}
789 
790 			var methods = MemberCache.GetUserOperator (expr.Type, op_type, false);
791 			if (methods == null)
792 				return null;
793 
794 			Arguments args = new Arguments (1);
795 			args.Add (new Argument (expr));
796 
797 			var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc);
798 			var oper = res.ResolveOperator (ec, ref args);
799 
800 			if (oper == null)
801 				return null;
802 
803 			Expr = args [0].Expr;
804 			return new UserOperatorCall (oper, args, CreateExpressionTree, expr.Location);
805 		}
806 
807 		//
808 		// Unary user type overload resolution
809 		//
ResolveUserType(ResolveContext ec, Expression expr, TypeSpec[] predefined)810 		Expression ResolveUserType (ResolveContext ec, Expression expr, TypeSpec[] predefined)
811 		{
812 			Expression best_expr = ResolveUserOperator (ec, expr);
813 			if (best_expr != null)
814 				return best_expr;
815 
816 			foreach (TypeSpec t in predefined) {
817 				Expression oper_expr = Convert.ImplicitUserConversion (ec, expr, t, expr.Location);
818 				if (oper_expr == null)
819 					continue;
820 
821 				if (oper_expr == ErrorExpression.Instance)
822 					return oper_expr;
823 
824 				//
825 				// decimal type is predefined but has user-operators
826 				//
827 				if (oper_expr.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal)
828 					oper_expr = ResolveUserType (ec, oper_expr, predefined);
829 				else
830 					oper_expr = ResolvePrimitivePredefinedType (ec, oper_expr, predefined);
831 
832 				if (oper_expr == null)
833 					continue;
834 
835 				if (best_expr == null) {
836 					best_expr = oper_expr;
837 					continue;
838 				}
839 
840 				int result = OverloadResolver.BetterTypeConversion (ec, best_expr.Type, t);
841 				if (result == 0) {
842 					if ((oper_expr is UserOperatorCall || oper_expr is UserCast) && (best_expr is UserOperatorCall || best_expr is UserCast)) {
843 						Error_Ambiguous (ec, OperName (Oper), expr.Type, loc);
844 					} else {
845 						Error_OperatorCannotBeApplied (ec, loc, OperName (Oper), expr.Type);
846 					}
847 
848 					break;
849 				}
850 
851 				if (result == 2)
852 					best_expr = oper_expr;
853 			}
854 
855 			if (best_expr == null)
856 				return null;
857 
858 			//
859 			// HACK: Decimal user-operator is included in standard operators
860 			//
861 			if (best_expr.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal)
862 				return best_expr;
863 
864 			Expr = best_expr;
865 			type = best_expr.Type;
866 			return this;
867 		}
868 
CloneTo(CloneContext clonectx, Expression t)869 		protected override void CloneTo (CloneContext clonectx, Expression t)
870 		{
871 			Unary target = (Unary) t;
872 
873 			target.Expr = Expr.Clone (clonectx);
874 		}
875 
Accept(StructuralVisitor visitor)876 		public override object Accept (StructuralVisitor visitor)
877 		{
878 			return visitor.Visit (this);
879 		}
880 
881 	}
882 
883 	//
884 	// Unary operators are turned into Indirection expressions
885 	// after semantic analysis (this is so we can take the address
886 	// of an indirection).
887 	//
888 	public class Indirection : Expression, IMemoryLocation, IAssignMethod, IFixedExpression {
889 		Expression expr;
890 		LocalTemporary temporary;
891 		bool prepared;
892 
Indirection(Expression expr, Location l)893 		public Indirection (Expression expr, Location l)
894 		{
895 			this.expr = expr;
896 			loc = l;
897 		}
898 
899 		public Expression Expr {
900 			get {
901 				return expr;
902 			}
903 		}
904 
905 		public bool IsFixed {
906 			get { return true; }
907 		}
908 
909 		public override Location StartLocation {
910 			get {
911 				return expr.StartLocation;
912 			}
913 		}
914 
CloneTo(CloneContext clonectx, Expression t)915 		protected override void CloneTo (CloneContext clonectx, Expression t)
916 		{
917 			Indirection target = (Indirection) t;
918 			target.expr = expr.Clone (clonectx);
919 		}
920 
ContainsEmitWithAwait()921 		public override bool ContainsEmitWithAwait ()
922 		{
923 			throw new NotImplementedException ();
924 		}
925 
CreateExpressionTree(ResolveContext ec)926 		public override Expression CreateExpressionTree (ResolveContext ec)
927 		{
928 			Error_PointerInsideExpressionTree (ec);
929 			return null;
930 		}
931 
Emit(EmitContext ec)932 		public override void Emit (EmitContext ec)
933 		{
934 			if (!prepared)
935 				expr.Emit (ec);
936 
937 			ec.EmitLoadFromPtr (Type);
938 		}
939 
Emit(EmitContext ec, bool leave_copy)940 		public void Emit (EmitContext ec, bool leave_copy)
941 		{
942 			Emit (ec);
943 			if (leave_copy) {
944 				ec.Emit (OpCodes.Dup);
945 				temporary = new LocalTemporary (expr.Type);
946 				temporary.Store (ec);
947 			}
948 		}
949 
EmitAssign(EmitContext ec, Expression source, bool leave_copy, bool isCompound)950 		public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
951 		{
952 			prepared = isCompound;
953 
954 			expr.Emit (ec);
955 
956 			if (isCompound)
957 				ec.Emit (OpCodes.Dup);
958 
959 			source.Emit (ec);
960 			if (leave_copy) {
961 				ec.Emit (OpCodes.Dup);
962 				temporary = new LocalTemporary (source.Type);
963 				temporary.Store (ec);
964 			}
965 
966 			ec.EmitStoreFromPtr (type);
967 
968 			if (temporary != null) {
969 				temporary.Emit (ec);
970 				temporary.Release (ec);
971 			}
972 		}
973 
AddressOf(EmitContext ec, AddressOp Mode)974 		public void AddressOf (EmitContext ec, AddressOp Mode)
975 		{
976 			expr.Emit (ec);
977 		}
978 
DoResolveLValue(ResolveContext ec, Expression right_side)979 		public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
980 		{
981 			return DoResolve (ec);
982 		}
983 
DoResolve(ResolveContext ec)984 		protected override Expression DoResolve (ResolveContext ec)
985 		{
986 			expr = expr.Resolve (ec);
987 			if (expr == null)
988 				return null;
989 
990 			if (ec.CurrentIterator != null) {
991 				UnsafeInsideIteratorError (ec, loc);
992 			} else if (!ec.IsUnsafe) {
993 				UnsafeError (ec, loc);
994 			}
995 
996 			var pc = expr.Type as PointerContainer;
997 
998 			if (pc == null) {
999 				ec.Report.Error (193, loc, "The * or -> operator must be applied to a pointer");
1000 				return null;
1001 			}
1002 
1003 			type = pc.Element;
1004 
1005 			if (type.Kind == MemberKind.Void) {
1006 				Error_VoidPointerOperation (ec);
1007 				return null;
1008 			}
1009 
1010 			eclass = ExprClass.Variable;
1011 			return this;
1012 		}
1013 
Accept(StructuralVisitor visitor)1014 		public override object Accept (StructuralVisitor visitor)
1015 		{
1016 			return visitor.Visit (this);
1017 		}
1018 	}
1019 
1020 	/// <summary>
1021 	///   Unary Mutator expressions (pre and post ++ and --)
1022 	/// </summary>
1023 	///
1024 	/// <remarks>
1025 	///   UnaryMutator implements ++ and -- expressions.   It derives from
1026 	///   ExpressionStatement becuase the pre/post increment/decrement
1027 	///   operators can be used in a statement context.
1028 	///
1029 	/// FIXME: Idea, we could split this up in two classes, one simpler
1030 	/// for the common case, and one with the extra fields for more complex
1031 	/// classes (indexers require temporary access;  overloaded require method)
1032 	///
1033 	/// </remarks>
1034 	public class UnaryMutator : ExpressionStatement
1035 	{
1036 		class DynamicPostMutator : Expression, IAssignMethod
1037 		{
1038 			LocalTemporary temp;
1039 			Expression expr;
1040 
DynamicPostMutator(Expression expr)1041 			public DynamicPostMutator (Expression expr)
1042 			{
1043 				this.expr = expr;
1044 				this.type = expr.Type;
1045 				this.loc = expr.Location;
1046 			}
1047 
CreateExpressionTree(ResolveContext ec)1048 			public override Expression CreateExpressionTree (ResolveContext ec)
1049 			{
1050 				throw new NotImplementedException ("ET");
1051 			}
1052 
DoResolve(ResolveContext rc)1053 			protected override Expression DoResolve (ResolveContext rc)
1054 			{
1055 				eclass = expr.eclass;
1056 				return this;
1057 			}
1058 
DoResolveLValue(ResolveContext ec, Expression right_side)1059 			public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
1060 			{
1061 				expr.DoResolveLValue (ec, right_side);
1062 				return DoResolve (ec);
1063 			}
1064 
Emit(EmitContext ec)1065 			public override void Emit (EmitContext ec)
1066 			{
1067 				temp.Emit (ec);
1068 			}
1069 
Emit(EmitContext ec, bool leave_copy)1070 			public void Emit (EmitContext ec, bool leave_copy)
1071 			{
1072 				throw new NotImplementedException ();
1073 			}
1074 
1075 			//
1076 			// Emits target assignment using unmodified source value
1077 			//
EmitAssign(EmitContext ec, Expression source, bool leave_copy, bool isCompound)1078 			public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
1079 			{
1080 				//
1081 				// Allocate temporary variable to keep original value before it's modified
1082 				//
1083 				temp = new LocalTemporary (type);
1084 				expr.Emit (ec);
1085 				temp.Store (ec);
1086 
1087 				((IAssignMethod) expr).EmitAssign (ec, source, false, isCompound);
1088 
1089 				if (leave_copy)
1090 					Emit (ec);
1091 
1092 				temp.Release (ec);
1093 				temp = null;
1094 			}
1095 		}
1096 
1097 		[Flags]
1098 		public enum Mode : byte {
1099 			IsIncrement    = 0,
1100 			IsDecrement    = 1,
1101 			IsPre          = 0,
1102 			IsPost         = 2,
1103 
1104 			PreIncrement   = 0,
1105 			PreDecrement   = IsDecrement,
1106 			PostIncrement  = IsPost,
1107 			PostDecrement  = IsPost | IsDecrement
1108 		}
1109 
1110 		Mode mode;
1111 		bool is_expr, recurse;
1112 
1113 		protected Expression expr;
1114 
1115 		// Holds the real operation
1116 		Expression operation;
1117 
UnaryMutator(Mode m, Expression e, Location loc)1118 		public UnaryMutator (Mode m, Expression e, Location loc)
1119 		{
1120 			mode = m;
1121 			this.loc = loc;
1122 			expr = e;
1123 		}
1124 
1125 		public Mode UnaryMutatorMode {
1126 			get {
1127 				return mode;
1128 			}
1129 		}
1130 
1131 		public Expression Expr {
1132 			get {
1133 				return expr;
1134 			}
1135 		}
1136 
1137 		public override Location StartLocation {
1138 			get {
1139 				return (mode & Mode.IsPost) != 0 ? expr.Location : loc;
1140 			}
1141 		}
1142 
ContainsEmitWithAwait()1143 		public override bool ContainsEmitWithAwait ()
1144 		{
1145 			return expr.ContainsEmitWithAwait ();
1146 		}
1147 
CreateExpressionTree(ResolveContext ec)1148 		public override Expression CreateExpressionTree (ResolveContext ec)
1149 		{
1150 			return new SimpleAssign (this, this).CreateExpressionTree (ec);
1151 		}
1152 
CreatePredefinedOperatorsTable(BuiltinTypes types)1153 		public static TypeSpec[] CreatePredefinedOperatorsTable (BuiltinTypes types)
1154 		{
1155 			//
1156 			// Predefined ++ and -- operators exist for the following types:
1157 			// sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal
1158 			//
1159 			return new TypeSpec[] {
1160 				types.Int,
1161 				types.Long,
1162 
1163 				types.SByte,
1164 				types.Byte,
1165 				types.Short,
1166 				types.UInt,
1167 				types.ULong,
1168 				types.Char,
1169 				types.Float,
1170 				types.Double,
1171 				types.Decimal
1172 			};
1173 		}
1174 
DoResolve(ResolveContext ec)1175 		protected override Expression DoResolve (ResolveContext ec)
1176 		{
1177 			expr = expr.Resolve (ec);
1178 
1179 			if (expr == null || expr.Type == InternalType.ErrorType)
1180 				return null;
1181 
1182 			if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1183 				//
1184 				// Handle postfix unary operators using local
1185 				// temporary variable
1186 				//
1187 				if ((mode & Mode.IsPost) != 0)
1188 					expr = new DynamicPostMutator (expr);
1189 
1190 				Arguments args = new Arguments (1);
1191 				args.Add (new Argument (expr));
1192 				return new SimpleAssign (expr, new DynamicUnaryConversion (GetOperatorExpressionTypeName (), args, loc)).Resolve (ec);
1193 			}
1194 
1195 			if (expr.Type.IsNullableType)
1196 				return new Nullable.LiftedUnaryMutator (mode, expr, loc).Resolve (ec);
1197 
1198 			return DoResolveOperation (ec);
1199 		}
1200 
DoResolveOperation(ResolveContext ec)1201 		protected Expression DoResolveOperation (ResolveContext ec)
1202 		{
1203 			eclass = ExprClass.Value;
1204 			type = expr.Type;
1205 
1206 			if (expr is RuntimeValueExpression) {
1207 				operation = expr;
1208 			} else {
1209 				// Use itself at the top of the stack
1210 				operation = new EmptyExpression (type);
1211 			}
1212 
1213 			//
1214 			// The operand of the prefix/postfix increment decrement operators
1215 			// should be an expression that is classified as a variable,
1216 			// a property access or an indexer access
1217 			//
1218 			// TODO: Move to parser, expr is ATypeNameExpression
1219 			if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) {
1220 				expr = expr.ResolveLValue (ec, expr);
1221 			} else {
1222 				ec.Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer");
1223 				return null;
1224 			}
1225 
1226 			//
1227 			// Step 1: Try to find a user operator, it has priority over predefined ones
1228 			//
1229 			var user_op = IsDecrement ? Operator.OpType.Decrement : Operator.OpType.Increment;
1230 			var methods = MemberCache.GetUserOperator (type, user_op, false);
1231 
1232 			if (methods != null) {
1233 				Arguments args = new Arguments (1);
1234 				args.Add (new Argument (expr));
1235 
1236 				var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc);
1237 				var method = res.ResolveOperator (ec, ref args);
1238 				if (method == null)
1239 					return null;
1240 
1241 				args[0].Expr = operation;
1242 				operation = new UserOperatorCall (method, args, null, loc);
1243 				operation = Convert.ImplicitConversionRequired (ec, operation, type, loc);
1244 				return this;
1245 			}
1246 
1247 			//
1248 			// Step 2: Try predefined types
1249 			//
1250 
1251 			Expression source = null;
1252 			bool primitive_type;
1253 
1254 			//
1255 			// Predefined without user conversion first for speed-up
1256 			//
1257 			// Predefined ++ and -- operators exist for the following types:
1258 			// sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal
1259 			//
1260 			switch (type.BuiltinType) {
1261 			case BuiltinTypeSpec.Type.Byte:
1262 			case BuiltinTypeSpec.Type.SByte:
1263 			case BuiltinTypeSpec.Type.Short:
1264 			case BuiltinTypeSpec.Type.UShort:
1265 			case BuiltinTypeSpec.Type.Int:
1266 			case BuiltinTypeSpec.Type.UInt:
1267 			case BuiltinTypeSpec.Type.Long:
1268 			case BuiltinTypeSpec.Type.ULong:
1269 			case BuiltinTypeSpec.Type.Char:
1270 			case BuiltinTypeSpec.Type.Float:
1271 			case BuiltinTypeSpec.Type.Double:
1272 			case BuiltinTypeSpec.Type.Decimal:
1273 				source = operation;
1274 				primitive_type = true;
1275 				break;
1276 			default:
1277 				primitive_type = false;
1278 
1279 				// ++/-- on pointer variables of all types except void*
1280 				if (type.IsPointer) {
1281 					if (((PointerContainer) type).Element.Kind == MemberKind.Void) {
1282 						Error_VoidPointerOperation (ec);
1283 						return null;
1284 					}
1285 
1286 					source = operation;
1287 				} else {
1288 					Expression best_source = null;
1289 					foreach (var t in ec.BuiltinTypes.OperatorsUnaryMutator) {
1290 						source = Convert.ImplicitUserConversion (ec, operation, t, loc);
1291 
1292 						// LAMESPEC: It should error on ambiguous operators but that would make us incompatible
1293 						if (source == null)
1294 							continue;
1295 
1296 						if (best_source == null) {
1297 							best_source = source;
1298 							continue;
1299 						}
1300 
1301 						var better = OverloadResolver.BetterTypeConversion (ec, best_source.Type, source.Type);
1302 						if (better == 1)
1303 							continue;
1304 
1305 						if (better == 2) {
1306 							best_source = source;
1307 							continue;
1308 						}
1309 
1310 						Unary.Error_Ambiguous (ec, OperName (mode), type, loc);
1311 						break;
1312 					}
1313 
1314 					source = best_source;
1315 				}
1316 
1317 				// ++/-- on enum types
1318 				if (source == null && type.IsEnum)
1319 					source = operation;
1320 
1321 				if (source == null) {
1322 					expr.Error_OperatorCannotBeApplied (ec, loc, Operator.GetName (user_op), type);
1323 					return null;
1324 				}
1325 
1326 				break;
1327 			}
1328 
1329 			var one = new IntConstant (ec.BuiltinTypes, 1, loc);
1330 			var op = IsDecrement ? Binary.Operator.Subtraction : Binary.Operator.Addition;
1331 			operation = new Binary (op, source, one);
1332 			operation = operation.Resolve (ec);
1333 			if (operation == null)
1334 				throw new NotImplementedException ("should not be reached");
1335 
1336 			if (operation.Type != type) {
1337 				if (primitive_type)
1338 					operation = Convert.ExplicitNumericConversion (ec, operation, type);
1339 				else
1340 					operation = Convert.ImplicitConversionRequired (ec, operation, type, loc);
1341 			}
1342 
1343 			return this;
1344 		}
1345 
EmitCode(EmitContext ec, bool is_expr)1346 		void EmitCode (EmitContext ec, bool is_expr)
1347 		{
1348 			recurse = true;
1349 			this.is_expr = is_expr;
1350 			((IAssignMethod) expr).EmitAssign (ec, this, is_expr && (mode == Mode.PreIncrement || mode == Mode.PreDecrement), true);
1351 		}
1352 
Emit(EmitContext ec)1353 		public override void Emit (EmitContext ec)
1354 		{
1355 			//
1356 			// We use recurse to allow ourselfs to be the source
1357 			// of an assignment. This little hack prevents us from
1358 			// having to allocate another expression
1359 			//
1360 			if (recurse) {
1361 				((IAssignMethod) expr).Emit (ec, is_expr && (mode == Mode.PostIncrement || mode == Mode.PostDecrement));
1362 
1363 				EmitOperation (ec);
1364 
1365 				recurse = false;
1366 				return;
1367 			}
1368 
1369 			EmitCode (ec, true);
1370 		}
1371 
EmitOperation(EmitContext ec)1372 		protected virtual void EmitOperation (EmitContext ec)
1373 		{
1374 			operation.Emit (ec);
1375 		}
1376 
EmitStatement(EmitContext ec)1377 		public override void EmitStatement (EmitContext ec)
1378 		{
1379 			EmitCode (ec, false);
1380 		}
1381 
FlowAnalysis(FlowAnalysisContext fc)1382 		public override void FlowAnalysis (FlowAnalysisContext fc)
1383 		{
1384 			expr.FlowAnalysis (fc);
1385 		}
1386 
1387 		//
1388 		// Converts operator to System.Linq.Expressions.ExpressionType enum name
1389 		//
GetOperatorExpressionTypeName()1390 		string GetOperatorExpressionTypeName ()
1391 		{
1392 			return IsDecrement ? "Decrement" : "Increment";
1393 		}
1394 
1395 		bool IsDecrement {
1396 			get { return (mode & Mode.IsDecrement) != 0; }
1397 		}
1398 
1399 
MakeExpression(BuilderContext ctx)1400 		public override SLE.Expression MakeExpression (BuilderContext ctx)
1401 		{
1402 			var target = ((RuntimeValueExpression) expr).MetaObject.Expression;
1403 			var source = SLE.Expression.Convert (operation.MakeExpression (ctx), target.Type);
1404 			return SLE.Expression.Assign (target, source);
1405 		}
1406 
OperName(Mode oper)1407 		public static string OperName (Mode oper)
1408 		{
1409 			return (oper & Mode.IsDecrement) != 0 ? "--" : "++";
1410 		}
1411 
CloneTo(CloneContext clonectx, Expression t)1412 		protected override void CloneTo (CloneContext clonectx, Expression t)
1413 		{
1414 			UnaryMutator target = (UnaryMutator) t;
1415 
1416 			target.expr = expr.Clone (clonectx);
1417 		}
1418 
Accept(StructuralVisitor visitor)1419 		public override object Accept (StructuralVisitor visitor)
1420 		{
1421 			return visitor.Visit (this);
1422 		}
1423 
1424 	}
1425 
1426 	//
1427 	// Base class for the `is' and `as' operators
1428 	//
1429 	public abstract class Probe : Expression
1430 	{
1431 		public Expression ProbeType;
1432 		protected Expression expr;
1433 		protected TypeSpec probe_type_expr;
1434 
Probe(Expression expr, Expression probe_type, Location l)1435 		protected Probe (Expression expr, Expression probe_type, Location l)
1436 		{
1437 			ProbeType = probe_type;
1438 			loc = l;
1439 			this.expr = expr;
1440 		}
1441 
1442 		public Expression Expr {
1443 			get {
1444 				return expr;
1445 			}
1446 		}
1447 
ContainsEmitWithAwait()1448 		public override bool ContainsEmitWithAwait ()
1449 		{
1450 			return expr.ContainsEmitWithAwait ();
1451 		}
1452 
ResolveCommon(ResolveContext rc)1453 		protected Expression ResolveCommon (ResolveContext rc)
1454 		{
1455 			expr = expr.Resolve (rc);
1456 			if (expr == null)
1457 				return null;
1458 
1459 			ResolveProbeType (rc);
1460 			if (probe_type_expr == null)
1461 				return this;
1462 
1463 			if (probe_type_expr.IsStatic) {
1464 				rc.Report.Error (7023, loc, "The second operand of `is' or `as' operator cannot be static type `{0}'",
1465 					probe_type_expr.GetSignatureForError ());
1466 				return null;
1467 			}
1468 
1469 			if (expr.Type.IsPointer || probe_type_expr.IsPointer) {
1470 				rc.Report.Error (244, loc, "The `{0}' operator cannot be applied to an operand of pointer type",
1471 					OperatorName);
1472 				return null;
1473 			}
1474 
1475 			if (expr.Type == InternalType.AnonymousMethod || expr.Type == InternalType.MethodGroup) {
1476 				rc.Report.Error (837, loc, "The `{0}' operator cannot be applied to a lambda expression, anonymous method, or method group",
1477 					OperatorName);
1478 				return null;
1479 			}
1480 
1481 			if (expr.Type == InternalType.DefaultType) {
1482 				Error_OperatorCannotBeApplied (rc, loc, OperatorName, expr.Type);
1483 				return null;
1484 			}
1485 
1486 			return this;
1487 		}
1488 
ResolveProbeType(ResolveContext rc)1489 		protected virtual void ResolveProbeType (ResolveContext rc)
1490 		{
1491 			probe_type_expr = ProbeType.ResolveAsType (rc);
1492 		}
1493 
EmitSideEffect(EmitContext ec)1494 		public override void EmitSideEffect (EmitContext ec)
1495 		{
1496 			expr.EmitSideEffect (ec);
1497 		}
1498 
EmitPrepare(EmitContext ec)1499 		public override void EmitPrepare (EmitContext ec)
1500 		{
1501 			expr.EmitPrepare (ec);
1502 		}
1503 
FlowAnalysis(FlowAnalysisContext fc)1504 		public override void FlowAnalysis (FlowAnalysisContext fc)
1505 		{
1506 			expr.FlowAnalysis (fc);
1507 		}
1508 
HasConditionalAccess()1509 		public override bool HasConditionalAccess ()
1510 		{
1511 			return expr.HasConditionalAccess ();
1512 		}
1513 
1514 		protected abstract string OperatorName { get; }
1515 
CloneTo(CloneContext clonectx, Expression t)1516 		protected override void CloneTo (CloneContext clonectx, Expression t)
1517 		{
1518 			Probe target = (Probe) t;
1519 
1520 			target.expr = expr.Clone (clonectx);
1521 			target.ProbeType = ProbeType.Clone (clonectx);
1522 		}
1523 
1524 	}
1525 
1526 	/// <summary>
1527 	///   Implementation of the `is' operator.
1528 	/// </summary>
1529 	public class Is : Probe
1530 	{
1531 		Nullable.Unwrap expr_unwrap;
1532 		MethodSpec number_mg;
1533 		Arguments number_args;
1534 
Is(Expression expr, Expression probe_type, Location l)1535 		public Is (Expression expr, Expression probe_type, Location l)
1536 			: base (expr, probe_type, l)
1537 		{
1538 		}
1539 
1540 		protected override string OperatorName {
1541 			get { return "is"; }
1542 		}
1543 
1544 		public LocalVariable Variable { get; set; }
1545 
CreateExpressionTree(ResolveContext ec)1546 		public override Expression CreateExpressionTree (ResolveContext ec)
1547 		{
1548 			if (Variable != null)
1549 				ec.Report.Error (8122, loc, "An expression tree cannot contain a pattern matching operator");
1550 
1551 			Arguments args = Arguments.CreateForExpressionTree (ec, null,
1552 				expr.CreateExpressionTree (ec),
1553 				new TypeOf (probe_type_expr, loc));
1554 
1555 			return CreateExpressionFactoryCall (ec, "TypeIs", args);
1556 		}
1557 
CreateConstantResult(ResolveContext rc, bool result)1558 		Expression CreateConstantResult (ResolveContext rc, bool result)
1559 		{
1560 			if (result)
1561 				rc.Report.Warning (183, 1, loc, "The given expression is always of the provided (`{0}') type",
1562 					probe_type_expr.GetSignatureForError ());
1563 			else
1564 				rc.Report.Warning (184, 1, loc, "The given expression is never of the provided (`{0}') type",
1565 					probe_type_expr.GetSignatureForError ());
1566 
1567 			var c = new BoolConstant (rc.BuiltinTypes, result, loc);
1568 			return expr.IsSideEffectFree ?
1569 				ReducedExpression.Create (c, this) :
1570 				new SideEffectConstant (c, this, loc);
1571 		}
1572 
Emit(EmitContext ec)1573 		public override void Emit (EmitContext ec)
1574 		{
1575 			if (probe_type_expr == null) {
1576 				if (ProbeType is WildcardPattern) {
1577 					expr.EmitSideEffect (ec);
1578 					ProbeType.Emit (ec);
1579 				} else {
1580 					EmitPatternMatch (ec);
1581 				}
1582 				return;
1583 			}
1584 
1585 			EmitLoad (ec);
1586 
1587 			if (expr_unwrap == null) {
1588 				ec.EmitNull ();
1589 				ec.Emit (OpCodes.Cgt_Un);
1590 			}
1591 		}
1592 
EmitBranchable(EmitContext ec, Label target, bool on_true)1593 		public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
1594 		{
1595 			if (probe_type_expr == null) {
1596 				EmitPatternMatch (ec);
1597 			} else {
1598 				EmitLoad (ec);
1599 			}
1600 
1601 			ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
1602 		}
1603 
EmitPrepare(EmitContext ec)1604 		public override void EmitPrepare (EmitContext ec)
1605 		{
1606 			base.EmitPrepare (ec);
1607 
1608 			if (Variable != null)
1609 				Variable.CreateBuilder (ec);
1610 		}
1611 
EmitPatternMatch(EmitContext ec)1612 		void EmitPatternMatch (EmitContext ec)
1613 		{
1614 			var no_match = ec.DefineLabel ();
1615 			var end = ec.DefineLabel ();
1616 
1617 			if (expr_unwrap != null) {
1618 				expr_unwrap.EmitCheck (ec);
1619 
1620 				if (ProbeType.IsNull) {
1621 					ec.EmitInt (0);
1622 					ec.Emit (OpCodes.Ceq);
1623 					return;
1624 				}
1625 
1626 				ec.Emit (OpCodes.Brfalse_S, no_match);
1627 				expr_unwrap.Emit (ec);
1628 				ProbeType.Emit (ec);
1629 				ec.Emit (OpCodes.Ceq);
1630 				ec.Emit (OpCodes.Br_S, end);
1631 				ec.MarkLabel (no_match);
1632 				ec.EmitInt (0);
1633 				ec.MarkLabel (end);
1634 				return;
1635 			}
1636 
1637 			if (number_args != null && number_args.Count == 3) {
1638 				var ce = new CallEmitter ();
1639 				ce.Emit (ec, number_mg, number_args, loc);
1640 				return;
1641 			}
1642 
1643 			var probe_type = ProbeType.Type;
1644 
1645 			Expr.Emit (ec);
1646 			ec.Emit (OpCodes.Isinst, probe_type);
1647 			ec.Emit (OpCodes.Dup);
1648 			ec.Emit (OpCodes.Brfalse, no_match);
1649 
1650 			bool complex_pattern = ProbeType is ComplexPatternExpression;
1651 			Label prev = ec.RecursivePatternLabel;
1652 			if (complex_pattern)
1653 				ec.RecursivePatternLabel = ec.DefineLabel ();
1654 
1655 			if (number_mg != null) {
1656 				var ce = new CallEmitter ();
1657 				ce.Emit (ec, number_mg, number_args, loc);
1658 			} else {
1659 				if (TypeSpec.IsValueType (probe_type))
1660 					ec.Emit (OpCodes.Unbox_Any, probe_type);
1661 
1662 				ProbeType.Emit (ec);
1663 				if (complex_pattern) {
1664 					ec.EmitInt (1);
1665 				} else {
1666 					ec.Emit (OpCodes.Ceq);
1667 				}
1668 			}
1669 			ec.Emit (OpCodes.Br_S, end);
1670 			ec.MarkLabel (no_match);
1671 
1672 			ec.Emit (OpCodes.Pop);
1673 
1674 			if (complex_pattern)
1675 				ec.MarkLabel (ec.RecursivePatternLabel);
1676 
1677 			ec.RecursivePatternLabel = prev;
1678 
1679 			ec.EmitInt (0);
1680 			ec.MarkLabel (end);
1681 		}
1682 
EmitLoad(EmitContext ec)1683 		void EmitLoad (EmitContext ec)
1684 		{
1685 			if (expr_unwrap != null) {
1686 				expr_unwrap.EmitCheck (ec);
1687 
1688 				if (Variable == null)
1689 					return;
1690 
1691 				ec.Emit (OpCodes.Dup);
1692 				var no_value_label = ec.DefineLabel ();
1693 				ec.Emit (OpCodes.Brfalse_S, no_value_label);
1694 
1695 				if (Variable.HoistedVariant != null)
1696 					ec.EmitThis ();
1697 
1698 				expr_unwrap.Emit (ec);
1699 
1700 				if (Variable.HoistedVariant != null) {
1701 					Variable.HoistedVariant.EmitAssignFromStack (ec);
1702 				} else {
1703 					//
1704 					// It's ok to have variable builder created out of order. It simplifies emit
1705 					// of statements like while (condition) { }
1706 					//
1707 					if (!Variable.Created)
1708 						Variable.CreateBuilder (ec);
1709 
1710 					Variable.EmitAssign (ec);
1711 				}
1712 
1713 				ec.MarkLabel (no_value_label);
1714 				return;
1715 			}
1716 
1717 			expr.Emit (ec);
1718 
1719 			bool vtype_variable = Variable != null && (probe_type_expr.IsGenericParameter || TypeSpec.IsValueType (ProbeType.Type));
1720 			LocalBuilder expr_copy = null;
1721 
1722 			if (vtype_variable && !ExpressionAnalyzer.IsInexpensiveLoad (expr)) {
1723 				expr_copy = ec.GetTemporaryLocal (expr.Type);
1724 				ec.Emit (OpCodes.Stloc, expr_copy);
1725 				ec.Emit (OpCodes.Ldloc, expr_copy);
1726 			} else if (probe_type_expr.IsGenericParameter && TypeSpec.IsValueType (expr.Type)) {
1727 				//
1728 				// Only to make verifier happy
1729 				//
1730 				ec.Emit (OpCodes.Box, expr.Type);
1731 			}
1732 
1733 			ec.Emit (OpCodes.Isinst, probe_type_expr);
1734 
1735 			if (Variable != null) {
1736 				ec.Emit (OpCodes.Dup);
1737 
1738 				var nonmatching_label = ec.DefineLabel ();
1739 				ec.Emit (OpCodes.Brfalse_S, nonmatching_label);
1740 
1741 				if (vtype_variable) {
1742 					if (expr_copy != null) {
1743 						ec.Emit (OpCodes.Ldloc, expr_copy);
1744 						ec.FreeTemporaryLocal (expr_copy, expr.Type);
1745 					} else {
1746 						expr.Emit (ec);
1747 					}
1748 
1749 					ec.Emit (OpCodes.Unbox_Any, probe_type_expr);
1750 				} else {
1751 					// Already on the stack
1752 				}
1753 
1754 				if (Variable.HoistedVariant != null) {
1755 					var temp = new LocalTemporary (ProbeType.Type);
1756 					temp.Store (ec);
1757 					Variable.HoistedVariant.EmitAssign (ec, temp, false, false);
1758 					temp.Release (ec);
1759 
1760 					if (!vtype_variable)
1761 						Variable.HoistedVariant.Emit (ec);
1762 				} else {
1763 					//
1764 					// It's ok to have variable builder created out of order. It simplifies emit
1765 					// of statements like while (condition) { }
1766 					//
1767 					if (!Variable.Created)
1768 						Variable.CreateBuilder (ec);
1769 
1770 					Variable.EmitAssign (ec);
1771 
1772 					if (!vtype_variable)
1773 						Variable.Emit (ec);
1774 				}
1775 
1776 				ec.MarkLabel (nonmatching_label);
1777 			}
1778 		}
1779 
DoResolve(ResolveContext rc)1780 		protected override Expression DoResolve (ResolveContext rc)
1781 		{
1782 			if (ResolveCommon (rc) == null)
1783 				return null;
1784 
1785 			type = rc.BuiltinTypes.Bool;
1786 			eclass = ExprClass.Value;
1787 
1788 			if (probe_type_expr == null)
1789 				return ResolveMatchingExpression (rc);
1790 
1791 			var res = ResolveResultExpression (rc);
1792 			if (Variable != null) {
1793 				if (res is Constant)
1794 					throw new NotImplementedException ("constant in type pattern matching");
1795 
1796 				Variable.Type = probe_type_expr;
1797 				var bc = rc as BlockContext;
1798 				if (bc != null)
1799 					Variable.PrepareAssignmentAnalysis (bc);
1800 			}
1801 
1802 			return res;
1803 		}
1804 
FlowAnalysis(FlowAnalysisContext fc)1805 		public override void FlowAnalysis (FlowAnalysisContext fc)
1806 		{
1807 			base.FlowAnalysis (fc);
1808 
1809 			if (Variable != null)
1810 				fc.SetVariableAssigned (Variable.VariableInfo, true);
1811 		}
1812 
FlowAnalysisConditional(FlowAnalysisContext fc)1813 		public override void FlowAnalysisConditional (FlowAnalysisContext fc)
1814 		{
1815 			if (Variable == null) {
1816 				base.FlowAnalysisConditional (fc);
1817 				return;
1818 			}
1819 
1820 			expr.FlowAnalysis (fc);
1821 
1822 			fc.DefiniteAssignmentOnTrue = fc.BranchDefiniteAssignment ();
1823 			fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment;
1824 
1825 			fc.SetVariableAssigned (Variable.VariableInfo, fc.DefiniteAssignmentOnTrue);
1826 		}
1827 
ResolveProbeType(ResolveContext rc)1828 		protected override void ResolveProbeType (ResolveContext rc)
1829 		{
1830 			if (!(ProbeType is TypeExpr) && rc.Module.Compiler.Settings.Version == LanguageVersion.Experimental) {
1831 				if (ProbeType is PatternExpression) {
1832 					ProbeType.Resolve (rc);
1833 					return;
1834 				}
1835 
1836 				//
1837 				// Have to use session recording because we don't have reliable type probing
1838 				// mechanism (similar issue as in attributes resolving)
1839 				//
1840 				// TODO: This is still wrong because ResolveAsType can be destructive
1841 				//
1842 				var type_printer = new SessionReportPrinter ();
1843 				var prev_recorder = rc.Report.SetPrinter (type_printer);
1844 
1845 				probe_type_expr = ProbeType.ResolveAsType (rc);
1846 				type_printer.EndSession ();
1847 
1848 				if (probe_type_expr != null) {
1849 					type_printer.Merge (rc.Report.Printer);
1850 					rc.Report.SetPrinter (prev_recorder);
1851 					return;
1852 				}
1853 
1854 				var vexpr = ProbeType as VarExpr;
1855 				if (vexpr != null && vexpr.InferType (rc, expr)) {
1856 					probe_type_expr = vexpr.Type;
1857 					rc.Report.SetPrinter (prev_recorder);
1858 					return;
1859 				}
1860 
1861 				var expr_printer = new SessionReportPrinter ();
1862 				rc.Report.SetPrinter (expr_printer);
1863 				ProbeType = ProbeType.Resolve (rc);
1864 				expr_printer.EndSession ();
1865 
1866 				if (ProbeType != null) {
1867 					expr_printer.Merge (rc.Report.Printer);
1868 				} else {
1869 					type_printer.Merge (rc.Report.Printer);
1870 				}
1871 
1872 				rc.Report.SetPrinter (prev_recorder);
1873 				return;
1874 			}
1875 
1876 			base.ResolveProbeType (rc);
1877 		}
1878 
ResolveMatchingExpression(ResolveContext rc)1879 		Expression ResolveMatchingExpression (ResolveContext rc)
1880 		{
1881 			var mc = ProbeType as Constant;
1882 			if (mc != null) {
1883 				if (!Convert.ImplicitConversionExists (rc, ProbeType, Expr.Type)) {
1884 					ProbeType.Error_ValueCannotBeConverted (rc, Expr.Type, false);
1885 					return null;
1886 				}
1887 
1888 				if (mc.IsNull)
1889 					return new Binary (Binary.Operator.Equality, Expr, mc).Resolve (rc);
1890 
1891 				var c = Expr as Constant;
1892 				if (c != null) {
1893 					c = ConstantFold.BinaryFold (rc, Binary.Operator.Equality, c, mc, loc);
1894 					if (c != null)
1895 						return c;
1896 				}
1897 
1898 				if (Expr.Type.IsNullableType) {
1899 					expr_unwrap = new Nullable.Unwrap (Expr);
1900 					expr_unwrap.Resolve (rc);
1901 					ProbeType = Convert.ImplicitConversion (rc, ProbeType, expr_unwrap.Type, loc);
1902 				} else if (ProbeType.Type == Expr.Type) {
1903 					// TODO: Better error handling
1904 					return new Binary (Binary.Operator.Equality, Expr, mc, loc).Resolve (rc);
1905 				} else if (ProbeType.Type.IsEnum || (ProbeType.Type.BuiltinType >= BuiltinTypeSpec.Type.Byte && ProbeType.Type.BuiltinType <= BuiltinTypeSpec.Type.Decimal)) {
1906 					var helper = rc.Module.CreatePatterMatchingHelper ();
1907 					number_mg = helper.NumberMatcher.Spec;
1908 
1909 					//
1910 					// There are actually 3 arguments but the first one is already on the stack
1911 					//
1912 					number_args = new Arguments (3);
1913 					if (!ProbeType.Type.IsEnum)
1914 						number_args.Add (new Argument (Expr));
1915 
1916 					number_args.Add (new Argument (Convert.ImplicitConversion (rc, ProbeType, rc.BuiltinTypes.Object, loc)));
1917 					number_args.Add (new Argument (new BoolLiteral (rc.BuiltinTypes, ProbeType.Type.IsEnum, loc)));
1918 				}
1919 
1920 				return this;
1921 			}
1922 
1923 			if (ProbeType is PatternExpression) {
1924 				if (!(ProbeType is WildcardPattern) && !Convert.ImplicitConversionExists (rc, ProbeType, Expr.Type)) {
1925 					ProbeType.Error_ValueCannotBeConverted (rc, Expr.Type, false);
1926 				}
1927 
1928 				return this;
1929 			}
1930 
1931 			// TODO: Better error message
1932 			rc.Report.Error (150, ProbeType.Location, "A constant value is expected");
1933 			return this;
1934 		}
1935 
ResolveResultExpression(ResolveContext ec)1936 		Expression ResolveResultExpression (ResolveContext ec)
1937 		{
1938 			if (Variable != null) {
1939 				if (expr is NullLiteral) {
1940 					ec.Report.Error (8117, loc, "Cannot use null as pattern matching operand");
1941 					return this;
1942 				}
1943 
1944 				CheckExpressionVariable (ec);
1945 			}
1946 
1947 			TypeSpec d = expr.Type;
1948 			bool d_is_nullable = false;
1949 
1950 			//
1951 			// If E is a method group or the null literal, or if the type of E is a reference
1952 			// type or a nullable type and the value of E is null, the result is false
1953 			//
1954 			if (expr.IsNull)
1955 				return CreateConstantResult (ec, false);
1956 
1957 			if (d.IsNullableType) {
1958 				var ut = Nullable.NullableInfo.GetUnderlyingType (d);
1959 				if (!ut.IsGenericParameter) {
1960 					d = ut;
1961 					d_is_nullable = true;
1962 				}
1963 			}
1964 
1965 			TypeSpec t = probe_type_expr;
1966 			bool t_is_nullable = false;
1967 			if (t.IsNullableType) {
1968 				if (Variable != null) {
1969 					ec.Report.Error (8116, loc, "The nullable type `{0}' pattern matching is not allowed. Consider using underlying type `{1}'",
1970 									 t.GetSignatureForError (), Nullable.NullableInfo.GetUnderlyingType (t).GetSignatureForError ());
1971 				}
1972 
1973 				var ut = Nullable.NullableInfo.GetUnderlyingType (t);
1974 				if (!ut.IsGenericParameter) {
1975 					t = ut;
1976 					t_is_nullable = true;
1977 				}
1978 			}
1979 
1980 			if (t.IsStruct) {
1981 				if (d == t) {
1982 					//
1983 					// D and T are the same value types but D can be null
1984 					//
1985 					if (d_is_nullable && !t_is_nullable) {
1986 						expr_unwrap = Nullable.Unwrap.Create (expr, true);
1987 						return this;
1988 					}
1989 
1990 					//
1991 					// The result is true if D and T are the same value types
1992 					//
1993 					return CreateConstantResult (ec, true);
1994 				}
1995 
1996 				var tp = d as TypeParameterSpec;
1997 				if (tp != null)
1998 					return ResolveGenericParameter (ec, t, tp);
1999 
2000 				//
2001 				// An unboxing conversion exists
2002 				//
2003 				if (Convert.ExplicitReferenceConversionExists (d, t))
2004 					return this;
2005 
2006 				//
2007 				// open generic type
2008 				//
2009 				if (d is InflatedTypeSpec && InflatedTypeSpec.ContainsTypeParameter (d))
2010 					return this;
2011 			} else {
2012 				var tps = t as TypeParameterSpec;
2013 				if (tps != null)
2014 					return ResolveGenericParameter (ec, d, tps);
2015 
2016 				if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
2017 					if (Variable != null) {
2018 						ec.Report.Error (8208, loc, "The type `{0}' pattern matching is not allowed", t.GetSignatureForError ());
2019 					} else {
2020 						ec.Report.Warning (1981, 3, loc,
2021 							"Using `{0}' to test compatibility with `{1}' is identical to testing compatibility with `object'",
2022 							OperatorName, t.GetSignatureForError ());
2023 					}
2024 				}
2025 
2026 				if (TypeManager.IsGenericParameter (d))
2027 					return ResolveGenericParameter (ec, t, (TypeParameterSpec) d);
2028 
2029 				if (TypeSpec.IsValueType (d)) {
2030 					if (Convert.ImplicitBoxingConversion (null, d, t) != null) {
2031 						if (d_is_nullable && !t_is_nullable) {
2032 							expr_unwrap = Nullable.Unwrap.Create (expr, false);
2033 							return this;
2034 						}
2035 
2036 						return CreateConstantResult (ec, true);
2037 					}
2038 				} else {
2039 					if (Convert.ImplicitReferenceConversionExists (d, t)) {
2040 						var c = expr as Constant;
2041 						if (c != null)
2042 							return CreateConstantResult (ec, !c.IsNull);
2043 
2044 						//
2045 						// Do not optimize for imported type or dynamic type
2046 						//
2047 						if (d.MemberDefinition.IsImported && d.BuiltinType != BuiltinTypeSpec.Type.None &&
2048 							d.MemberDefinition.DeclaringAssembly != t.MemberDefinition.DeclaringAssembly) {
2049 							return this;
2050 						}
2051 
2052 						if (d.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
2053 							return this;
2054 
2055 						//
2056 						// Turn is check into simple null check for implicitly convertible reference types
2057 						//
2058 						return ReducedExpression.Create (
2059 							new Binary (Binary.Operator.Inequality, expr, new NullLiteral (loc), Binary.State.UserOperatorsExcluded).Resolve (ec),
2060 							this).Resolve (ec);
2061 					}
2062 
2063 					if (Convert.ExplicitReferenceConversionExists (d, t))
2064 						return this;
2065 
2066 					//
2067 					// open generic type
2068 					//
2069 					if ((d is InflatedTypeSpec || d.IsArray) && InflatedTypeSpec.ContainsTypeParameter (d))
2070 						return this;
2071 				}
2072 			}
2073 
2074 			return CreateConstantResult (ec, false);
2075 		}
2076 
ResolveGenericParameter(ResolveContext ec, TypeSpec d, TypeParameterSpec t)2077 		Expression ResolveGenericParameter (ResolveContext ec, TypeSpec d, TypeParameterSpec t)
2078 		{
2079 			if (t.IsReferenceType) {
2080 				if (d.IsStruct)
2081 					return CreateConstantResult (ec, false);
2082 			}
2083 
2084 			if (expr.Type.IsGenericParameter) {
2085 				if (expr.Type == d && TypeSpec.IsValueType (t) && TypeSpec.IsValueType (d))
2086 					return CreateConstantResult (ec, true);
2087 
2088 				expr = new BoxedCast (expr, d);
2089 			}
2090 
2091 			return this;
2092 		}
2093 
Accept(StructuralVisitor visitor)2094 		public override object Accept (StructuralVisitor visitor)
2095 		{
2096 			return visitor.Visit (this);
2097 		}
2098 	}
2099 
2100 	class WildcardPattern : PatternExpression
2101 	{
WildcardPattern(Location loc)2102 		public WildcardPattern (Location loc)
2103 			: base (loc)
2104 		{
2105 		}
2106 
DoResolve(ResolveContext rc)2107 		protected override Expression DoResolve (ResolveContext rc)
2108 		{
2109 			eclass = ExprClass.Value;
2110 			type = rc.BuiltinTypes.Object;
2111 			return this;
2112 		}
2113 
Emit(EmitContext ec)2114 		public override void Emit (EmitContext ec)
2115 		{
2116 			ec.EmitInt (1);
2117 		}
2118 	}
2119 
2120 	class RecursivePattern : ComplexPatternExpression
2121 	{
2122 		MethodGroupExpr operator_mg;
2123 		Arguments operator_args;
2124 
RecursivePattern(ATypeNameExpression typeExpresion, Arguments arguments, Location loc)2125 		public RecursivePattern (ATypeNameExpression typeExpresion, Arguments arguments, Location loc)
2126 			: base (typeExpresion, loc)
2127 		{
2128 			Arguments = arguments;
2129 		}
2130 
2131 		public Arguments Arguments { get; private set; }
2132 
DoResolve(ResolveContext rc)2133 		protected override Expression DoResolve (ResolveContext rc)
2134 		{
2135 			type = TypeExpression.ResolveAsType (rc);
2136 			if (type == null)
2137 				return null;
2138 
2139 			var operators = MemberCache.GetUserOperator (type, Operator.OpType.Is, true);
2140 			if (operators == null) {
2141 				Error_TypeDoesNotContainDefinition (rc, type, Operator.GetName (Operator.OpType.Is) + " operator");
2142 				return null;
2143 			}
2144 
2145 			var ops = FindMatchingOverloads (operators);
2146 			if (ops == null) {
2147 				// TODO: better error message
2148 				Error_TypeDoesNotContainDefinition (rc, type, Operator.GetName (Operator.OpType.Is) + " operator");
2149 				return null;
2150 			}
2151 
2152 			bool dynamic_args;
2153 			Arguments.Resolve (rc, out dynamic_args);
2154 			if (dynamic_args)
2155 				throw new NotImplementedException ("dynamic argument");
2156 
2157 			var op = FindBestOverload (rc, ops);
2158 			if (op == null) {
2159 				// TODO: better error message
2160 				Error_TypeDoesNotContainDefinition (rc, type, Operator.GetName (Operator.OpType.Is) + " operator");
2161 				return null;
2162 			}
2163 
2164 			var op_types = op.Parameters.Types;
2165 			operator_args = new Arguments (op_types.Length);
2166 			operator_args.Add (new Argument (new EmptyExpression (type)));
2167 
2168 			for (int i = 0; i < Arguments.Count; ++i) {
2169 				// TODO: Needs releasing optimization
2170 				var lt = new LocalTemporary (op_types [i + 1]);
2171 				operator_args.Add (new Argument (lt, Argument.AType.Out));
2172 
2173 				if (comparisons == null)
2174 					comparisons = new Expression[Arguments.Count];
2175 
2176 				int arg_comp_index;
2177 				Expression expr;
2178 
2179 				var arg = Arguments [i];
2180 				var named = arg as NamedArgument;
2181 				if (named != null) {
2182 					arg_comp_index = op.Parameters.GetParameterIndexByName (named.Name) - 1;
2183 					expr = Arguments [arg_comp_index].Expr;
2184 				} else {
2185 					arg_comp_index = i;
2186 					expr = arg.Expr;
2187 				}
2188 
2189 				comparisons [arg_comp_index] = ResolveComparison (rc, expr, lt);
2190 			}
2191 
2192 			operator_mg = MethodGroupExpr.CreatePredefined (op, type, loc);
2193 
2194 			eclass = ExprClass.Value;
2195 			return this;
2196 		}
2197 
FindMatchingOverloads(IList<MemberSpec> members)2198 		List<MethodSpec> FindMatchingOverloads (IList<MemberSpec> members)
2199 		{
2200 			int arg_count = Arguments.Count + 1;
2201 			List<MethodSpec> best = null;
2202 			foreach (MethodSpec method in members) {
2203 				var pm = method.Parameters;
2204 				if (pm.Count != arg_count)
2205 					continue;
2206 
2207 				// TODO: Needs more thorough operator checks elsewhere to avoid doing this every time
2208 				bool ok = true;
2209 				for (int ii = 1; ii < pm.Count; ++ii) {
2210 					if ((pm.FixedParameters [ii].ModFlags & Parameter.Modifier.OUT) == 0) {
2211 						ok = false;
2212 						break;
2213 					}
2214 				}
2215 
2216 				if (!ok)
2217 					continue;
2218 
2219 				if (best == null)
2220 					best = new List<MethodSpec> ();
2221 
2222 				best.Add (method);
2223 			}
2224 
2225 			return best;
2226 		}
2227 
FindBestOverload(ResolveContext rc, List<MethodSpec> methods)2228 		MethodSpec FindBestOverload (ResolveContext rc, List<MethodSpec> methods)
2229 		{
2230 			for (int ii = 0; ii < Arguments.Count; ++ii) {
2231 				var arg = Arguments [ii];
2232 				var expr = arg.Expr;
2233 				if (expr is WildcardPattern)
2234 					continue;
2235 
2236 				var na = arg as NamedArgument;
2237 				for (int i = 0; i < methods.Count; ++i) {
2238 					var pd = methods [i].Parameters;
2239 
2240 					int index;
2241 					if (na != null) {
2242 						index = pd.GetParameterIndexByName (na.Name);
2243 						if (index < 1) {
2244 							methods.RemoveAt (i--);
2245 							continue;
2246 						}
2247 					} else {
2248 						index = ii + 1;
2249 					}
2250 
2251 					var m = pd.Types [index];
2252 					if (!Convert.ImplicitConversionExists (rc, expr, m))
2253 						methods.RemoveAt (i--);
2254 				}
2255 			}
2256 
2257 			if (methods.Count != 1)
2258 				return null;
2259 
2260 			return methods [0];
2261 		}
2262 
EmitBranchable(EmitContext ec, Label target, bool on_true)2263 		public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
2264 		{
2265 			operator_mg.EmitCall (ec, operator_args, false);
2266 			ec.Emit (OpCodes.Brfalse, target);
2267 
2268 			base.EmitBranchable (ec, target, on_true);
2269 		}
2270 
ResolveComparison(ResolveContext rc, Expression expr, LocalTemporary lt)2271 		static Expression ResolveComparison (ResolveContext rc, Expression expr, LocalTemporary lt)
2272 		{
2273 			if (expr is WildcardPattern)
2274 				return new EmptyExpression (expr.Type);
2275 
2276 			var recursive = expr as RecursivePattern;
2277 			expr = Convert.ImplicitConversionRequired (rc, expr, lt.Type, expr.Location);
2278 			if (expr == null)
2279 				return null;
2280 
2281 			if (recursive != null) {
2282 				recursive.SetParentInstance (lt);
2283 				return expr;
2284 			}
2285 
2286 			// TODO: Better error handling
2287 			return new Binary (Binary.Operator.Equality, lt, expr, expr.Location).Resolve (rc);
2288 		}
2289 
SetParentInstance(Expression instance)2290 		public void SetParentInstance (Expression instance)
2291 		{
2292 			operator_args [0] = new Argument (instance);
2293 		}
2294 	}
2295 
2296 	class PropertyPattern : ComplexPatternExpression
2297 	{
2298 		LocalTemporary instance;
2299 
PropertyPattern(ATypeNameExpression typeExpresion, List<PropertyPatternMember> members, Location loc)2300 		public PropertyPattern (ATypeNameExpression typeExpresion, List<PropertyPatternMember> members, Location loc)
2301 			: base (typeExpresion, loc)
2302 		{
2303 			Members = members;
2304 		}
2305 
2306 		public List<PropertyPatternMember> Members { get; private set; }
2307 
DoResolve(ResolveContext rc)2308 		protected override Expression DoResolve (ResolveContext rc)
2309 		{
2310 			type = TypeExpression.ResolveAsType (rc);
2311 			if (type == null)
2312 				return null;
2313 
2314 			comparisons = new Expression[Members.Count];
2315 
2316 			// TODO: optimize when source is VariableReference, it'd save dup+pop
2317 			instance = new LocalTemporary (type);
2318 
2319 			for (int i = 0; i < Members.Count; i++) {
2320 				var lookup = Members [i];
2321 
2322 				var member = MemberLookup (rc, false, type, lookup.Name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
2323 				if (member == null) {
2324 					member = MemberLookup (rc, true, type, lookup.Name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
2325 					if (member != null) {
2326 						Expression.ErrorIsInaccesible (rc, member.GetSignatureForError (), loc);
2327 						continue;
2328 					}
2329 				}
2330 
2331 				if (member == null) {
2332 					Expression.Error_TypeDoesNotContainDefinition (rc, Location, Type, lookup.Name);
2333 					continue;
2334 				}
2335 
2336 				var pe = member as PropertyExpr;
2337 				if (pe == null || member is FieldExpr) {
2338 					rc.Report.Error (-2001, lookup.Location, "`{0}' is not a valid pattern member", lookup.Name);
2339 					continue;
2340 				}
2341 
2342 				// TODO: Obsolete checks
2343 				// TODO: check accessibility
2344 				if (pe != null && !pe.PropertyInfo.HasGet) {
2345 					rc.Report.Error (-2002, lookup.Location, "Property `{0}.get' accessor is required", pe.GetSignatureForError ());
2346 					continue;
2347 				}
2348 
2349 				var expr = lookup.Expr.Resolve (rc);
2350 				if (expr == null)
2351 					continue;
2352 
2353 				var me = (MemberExpr)member;
2354 				me.InstanceExpression = instance;
2355 
2356 				comparisons [i] = ResolveComparison (rc, expr, me);
2357 			}
2358 
2359 			eclass = ExprClass.Value;
2360 			return this;
2361 		}
2362 
ResolveComparison(ResolveContext rc, Expression expr, Expression instance)2363 		static Expression ResolveComparison (ResolveContext rc, Expression expr, Expression instance)
2364 		{
2365 			if (expr is WildcardPattern)
2366 				return new EmptyExpression (expr.Type);
2367 
2368 			return new Is (instance, expr, expr.Location).Resolve (rc);
2369 		}
2370 
EmitBranchable(EmitContext ec, Label target, bool on_true)2371 		public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
2372 		{
2373 			instance.Store (ec);
2374 
2375 			base.EmitBranchable (ec, target, on_true);
2376 		}
2377 	}
2378 
2379 	class PropertyPatternMember
2380 	{
PropertyPatternMember(string name, Expression expr, Location loc)2381 		public PropertyPatternMember (string name, Expression expr, Location loc)
2382 		{
2383 			Name = name;
2384 			Expr = expr;
2385 			Location = loc;
2386 		}
2387 
2388 		public string Name { get; private set; }
2389 		public Expression Expr { get; private set; }
2390 		public Location Location { get; private set; }
2391 	}
2392 
2393 	abstract class PatternExpression : Expression
2394 	{
PatternExpression(Location loc)2395 		protected PatternExpression (Location loc)
2396 		{
2397 			this.loc = loc;
2398 		}
2399 
CreateExpressionTree(ResolveContext ec)2400 		public override Expression CreateExpressionTree (ResolveContext ec)
2401 		{
2402 			throw new NotImplementedException ();
2403 		}
2404 	}
2405 
2406 	abstract class ComplexPatternExpression : PatternExpression
2407 	{
2408 		protected Expression[] comparisons;
2409 
ComplexPatternExpression(ATypeNameExpression typeExpresion, Location loc)2410 		protected ComplexPatternExpression (ATypeNameExpression typeExpresion, Location loc)
2411 			: base (loc)
2412 		{
2413 			TypeExpression = typeExpresion;
2414 		}
2415 
2416 		public ATypeNameExpression TypeExpression { get; private set; }
2417 
Emit(EmitContext ec)2418 		public override void Emit (EmitContext ec)
2419 		{
2420 			EmitBranchable (ec, ec.RecursivePatternLabel, false);
2421 		}
2422 
EmitBranchable(EmitContext ec, Label target, bool on_true)2423 		public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
2424 		{
2425 			if (comparisons != null) {
2426 				foreach (var comp in comparisons) {
2427 					comp.EmitBranchable (ec, target, false);
2428 				}
2429 			}
2430 		}
2431 	}
2432 
2433 	/// <summary>
2434 	///   Implementation of the `as' operator.
2435 	/// </summary>
2436 	public class As : Probe {
2437 
As(Expression expr, Expression probe_type, Location l)2438 		public As (Expression expr, Expression probe_type, Location l)
2439 			: base (expr, probe_type, l)
2440 		{
2441 		}
2442 
2443 		protected override string OperatorName {
2444 			get { return "as"; }
2445 		}
2446 
CreateExpressionTree(ResolveContext ec)2447 		public override Expression CreateExpressionTree (ResolveContext ec)
2448 		{
2449 			Arguments args = Arguments.CreateForExpressionTree (ec, null,
2450 				expr.CreateExpressionTree (ec),
2451 				new TypeOf (probe_type_expr, loc));
2452 
2453 			return CreateExpressionFactoryCall (ec, "TypeAs", args);
2454 		}
2455 
Emit(EmitContext ec)2456 		public override void Emit (EmitContext ec)
2457 		{
2458 			expr.Emit (ec);
2459 
2460 			ec.Emit (OpCodes.Isinst, type);
2461 
2462 			if (TypeManager.IsGenericParameter (type) || type.IsNullableType)
2463 				ec.Emit (OpCodes.Unbox_Any, type);
2464 		}
2465 
DoResolve(ResolveContext ec)2466 		protected override Expression DoResolve (ResolveContext ec)
2467 		{
2468 			if (ResolveCommon (ec) == null)
2469 				return null;
2470 
2471 			type = probe_type_expr;
2472 			eclass = ExprClass.Value;
2473 			TypeSpec etype = expr.Type;
2474 
2475 			if (expr is TupleLiteral && TupleLiteral.ContainsNoTypeElement (etype)) {
2476 				ec.Report.Error (8307, expr.Location, "The first operand of an `as' operator may not be a tuple literal without a natural type");
2477 				type = InternalType.ErrorType;
2478 				return this;
2479 			}
2480 
2481 			if (type == null) {
2482 				type = InternalType.ErrorType;
2483 				return this;
2484 			}
2485 
2486 			if (!TypeSpec.IsReferenceType (type) && !type.IsNullableType) {
2487 				if (TypeManager.IsGenericParameter (type)) {
2488 					ec.Report.Error (413, loc,
2489 						"The `as' operator cannot be used with a non-reference type parameter `{0}'. Consider adding `class' or a reference type constraint",
2490 						probe_type_expr.GetSignatureForError ());
2491 				} else {
2492 					ec.Report.Error (77, loc,
2493 						"The `as' operator cannot be used with a non-nullable value type `{0}'",
2494 						type.GetSignatureForError ());
2495 				}
2496 				return null;
2497 			}
2498 
2499 			if (expr.IsNull && type.IsNullableType) {
2500 				return Nullable.LiftedNull.CreateFromExpression (ec, this);
2501 			}
2502 
2503 			// If the compile-time type of E is dynamic, unlike the cast operator the as operator is not dynamically bound
2504 			if (etype.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
2505 				return this;
2506 			}
2507 
2508 			Expression e = Convert.ImplicitConversionStandard (ec, expr, type, loc);
2509 			if (e != null) {
2510 				e = EmptyCast.Create (e, type);
2511 				return ReducedExpression.Create (e, this).Resolve (ec);
2512 			}
2513 
2514 			if (Convert.ExplicitReferenceConversionExists (etype, type)){
2515 				if (TypeManager.IsGenericParameter (etype))
2516 					expr = new BoxedCast (expr, etype);
2517 
2518 				return this;
2519 			}
2520 
2521 			if (InflatedTypeSpec.ContainsTypeParameter (etype) || InflatedTypeSpec.ContainsTypeParameter (type)) {
2522 				expr = new BoxedCast (expr, etype);
2523 				return this;
2524 			}
2525 
2526 			if (etype != InternalType.ErrorType) {
2527 				ec.Report.Error (39, loc, "Cannot convert type `{0}' to `{1}' via a built-in conversion",
2528 					etype.GetSignatureForError (), type.GetSignatureForError ());
2529 			}
2530 
2531 			return null;
2532 		}
2533 
Accept(StructuralVisitor visitor)2534 		public override object Accept (StructuralVisitor visitor)
2535 		{
2536 			return visitor.Visit (this);
2537 		}
2538 	}
2539 
2540 	//
2541 	// This represents a typecast in the source language.
2542 	//
2543 	public class Cast : ShimExpression {
2544 		Expression target_type;
2545 
Cast(Expression cast_type, Expression expr, Location loc)2546 		public Cast (Expression cast_type, Expression expr, Location loc)
2547 			: base (expr)
2548 		{
2549 			this.target_type = cast_type;
2550 			this.loc = loc;
2551 		}
2552 
2553 		public Expression TargetType {
2554 			get { return target_type; }
2555 		}
2556 
DoResolve(ResolveContext ec)2557 		protected override Expression DoResolve (ResolveContext ec)
2558 		{
2559 			expr = expr.Resolve (ec);
2560 			if (expr == null)
2561 				return null;
2562 
2563 			type = target_type.ResolveAsType (ec);
2564 			if (type == null)
2565 				return null;
2566 
2567 			if (type.IsStatic) {
2568 				ec.Report.Error (716, loc, "Cannot convert to static type `{0}'", type.GetSignatureForError ());
2569 				return null;
2570 			}
2571 
2572 			if (type.IsPointer) {
2573 				if (ec.CurrentIterator != null) {
2574 					UnsafeInsideIteratorError (ec, loc);
2575 				} else if (!ec.IsUnsafe) {
2576 					UnsafeError (ec, loc);
2577 				}
2578 			}
2579 
2580 			eclass = ExprClass.Value;
2581 
2582 			Constant c = expr as Constant;
2583 			if (c != null) {
2584 				c = c.Reduce (ec, type);
2585 				if (c != null)
2586 					return c;
2587 			}
2588 
2589 			var res = Convert.ExplicitConversion (ec, expr, type, loc);
2590 			if (res == expr)
2591 				return EmptyCast.Create (res, type);
2592 
2593 			return res;
2594 		}
2595 
CloneTo(CloneContext clonectx, Expression t)2596 		protected override void CloneTo (CloneContext clonectx, Expression t)
2597 		{
2598 			Cast target = (Cast) t;
2599 
2600 			target.target_type = target_type.Clone (clonectx);
2601 			target.expr = expr.Clone (clonectx);
2602 		}
2603 
Accept(StructuralVisitor visitor)2604 		public override object Accept (StructuralVisitor visitor)
2605 		{
2606 			return visitor.Visit (this);
2607 		}
2608 	}
2609 
2610 	public class ImplicitCast : ShimExpression
2611 	{
2612 		bool arrayAccess;
2613 
ImplicitCast(Expression expr, TypeSpec target, bool arrayAccess)2614 		public ImplicitCast (Expression expr, TypeSpec target, bool arrayAccess)
2615 			: base (expr)
2616 		{
2617 			this.loc = expr.Location;
2618 			this.type = target;
2619 			this.arrayAccess = arrayAccess;
2620 		}
2621 
DoResolve(ResolveContext ec)2622 		protected override Expression DoResolve (ResolveContext ec)
2623 		{
2624 			expr = expr.Resolve (ec);
2625 			if (expr == null)
2626 				return null;
2627 
2628 			if (arrayAccess)
2629 				expr = ConvertExpressionToArrayIndex (ec, expr);
2630 			else
2631 				expr = Convert.ImplicitConversionRequired (ec, expr, type, loc);
2632 
2633 			return expr;
2634 		}
2635 	}
2636 
2637 	public class DeclarationExpression : Expression, IMemoryLocation
2638 	{
2639 		LocalVariableReference lvr;
2640 
DeclarationExpression(FullNamedExpression variableType, LocalVariable variable)2641 		public DeclarationExpression (FullNamedExpression variableType, LocalVariable variable)
2642 		{
2643 			VariableType = variableType;
2644 			Variable = variable;
2645 			this.loc = variable.Location;
2646 		}
2647 
2648 		public LocalVariable Variable { get; set; }
2649 		public Expression Initializer { get; set; }
2650 		public FullNamedExpression VariableType { get; set; }
2651 
AddressOf(EmitContext ec, AddressOp mode)2652 		public void AddressOf (EmitContext ec, AddressOp mode)
2653 		{
2654 			if (!Variable.Created)
2655 				Variable.CreateBuilder (ec);
2656 
2657 			if (Initializer != null) {
2658 				lvr.EmitAssign (ec, Initializer, false, false);
2659 			}
2660 
2661 			lvr.AddressOf (ec, mode);
2662 		}
2663 
CloneTo(CloneContext clonectx, Expression t)2664 		protected override void CloneTo (CloneContext clonectx, Expression t)
2665 		{
2666 			var target = (DeclarationExpression) t;
2667 
2668 			target.VariableType = (FullNamedExpression) VariableType.Clone (clonectx);
2669 
2670 			if (Initializer != null)
2671 				target.Initializer = Initializer.Clone (clonectx);
2672 		}
2673 
CreateExpressionTree(ResolveContext rc)2674 		public override Expression CreateExpressionTree (ResolveContext rc)
2675 		{
2676 			rc.Report.Error (8198, loc, "An expression tree cannot contain out variable declaration");
2677 			return null;
2678 		}
2679 
DoResolveCommon(ResolveContext rc)2680 		bool DoResolveCommon (ResolveContext rc)
2681 		{
2682 			CheckExpressionVariable (rc);
2683 
2684 			var var_expr = VariableType as VarExpr;
2685 			if (var_expr != null) {
2686 				type = InternalType.VarOutType;
2687 			} else {
2688 				type = VariableType.ResolveAsType (rc);
2689 				if (type == null)
2690 					return false;
2691 			}
2692 
2693 			if (Initializer != null) {
2694 				Initializer = Initializer.Resolve (rc);
2695 
2696 				if (var_expr != null && Initializer != null && var_expr.InferType (rc, Initializer)) {
2697 					type = var_expr.Type;
2698 				}
2699 			}
2700 
2701 			Variable.Type = type;
2702 			lvr = new LocalVariableReference (Variable, loc);
2703 
2704 			eclass = ExprClass.Variable;
2705 			return true;
2706 		}
2707 
DoResolve(ResolveContext rc)2708 		protected override Expression DoResolve (ResolveContext rc)
2709 		{
2710 			if (DoResolveCommon (rc))
2711 				lvr.Resolve (rc);
2712 
2713 			return this;
2714 		}
2715 
DoResolveLValue(ResolveContext rc, Expression right_side)2716 		public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
2717 		{
2718 			if (lvr == null && DoResolveCommon (rc))
2719 				lvr.ResolveLValue (rc, right_side);
2720 
2721 			return this;
2722 		}
2723 
Emit(EmitContext ec)2724 		public override void Emit (EmitContext ec)
2725 		{
2726 			throw new NotImplementedException ();
2727 		}
2728 
EmitPrepare(EmitContext ec)2729 		public override void EmitPrepare (EmitContext ec)
2730 		{
2731 			Variable.CreateBuilder (ec);
2732 		}
2733 	}
2734 
2735 	//
2736 	// C# 2.0 Default value expression
2737 	//
2738 	public class DefaultValueExpression : Expression
2739 	{
2740 		Expression expr;
2741 
DefaultValueExpression(Expression expr, Location loc)2742 		public DefaultValueExpression (Expression expr, Location loc)
2743 		{
2744 			this.expr = expr;
2745 			this.loc = loc;
2746 		}
2747 
2748 		public Expression Expr {
2749 			get {
2750 				return this.expr;
2751 			}
2752 		}
2753 
2754 		public override bool IsSideEffectFree {
2755 			get {
2756 				return true;
2757 			}
2758 		}
2759 
ContainsEmitWithAwait()2760 		public override bool ContainsEmitWithAwait ()
2761 		{
2762 			return false;
2763 		}
2764 
CreateExpressionTree(ResolveContext ec)2765 		public override Expression CreateExpressionTree (ResolveContext ec)
2766 		{
2767 			Arguments args = new Arguments (2);
2768 			args.Add (new Argument (this));
2769 			args.Add (new Argument (new TypeOf (type, loc)));
2770 			return CreateExpressionFactoryCall (ec, "Constant", args);
2771 		}
2772 
DoResolve(ResolveContext ec)2773 		protected override Expression DoResolve (ResolveContext ec)
2774 		{
2775 			type = expr.ResolveAsType (ec);
2776 			if (type == null)
2777 				return null;
2778 
2779 			if (type.IsStatic) {
2780 				ec.Report.Error (-244, loc, "The `default value' operator cannot be applied to an operand of a static type");
2781 			}
2782 
2783 			if (type.IsPointer)
2784 				return new NullLiteral (Location).ConvertImplicitly (type);
2785 
2786 			if (TypeSpec.IsReferenceType (type))
2787 				return new NullConstant (type, loc);
2788 
2789 			Constant c = New.Constantify (type, expr.Location);
2790 			if (c != null)
2791 				return c;
2792 
2793 			eclass = ExprClass.Variable;
2794 			return this;
2795 		}
2796 
Emit(EmitContext ec)2797 		public override void Emit (EmitContext ec)
2798 		{
2799 			LocalTemporary temp_storage = new LocalTemporary(type);
2800 
2801 			temp_storage.AddressOf(ec, AddressOp.LoadStore);
2802 			ec.Emit(OpCodes.Initobj, type);
2803 			temp_storage.Emit(ec);
2804 			temp_storage.Release (ec);
2805 		}
2806 
2807 #if !STATIC
MakeExpression(BuilderContext ctx)2808 		public override SLE.Expression MakeExpression (BuilderContext ctx)
2809 		{
2810 			return SLE.Expression.Default (type.GetMetaInfo ());
2811 		}
2812 #endif
2813 
CloneTo(CloneContext clonectx, Expression t)2814 		protected override void CloneTo (CloneContext clonectx, Expression t)
2815 		{
2816 			DefaultValueExpression target = (DefaultValueExpression) t;
2817 
2818 			target.expr = expr.Clone (clonectx);
2819 		}
2820 
Accept(StructuralVisitor visitor)2821 		public override object Accept (StructuralVisitor visitor)
2822 		{
2823 			return visitor.Visit (this);
2824 		}
2825 	}
2826 
2827 	/// <summary>
2828 	///   Binary operators
2829 	/// </summary>
2830 	public class Binary : Expression, IDynamicBinder
2831 	{
2832 		public class PredefinedOperator
2833 		{
2834 			protected readonly TypeSpec left;
2835 			protected readonly TypeSpec right;
2836 			protected readonly TypeSpec left_unwrap;
2837 			protected readonly TypeSpec right_unwrap;
2838 			public readonly Operator OperatorsMask;
2839 			public TypeSpec ReturnType;
2840 
PredefinedOperator(TypeSpec ltype, TypeSpec rtype, Operator op_mask)2841 			public PredefinedOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask)
2842 				: this (ltype, rtype, op_mask, ltype)
2843 			{
2844 			}
2845 
PredefinedOperator(TypeSpec type, Operator op_mask, TypeSpec return_type)2846 			public PredefinedOperator (TypeSpec type, Operator op_mask, TypeSpec return_type)
2847 				: this (type, type, op_mask, return_type)
2848 			{
2849 			}
2850 
PredefinedOperator(TypeSpec type, Operator op_mask)2851 			public PredefinedOperator (TypeSpec type, Operator op_mask)
2852 				: this (type, type, op_mask, type)
2853 			{
2854 			}
2855 
PredefinedOperator(TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec return_type)2856 			public PredefinedOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec return_type)
2857 			{
2858 				if ((op_mask & Operator.ValuesOnlyMask) != 0)
2859 					throw new InternalErrorException ("Only masked values can be used");
2860 
2861 				if ((op_mask & Operator.NullableMask) != 0) {
2862 					left_unwrap = Nullable.NullableInfo.GetUnderlyingType (ltype);
2863 					right_unwrap = Nullable.NullableInfo.GetUnderlyingType (rtype);
2864 				} else {
2865 					left_unwrap = ltype;
2866 					right_unwrap = rtype;
2867 				}
2868 
2869 				this.left = ltype;
2870 				this.right = rtype;
2871 				this.OperatorsMask = op_mask;
2872 				this.ReturnType = return_type;
2873 			}
2874 
2875 			public bool IsLifted {
2876 				get {
2877 					return (OperatorsMask & Operator.NullableMask) != 0;
2878 				}
2879 			}
2880 
ConvertResult(ResolveContext rc, Binary b)2881 			public virtual Expression ConvertResult (ResolveContext rc, Binary b)
2882 			{
2883 				Constant c;
2884 
2885 				var left_expr = b.left;
2886 				var right_expr = b.right;
2887 
2888 				b.type = ReturnType;
2889 
2890 				if (IsLifted) {
2891 					if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion)) {
2892 						b.left = Convert.ImplicitConversion (rc, b.left, left, b.left.Location);
2893 						b.right = Convert.ImplicitConversion (rc, b.right, right, b.right.Location);
2894 					}
2895 
2896 					if (right_expr.IsNull) {
2897 						if ((b.oper & Operator.EqualityMask) != 0) {
2898 							if (!left_expr.Type.IsNullableType && BuiltinTypeSpec.IsPrimitiveType (left_expr.Type))
2899 								return b.CreateLiftedValueTypeResult (rc, left_expr.Type);
2900 						} else if ((b.oper & Operator.BitwiseMask) != 0) {
2901 							if (left_unwrap.BuiltinType != BuiltinTypeSpec.Type.Bool)
2902 								return Nullable.LiftedNull.CreateFromExpression (rc, b);
2903 						} else {
2904 							b.left = Convert.ImplicitConversion (rc, b.left, left, b.left.Location);
2905 							b.right = Convert.ImplicitConversion (rc, b.right, right, b.right.Location);
2906 
2907 							if ((b.Oper & (Operator.ArithmeticMask | Operator.ShiftMask)) != 0)
2908 								return Nullable.LiftedNull.CreateFromExpression (rc, b);
2909 
2910 							return b.CreateLiftedValueTypeResult (rc, left);
2911 						}
2912 					} else if (left_expr.IsNull) {
2913 						if ((b.oper & Operator.EqualityMask) != 0) {
2914 							if (!right_expr.Type.IsNullableType && BuiltinTypeSpec.IsPrimitiveType (right_expr.Type))
2915 								return b.CreateLiftedValueTypeResult (rc, right_expr.Type);
2916 						} else if ((b.oper & Operator.BitwiseMask) != 0) {
2917 							if (right_unwrap.BuiltinType != BuiltinTypeSpec.Type.Bool)
2918 								return Nullable.LiftedNull.CreateFromExpression (rc, b);
2919 						} else {
2920 							b.left = Convert.ImplicitConversion (rc, b.left, left, b.left.Location);
2921 							b.right = Convert.ImplicitConversion (rc, b.right, right, b.right.Location);
2922 
2923 							if ((b.Oper & (Operator.ArithmeticMask | Operator.ShiftMask)) != 0)
2924 								return Nullable.LiftedNull.CreateFromExpression (rc, b);
2925 
2926 							return b.CreateLiftedValueTypeResult (rc, right);
2927 						}
2928 					}
2929 				}
2930 
2931 				//
2932 				// A user operators does not support multiple user conversions, but decimal type
2933 				// is considered to be predefined type therefore we apply predefined operators rules
2934 				// and then look for decimal user-operator implementation
2935 				//
2936 				if (left.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
2937 					b.left = Convert.ImplicitConversion (rc, b.left, left, b.left.Location);
2938 					b.right = Convert.ImplicitConversion (rc, b.right, right, b.right.Location);
2939 
2940 					return b.ResolveUserOperator (rc, b.left, b.right);
2941 				}
2942 
2943 				c = right_expr as Constant;
2944 				if (c != null) {
2945 					if (c.IsDefaultValue) {
2946 						//
2947 						// Optimizes
2948 						//
2949 						// (expr + 0) to expr
2950 						// (expr - 0) to expr
2951 						// (bool? | false) to bool?
2952 						//
2953 						if (b.oper == Operator.Addition || b.oper == Operator.Subtraction ||
2954 							(b.oper == Operator.BitwiseOr && left_unwrap.BuiltinType == BuiltinTypeSpec.Type.Bool && c is BoolConstant)) {
2955 							b.left = Convert.ImplicitConversion (rc, b.left, left, b.left.Location);
2956 							return ReducedExpression.Create (b.left, b).Resolve (rc);
2957 						}
2958 
2959 						//
2960 						// Optimizes (value &/&& 0) to 0
2961 						//
2962 						if ((b.oper == Operator.BitwiseAnd || b.oper == Operator.LogicalAnd) && !IsLifted) {
2963 							Constant side_effect = new SideEffectConstant (c, b.left, c.Location);
2964 							return ReducedExpression.Create (side_effect, b);
2965 						}
2966 					} else {
2967 						//
2968 						// Optimizes (bool? & true) to bool?
2969 						//
2970 						if (IsLifted && left_unwrap.BuiltinType == BuiltinTypeSpec.Type.Bool && b.oper == Operator.BitwiseAnd) {
2971 							return ReducedExpression.Create (b.left, b).Resolve (rc);
2972 						}
2973 					}
2974 
2975 					if ((b.oper == Operator.Multiply || b.oper == Operator.Division) && c.IsOneInteger)
2976 						return ReducedExpression.Create (b.left, b).Resolve (rc);
2977 
2978 					if ((b.oper & Operator.ShiftMask) != 0 && c is IntConstant) {
2979 						b.right = new IntConstant (rc.BuiltinTypes, ((IntConstant) c).Value & GetShiftMask (left_unwrap), b.right.Location);
2980 					}
2981 				}
2982 
2983 				c = b.left as Constant;
2984 				if (c != null) {
2985 					if (c.IsDefaultValue) {
2986 						//
2987 						// Optimizes
2988 						//
2989 						// (0 + expr) to expr
2990 						// (false | bool?) to bool?
2991 						//
2992 						if (b.oper == Operator.Addition ||
2993 							(b.oper == Operator.BitwiseOr && right_unwrap.BuiltinType == BuiltinTypeSpec.Type.Bool && c is BoolConstant)) {
2994 							b.right = Convert.ImplicitConversion (rc, b.right, right, b.right.Location);
2995 							return ReducedExpression.Create (b.right, b).Resolve (rc);
2996 						}
2997 
2998 						//
2999 						// Optimizes (false && expr) to false
3000 						//
3001 						if (b.oper == Operator.LogicalAnd && c.Type.BuiltinType == BuiltinTypeSpec.Type.Bool) {
3002 							// No rhs side-effects
3003 							Expression.Warning_UnreachableExpression (rc, b.right.StartLocation);
3004 							return ReducedExpression.Create (c, b);
3005 						}
3006 
3007 						//
3008 						// Optimizes (0 & value) to 0
3009 						//
3010 						if (b.oper == Operator.BitwiseAnd && !IsLifted) {
3011 							Constant side_effect = new SideEffectConstant (c, b.right, c.Location);
3012 							return ReducedExpression.Create (side_effect, b);
3013 						}
3014 					} else {
3015 						//
3016 						// Optimizes (true & bool?) to bool?
3017 						//
3018 						if (IsLifted && left_unwrap.BuiltinType == BuiltinTypeSpec.Type.Bool && b.oper == Operator.BitwiseAnd) {
3019 							return ReducedExpression.Create (b.right, b).Resolve (rc);
3020 						}
3021 
3022 						//
3023 						// Optimizes (true || expr) to true
3024 						//
3025 						if (b.oper == Operator.LogicalOr && c.Type.BuiltinType == BuiltinTypeSpec.Type.Bool) {
3026 							// No rhs side-effects
3027 							Expression.Warning_UnreachableExpression (rc, b.right.StartLocation);
3028 							return ReducedExpression.Create (c, b);
3029 						}
3030 					}
3031 
3032 					if (b.oper == Operator.Multiply && c.IsOneInteger)
3033 						return ReducedExpression.Create (b.right, b).Resolve (rc);
3034 				}
3035 
3036 				if (IsLifted) {
3037 					var lifted = new Nullable.LiftedBinaryOperator (b);
3038 
3039 					TypeSpec ltype, rtype;
3040 					if (b.left.Type.IsNullableType) {
3041 						lifted.UnwrapLeft = new Nullable.Unwrap (b.left);
3042 						ltype = left_unwrap;
3043 					} else {
3044 						ltype = left;
3045 					}
3046 
3047 					if (b.right.Type.IsNullableType) {
3048 						lifted.UnwrapRight = new Nullable.Unwrap (b.right);
3049 						rtype = right_unwrap;
3050 					} else {
3051 						rtype = right;
3052 					}
3053 
3054 					lifted.Left = b.left.IsNull ?
3055 						Nullable.LiftedNull.Create (ltype, b.left.Location) :
3056 						Convert.ImplicitConversion (rc, lifted.UnwrapLeft ?? b.left, ltype, b.left.Location);
3057 
3058 					lifted.Right = b.right.IsNull ?
3059 						Nullable.LiftedNull.Create (rtype, b.right.Location) :
3060 						Convert.ImplicitConversion (rc, lifted.UnwrapRight ?? b.right, rtype, b.right.Location);
3061 
3062 					return lifted.Resolve (rc);
3063 				}
3064 
3065 				b.left = Convert.ImplicitConversion (rc, b.left, left, b.left.Location);
3066 				b.right = Convert.ImplicitConversion (rc, b.right, right, b.right.Location);
3067 
3068 				return b;
3069 			}
3070 
IsPrimitiveApplicable(TypeSpec ltype, TypeSpec rtype)3071 			public bool IsPrimitiveApplicable (TypeSpec ltype, TypeSpec rtype)
3072 			{
3073 				//
3074 				// We are dealing with primitive types only
3075 				//
3076 				return left == ltype && ltype == rtype;
3077 			}
3078 
IsApplicable(ResolveContext ec, Expression lexpr, Expression rexpr)3079 			public virtual bool IsApplicable (ResolveContext ec, Expression lexpr, Expression rexpr)
3080 			{
3081 				// Quick path
3082 				if (left == lexpr.Type && right == rexpr.Type)
3083 					return true;
3084 
3085 				return Convert.ImplicitConversionExists (ec, lexpr, left) &&
3086 					Convert.ImplicitConversionExists (ec, rexpr, right);
3087 			}
3088 
ResolveBetterOperator(ResolveContext ec, PredefinedOperator best_operator)3089 			public PredefinedOperator ResolveBetterOperator (ResolveContext ec, PredefinedOperator best_operator)
3090 			{
3091 				if ((OperatorsMask & Operator.DecomposedMask) != 0)
3092 					return best_operator;
3093 
3094 				if ((best_operator.OperatorsMask & Operator.DecomposedMask) != 0)
3095 					return this;
3096 
3097 				int result = 0;
3098 				if (left != null && best_operator.left != null) {
3099 					result = OverloadResolver.BetterTypeConversion (ec, best_operator.left_unwrap, left_unwrap);
3100 				}
3101 
3102 				//
3103 				// When second argument is same as the first one, the result is same
3104 				//
3105 				if (right != null && (left != right || best_operator.left != best_operator.right)) {
3106 					result |= OverloadResolver.BetterTypeConversion (ec, best_operator.right_unwrap, right_unwrap);
3107 				}
3108 
3109 				if (result == 0 || result > 2)
3110 					return null;
3111 
3112 				return result == 1 ? best_operator : this;
3113 			}
3114 		}
3115 
3116 		sealed class PredefinedStringOperator : PredefinedOperator
3117 		{
PredefinedStringOperator(TypeSpec type, Operator op_mask, TypeSpec retType)3118 			public PredefinedStringOperator (TypeSpec type, Operator op_mask, TypeSpec retType)
3119 				: base (type, type, op_mask, retType)
3120 			{
3121 			}
3122 
PredefinedStringOperator(TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec retType)3123 			public PredefinedStringOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec retType)
3124 				: base (ltype, rtype, op_mask, retType)
3125 			{
3126 			}
3127 
ConvertResult(ResolveContext ec, Binary b)3128 			public override Expression ConvertResult (ResolveContext ec, Binary b)
3129 			{
3130 				//
3131 				// Use original expression for nullable arguments
3132 				//
3133 				Nullable.Unwrap unwrap = b.left as Nullable.Unwrap;
3134 				if (unwrap != null)
3135 					b.left = unwrap.Original;
3136 
3137 				unwrap = b.right as Nullable.Unwrap;
3138 				if (unwrap != null)
3139 					b.right = unwrap.Original;
3140 
3141 				b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location);
3142 				b.right = Convert.ImplicitConversion (ec, b.right, right, b.right.Location);
3143 
3144 				//
3145 				// Start a new concat expression using converted expression
3146 				//
3147 				return StringConcat.Create (ec, b.left, b.right, b.loc);
3148 			}
3149 		}
3150 
3151 		sealed class PredefinedEqualityOperator : PredefinedOperator
3152 		{
3153 			MethodSpec equal_method, inequal_method;
3154 
PredefinedEqualityOperator(TypeSpec arg, TypeSpec retType)3155 			public PredefinedEqualityOperator (TypeSpec arg, TypeSpec retType)
3156 				: base (arg, arg, Operator.EqualityMask, retType)
3157 			{
3158 			}
3159 
ConvertResult(ResolveContext ec, Binary b)3160 			public override Expression ConvertResult (ResolveContext ec, Binary b)
3161 			{
3162 				b.type = ReturnType;
3163 
3164 				b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location);
3165 				b.right = Convert.ImplicitConversion (ec, b.right, right, b.right.Location);
3166 
3167 				Arguments args = new Arguments (2);
3168 				args.Add (new Argument (b.left));
3169 				args.Add (new Argument (b.right));
3170 
3171 				MethodSpec method;
3172 				if (b.oper == Operator.Equality) {
3173 					if (equal_method == null) {
3174 						if (left.BuiltinType == BuiltinTypeSpec.Type.String)
3175 							equal_method = ec.Module.PredefinedMembers.StringEqual.Resolve (b.loc);
3176 						else if (left.BuiltinType == BuiltinTypeSpec.Type.Delegate)
3177 							equal_method = ec.Module.PredefinedMembers.DelegateEqual.Resolve (b.loc);
3178 						else
3179 							throw new NotImplementedException (left.GetSignatureForError ());
3180 					}
3181 
3182 					method = equal_method;
3183 				} else {
3184 					if (inequal_method == null) {
3185 						if (left.BuiltinType == BuiltinTypeSpec.Type.String)
3186 							inequal_method = ec.Module.PredefinedMembers.StringInequal.Resolve (b.loc);
3187 						else if (left.BuiltinType == BuiltinTypeSpec.Type.Delegate)
3188 							inequal_method = ec.Module.PredefinedMembers.DelegateInequal.Resolve (b.loc);
3189 						else
3190 							throw new NotImplementedException (left.GetSignatureForError ());
3191 					}
3192 
3193 					method = inequal_method;
3194 				}
3195 
3196 				return new UserOperatorCall (method, args, b.CreateExpressionTree, b.loc);
3197 			}
3198 		}
3199 
3200 		class PredefinedPointerOperator : PredefinedOperator
3201 		{
PredefinedPointerOperator(TypeSpec ltype, TypeSpec rtype, Operator op_mask)3202 			public PredefinedPointerOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask)
3203 				: base (ltype, rtype, op_mask)
3204 			{
3205 			}
3206 
PredefinedPointerOperator(TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec retType)3207 			public PredefinedPointerOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec retType)
3208 				: base (ltype, rtype, op_mask, retType)
3209 			{
3210 			}
3211 
PredefinedPointerOperator(TypeSpec type, Operator op_mask, TypeSpec return_type)3212 			public PredefinedPointerOperator (TypeSpec type, Operator op_mask, TypeSpec return_type)
3213 				: base (type, op_mask, return_type)
3214 			{
3215 			}
3216 
IsApplicable(ResolveContext ec, Expression lexpr, Expression rexpr)3217 			public override bool IsApplicable (ResolveContext ec, Expression lexpr, Expression rexpr)
3218 			{
3219 				if (left == null) {
3220 					if (!lexpr.Type.IsPointer)
3221 						return false;
3222 				} else {
3223 					if (!Convert.ImplicitConversionExists (ec, lexpr, left))
3224 						return false;
3225 				}
3226 
3227 				if (right == null) {
3228 					if (!rexpr.Type.IsPointer)
3229 						return false;
3230 				} else {
3231 					if (!Convert.ImplicitConversionExists (ec, rexpr, right))
3232 						return false;
3233 				}
3234 
3235 				return true;
3236 			}
3237 
ConvertResult(ResolveContext ec, Binary b)3238 			public override Expression ConvertResult (ResolveContext ec, Binary b)
3239 			{
3240 				if (left != null) {
3241 					b.left = Convert.UserDefinedConversion (ec, b.left, left, Convert.UserConversionRestriction.ImplicitOnly, b.loc) ?? EmptyCast.Create (b.left, left);
3242 				} else if (right != null) {
3243 					b.right = Convert.UserDefinedConversion (ec, b.right, right, Convert.UserConversionRestriction.ImplicitOnly, b.loc) ?? EmptyCast.Create (b.right, right);
3244 				}
3245 
3246 				TypeSpec r_type = ReturnType;
3247 				Expression left_arg, right_arg;
3248 				if (r_type == null) {
3249 					if (left == null) {
3250 						left_arg = b.left;
3251 						right_arg = b.right;
3252 						r_type = b.left.Type;
3253 					} else {
3254 						left_arg = b.right;
3255 						right_arg = b.left;
3256 						r_type = b.right.Type;
3257 					}
3258 				} else {
3259 					left_arg = b.left;
3260 					right_arg = b.right;
3261 				}
3262 
3263 				return new PointerArithmetic (b.oper, left_arg, right_arg, r_type, b.loc).Resolve (ec);
3264 			}
3265 		}
3266 
3267 		[Flags]
3268 		public enum Operator {
3269 			Multiply	= 0 | ArithmeticMask,
3270 			Division	= 1 | ArithmeticMask,
3271 			Modulus		= 2 | ArithmeticMask,
3272 			Addition	= 3 | ArithmeticMask | AdditionMask,
3273 			Subtraction = 4 | ArithmeticMask | SubtractionMask,
3274 
3275 			LeftShift	= 5 | ShiftMask,
3276 			RightShift	= 6 | ShiftMask,
3277 
3278 			LessThan	= 7 | ComparisonMask | RelationalMask,
3279 			GreaterThan	= 8 | ComparisonMask | RelationalMask,
3280 			LessThanOrEqual		= 9 | ComparisonMask | RelationalMask,
3281 			GreaterThanOrEqual	= 10 | ComparisonMask | RelationalMask,
3282 			Equality	= 11 | ComparisonMask | EqualityMask,
3283 			Inequality	= 12 | ComparisonMask | EqualityMask,
3284 
3285 			BitwiseAnd	= 13 | BitwiseMask,
3286 			ExclusiveOr	= 14 | BitwiseMask,
3287 			BitwiseOr	= 15 | BitwiseMask,
3288 
3289 			LogicalAnd	= 16 | LogicalMask,
3290 			LogicalOr	= 17 | LogicalMask,
3291 
3292 			//
3293 			// Operator masks
3294 			//
3295 			ValuesOnlyMask	= ArithmeticMask - 1,
3296 			ArithmeticMask	= 1 << 5,
3297 			ShiftMask		= 1 << 6,
3298 			ComparisonMask	= 1 << 7,
3299 			EqualityMask	= 1 << 8,
3300 			BitwiseMask		= 1 << 9,
3301 			LogicalMask		= 1 << 10,
3302 			AdditionMask	= 1 << 11,
3303 			SubtractionMask	= 1 << 12,
3304 			RelationalMask	= 1 << 13,
3305 
3306 			DecomposedMask	= 1 << 19,
3307 			NullableMask	= 1 << 20
3308 		}
3309 
3310 		[Flags]
3311 		public enum State : byte
3312 		{
3313 			None = 0,
3314 			Compound = 1 << 1,
3315 			UserOperatorsExcluded = 1 << 2
3316 		}
3317 
3318 		readonly Operator oper;
3319 		Expression left, right;
3320 		State state;
3321 		ConvCast.Mode enum_conversion;
3322 
Binary(Operator oper, Expression left, Expression right, bool isCompound)3323 		public Binary (Operator oper, Expression left, Expression right, bool isCompound)
3324 			: this (oper, left, right, State.Compound)
3325 		{
3326 		}
3327 
Binary(Operator oper, Expression left, Expression right, State state)3328 		public Binary (Operator oper, Expression left, Expression right, State state)
3329 			: this (oper, left, right)
3330 		{
3331 			this.state = state;
3332 		}
3333 
Binary(Operator oper, Expression left, Expression right)3334 		public Binary (Operator oper, Expression left, Expression right)
3335 			: this (oper, left, right, left.Location)
3336 		{
3337 		}
3338 
Binary(Operator oper, Expression left, Expression right, Location loc)3339 		public Binary (Operator oper, Expression left, Expression right, Location loc)
3340 		{
3341 			this.oper = oper;
3342 			this.left = left;
3343 			this.right = right;
3344 			this.loc = loc;
3345 		}
3346 
3347 		#region Properties
3348 
3349 		public bool IsCompound {
3350 			get {
3351 				return (state & State.Compound) != 0;
3352 			}
3353 		}
3354 
3355 		public Operator Oper {
3356 			get {
3357 				return oper;
3358 			}
3359 		}
3360 
3361 		public Expression Left {
3362 			get {
3363 				return this.left;
3364 			}
3365 		}
3366 
3367 		public Expression Right {
3368 			get {
3369 				return this.right;
3370 			}
3371 		}
3372 
3373 		public override Location StartLocation {
3374 			get {
3375 				return left.StartLocation;
3376 			}
3377 		}
3378 
3379 		#endregion
3380 
3381 		/// <summary>
3382 		///   Returns a stringified representation of the Operator
3383 		/// </summary>
OperName(Operator oper)3384 		string OperName (Operator oper)
3385 		{
3386 			string s;
3387 			switch (oper){
3388 			case Operator.Multiply:
3389 				s = "*";
3390 				break;
3391 			case Operator.Division:
3392 				s = "/";
3393 				break;
3394 			case Operator.Modulus:
3395 				s = "%";
3396 				break;
3397 			case Operator.Addition:
3398 				s = "+";
3399 				break;
3400 			case Operator.Subtraction:
3401 				s = "-";
3402 				break;
3403 			case Operator.LeftShift:
3404 				s = "<<";
3405 				break;
3406 			case Operator.RightShift:
3407 				s = ">>";
3408 				break;
3409 			case Operator.LessThan:
3410 				s = "<";
3411 				break;
3412 			case Operator.GreaterThan:
3413 				s = ">";
3414 				break;
3415 			case Operator.LessThanOrEqual:
3416 				s = "<=";
3417 				break;
3418 			case Operator.GreaterThanOrEqual:
3419 				s = ">=";
3420 				break;
3421 			case Operator.Equality:
3422 				s = "==";
3423 				break;
3424 			case Operator.Inequality:
3425 				s = "!=";
3426 				break;
3427 			case Operator.BitwiseAnd:
3428 				s = "&";
3429 				break;
3430 			case Operator.BitwiseOr:
3431 				s = "|";
3432 				break;
3433 			case Operator.ExclusiveOr:
3434 				s = "^";
3435 				break;
3436 			case Operator.LogicalOr:
3437 				s = "||";
3438 				break;
3439 			case Operator.LogicalAnd:
3440 				s = "&&";
3441 				break;
3442 			default:
3443 				s = oper.ToString ();
3444 				break;
3445 			}
3446 
3447 			if (IsCompound)
3448 				return s + "=";
3449 
3450 			return s;
3451 		}
3452 
Error_OperatorCannotBeApplied(ResolveContext ec, Expression left, Expression right, Operator oper, Location loc)3453 		public static void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right, Operator oper, Location loc)
3454 		{
3455 			new Binary (oper, left, right).Error_OperatorCannotBeApplied (ec, left, right);
3456 		}
3457 
Error_OperatorCannotBeApplied(ResolveContext ec, Expression left, Expression right, string oper, Location loc)3458 		public static void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right, string oper, Location loc)
3459 		{
3460 			if (left.Type == InternalType.ErrorType || right.Type == InternalType.ErrorType)
3461 				return;
3462 
3463 			string l, r;
3464 			l = left.Type.GetSignatureForError ();
3465 			r = right.Type.GetSignatureForError ();
3466 
3467 			ec.Report.Error (19, loc, "Operator `{0}' cannot be applied to operands of type `{1}' and `{2}'",
3468 				oper, l, r);
3469 		}
3470 
Error_OperatorCannotBeApplied(ResolveContext ec, Expression left, Expression right)3471 		void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right)
3472 		{
3473 			Error_OperatorCannotBeApplied (ec, left, right, OperName (oper), loc);
3474 		}
3475 
FlowAnalysis(FlowAnalysisContext fc)3476 		public override void FlowAnalysis (FlowAnalysisContext fc)
3477 		{
3478 			//
3479 			// Optimized version when on-true/on-false data are not needed
3480 			//
3481 			if ((oper & Operator.LogicalMask) == 0) {
3482 				left.FlowAnalysis (fc);
3483 				right.FlowAnalysis (fc);
3484 				return;
3485 			}
3486 
3487 			left.FlowAnalysisConditional (fc);
3488 			var left_fc_ontrue = fc.DefiniteAssignmentOnTrue;
3489 			var left_fc_onfalse = fc.DefiniteAssignmentOnFalse;
3490 
3491 			fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment = new DefiniteAssignmentBitSet (
3492 				oper == Operator.LogicalOr ? left_fc_onfalse : left_fc_ontrue);
3493 			right.FlowAnalysisConditional (fc);
3494 
3495 			if (oper == Operator.LogicalOr)
3496 				fc.DefiniteAssignment = (left_fc_onfalse | (fc.DefiniteAssignmentOnFalse & fc.DefiniteAssignmentOnTrue)) & left_fc_ontrue;
3497 			else
3498 				fc.DefiniteAssignment = (left_fc_ontrue | (fc.DefiniteAssignmentOnFalse & fc.DefiniteAssignmentOnTrue)) & left_fc_onfalse;
3499 		}
3500 
FlowAnalysisConditional(FlowAnalysisContext fc)3501 		public override void FlowAnalysisConditional (FlowAnalysisContext fc)
3502 		{
3503 			if ((oper & Operator.LogicalMask) == 0) {
3504 				base.FlowAnalysisConditional (fc);
3505 				return;
3506 			}
3507 
3508 			left.FlowAnalysisConditional (fc);
3509 			var left_fc_ontrue = fc.DefiniteAssignmentOnTrue;
3510 			var left_fc_onfalse = fc.DefiniteAssignmentOnFalse;
3511 
3512 			fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment = new DefiniteAssignmentBitSet (
3513 				oper == Operator.LogicalOr ? left_fc_onfalse : left_fc_ontrue);
3514 			right.FlowAnalysisConditional (fc);
3515 
3516 			var lc = left as Constant;
3517 			if (oper == Operator.LogicalOr) {
3518 				fc.DefiniteAssignmentOnFalse = left_fc_onfalse | fc.DefiniteAssignmentOnFalse;
3519 				if (lc != null && lc.IsDefaultValue)
3520 					fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse;
3521 				else
3522 					fc.DefiniteAssignmentOnTrue = new DefiniteAssignmentBitSet (left_fc_ontrue & (left_fc_onfalse | fc.DefiniteAssignmentOnTrue));
3523 			} else {
3524 				fc.DefiniteAssignmentOnTrue = left_fc_ontrue | fc.DefiniteAssignmentOnTrue;
3525 				if (lc != null && !lc.IsDefaultValue)
3526 					fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignmentOnTrue;
3527 				else
3528 					fc.DefiniteAssignmentOnFalse = new DefiniteAssignmentBitSet ((left_fc_ontrue | fc.DefiniteAssignmentOnFalse) & left_fc_onfalse);
3529 			}
3530 		}
3531 
3532 		//
3533 		// Converts operator to System.Linq.Expressions.ExpressionType enum name
3534 		//
GetOperatorExpressionTypeName()3535 		string GetOperatorExpressionTypeName ()
3536 		{
3537 			switch (oper) {
3538 			case Operator.Addition:
3539 				return IsCompound ? "AddAssign" : "Add";
3540 			case Operator.BitwiseAnd:
3541 				return IsCompound ? "AndAssign" : "And";
3542 			case Operator.BitwiseOr:
3543 				return IsCompound ? "OrAssign" : "Or";
3544 			case Operator.Division:
3545 				return IsCompound ? "DivideAssign" : "Divide";
3546 			case Operator.ExclusiveOr:
3547 				return IsCompound ? "ExclusiveOrAssign" : "ExclusiveOr";
3548 			case Operator.Equality:
3549 				return "Equal";
3550 			case Operator.GreaterThan:
3551 				return "GreaterThan";
3552 			case Operator.GreaterThanOrEqual:
3553 				return "GreaterThanOrEqual";
3554 			case Operator.Inequality:
3555 				return "NotEqual";
3556 			case Operator.LeftShift:
3557 				return IsCompound ? "LeftShiftAssign" : "LeftShift";
3558 			case Operator.LessThan:
3559 				return "LessThan";
3560 			case Operator.LessThanOrEqual:
3561 				return "LessThanOrEqual";
3562 			case Operator.LogicalAnd:
3563 				return "And";
3564 			case Operator.LogicalOr:
3565 				return "Or";
3566 			case Operator.Modulus:
3567 				return IsCompound ? "ModuloAssign" : "Modulo";
3568 			case Operator.Multiply:
3569 				return IsCompound ? "MultiplyAssign" : "Multiply";
3570 			case Operator.RightShift:
3571 				return IsCompound ? "RightShiftAssign" : "RightShift";
3572 			case Operator.Subtraction:
3573 				return IsCompound ? "SubtractAssign" : "Subtract";
3574 			default:
3575 				throw new NotImplementedException ("Unknown expression type operator " + oper.ToString ());
3576 			}
3577 		}
3578 
ConvertBinaryToUserOperator(Operator op)3579 		public static CSharp.Operator.OpType ConvertBinaryToUserOperator (Operator op)
3580 		{
3581 			switch (op) {
3582 			case Operator.Addition:
3583 				return CSharp.Operator.OpType.Addition;
3584 			case Operator.BitwiseAnd:
3585 			case Operator.LogicalAnd:
3586 				return CSharp.Operator.OpType.BitwiseAnd;
3587 			case Operator.BitwiseOr:
3588 			case Operator.LogicalOr:
3589 				return CSharp.Operator.OpType.BitwiseOr;
3590 			case Operator.Division:
3591 				return CSharp.Operator.OpType.Division;
3592 			case Operator.Equality:
3593 				return CSharp.Operator.OpType.Equality;
3594 			case Operator.ExclusiveOr:
3595 				return CSharp.Operator.OpType.ExclusiveOr;
3596 			case Operator.GreaterThan:
3597 				return CSharp.Operator.OpType.GreaterThan;
3598 			case Operator.GreaterThanOrEqual:
3599 				return CSharp.Operator.OpType.GreaterThanOrEqual;
3600 			case Operator.Inequality:
3601 				return CSharp.Operator.OpType.Inequality;
3602 			case Operator.LeftShift:
3603 				return CSharp.Operator.OpType.LeftShift;
3604 			case Operator.LessThan:
3605 				return CSharp.Operator.OpType.LessThan;
3606 			case Operator.LessThanOrEqual:
3607 				return CSharp.Operator.OpType.LessThanOrEqual;
3608 			case Operator.Modulus:
3609 				return CSharp.Operator.OpType.Modulus;
3610 			case Operator.Multiply:
3611 				return CSharp.Operator.OpType.Multiply;
3612 			case Operator.RightShift:
3613 				return CSharp.Operator.OpType.RightShift;
3614 			case Operator.Subtraction:
3615 				return CSharp.Operator.OpType.Subtraction;
3616 			default:
3617 				throw new InternalErrorException (op.ToString ());
3618 			}
3619 		}
3620 
ContainsEmitWithAwait()3621 		public override bool ContainsEmitWithAwait ()
3622 		{
3623 			return left.ContainsEmitWithAwait () || right.ContainsEmitWithAwait ();
3624 		}
3625 
EmitOperatorOpcode(EmitContext ec, Operator oper, TypeSpec l, Expression right)3626 		public static void EmitOperatorOpcode (EmitContext ec, Operator oper, TypeSpec l, Expression right)
3627 		{
3628 			OpCode opcode;
3629 
3630 			switch (oper){
3631 			case Operator.Multiply:
3632 				if (ec.HasSet (EmitContext.Options.CheckedScope)) {
3633 					if (l.BuiltinType == BuiltinTypeSpec.Type.Int || l.BuiltinType == BuiltinTypeSpec.Type.Long)
3634 						opcode = OpCodes.Mul_Ovf;
3635 					else if (!IsFloat (l))
3636 						opcode = OpCodes.Mul_Ovf_Un;
3637 					else
3638 						opcode = OpCodes.Mul;
3639 				} else
3640 					opcode = OpCodes.Mul;
3641 
3642 				break;
3643 
3644 			case Operator.Division:
3645 				if (IsUnsigned (l))
3646 					opcode = OpCodes.Div_Un;
3647 				else
3648 					opcode = OpCodes.Div;
3649 				break;
3650 
3651 			case Operator.Modulus:
3652 				if (IsUnsigned (l))
3653 					opcode = OpCodes.Rem_Un;
3654 				else
3655 					opcode = OpCodes.Rem;
3656 				break;
3657 
3658 			case Operator.Addition:
3659 				if (ec.HasSet (EmitContext.Options.CheckedScope)) {
3660 					if (l.BuiltinType == BuiltinTypeSpec.Type.Int || l.BuiltinType == BuiltinTypeSpec.Type.Long)
3661 						opcode = OpCodes.Add_Ovf;
3662 					else if (!IsFloat (l))
3663 						opcode = OpCodes.Add_Ovf_Un;
3664 					else
3665 						opcode = OpCodes.Add;
3666 				} else
3667 					opcode = OpCodes.Add;
3668 				break;
3669 
3670 			case Operator.Subtraction:
3671 				if (ec.HasSet (EmitContext.Options.CheckedScope)) {
3672 					if (l.BuiltinType == BuiltinTypeSpec.Type.Int || l.BuiltinType == BuiltinTypeSpec.Type.Long)
3673 						opcode = OpCodes.Sub_Ovf;
3674 					else if (!IsFloat (l))
3675 						opcode = OpCodes.Sub_Ovf_Un;
3676 					else
3677 						opcode = OpCodes.Sub;
3678 				} else
3679 					opcode = OpCodes.Sub;
3680 				break;
3681 
3682 			case Operator.RightShift:
3683 				if (!(right is IntConstant)) {
3684 					ec.EmitInt (GetShiftMask (l));
3685 					ec.Emit (OpCodes.And);
3686 				}
3687 
3688 				if (IsUnsigned (l))
3689 					opcode = OpCodes.Shr_Un;
3690 				else
3691 					opcode = OpCodes.Shr;
3692 				break;
3693 
3694 			case Operator.LeftShift:
3695 				if (!(right is IntConstant)) {
3696 					ec.EmitInt (GetShiftMask (l));
3697 					ec.Emit (OpCodes.And);
3698 				}
3699 
3700 				opcode = OpCodes.Shl;
3701 				break;
3702 
3703 			case Operator.Equality:
3704 				opcode = OpCodes.Ceq;
3705 				break;
3706 
3707 			case Operator.Inequality:
3708 				ec.Emit (OpCodes.Ceq);
3709 				ec.EmitInt (0);
3710 
3711 				opcode = OpCodes.Ceq;
3712 				break;
3713 
3714 			case Operator.LessThan:
3715 				if (IsUnsigned (l))
3716 					opcode = OpCodes.Clt_Un;
3717 				else
3718 					opcode = OpCodes.Clt;
3719 				break;
3720 
3721 			case Operator.GreaterThan:
3722 				if (IsUnsigned (l))
3723 					opcode = OpCodes.Cgt_Un;
3724 				else
3725 					opcode = OpCodes.Cgt;
3726 				break;
3727 
3728 			case Operator.LessThanOrEqual:
3729 				if (IsUnsigned (l) || IsFloat (l))
3730 					ec.Emit (OpCodes.Cgt_Un);
3731 				else
3732 					ec.Emit (OpCodes.Cgt);
3733 				ec.EmitInt (0);
3734 
3735 				opcode = OpCodes.Ceq;
3736 				break;
3737 
3738 			case Operator.GreaterThanOrEqual:
3739 				if (IsUnsigned (l) || IsFloat (l))
3740 					ec.Emit (OpCodes.Clt_Un);
3741 				else
3742 					ec.Emit (OpCodes.Clt);
3743 
3744 				ec.EmitInt (0);
3745 
3746 				opcode = OpCodes.Ceq;
3747 				break;
3748 
3749 			case Operator.BitwiseOr:
3750 				opcode = OpCodes.Or;
3751 				break;
3752 
3753 			case Operator.BitwiseAnd:
3754 				opcode = OpCodes.And;
3755 				break;
3756 
3757 			case Operator.ExclusiveOr:
3758 				opcode = OpCodes.Xor;
3759 				break;
3760 
3761 			default:
3762 				throw new InternalErrorException (oper.ToString ());
3763 			}
3764 
3765 			ec.Emit (opcode);
3766 		}
3767 
GetShiftMask(TypeSpec type)3768 		static int GetShiftMask (TypeSpec type)
3769 		{
3770 			return type.BuiltinType == BuiltinTypeSpec.Type.Int || type.BuiltinType == BuiltinTypeSpec.Type.UInt ? 0x1f : 0x3f;
3771 		}
3772 
IsUnsigned(TypeSpec t)3773 		static bool IsUnsigned (TypeSpec t)
3774 		{
3775 			switch (t.BuiltinType) {
3776 			case BuiltinTypeSpec.Type.Char:
3777 			case BuiltinTypeSpec.Type.UInt:
3778 			case BuiltinTypeSpec.Type.ULong:
3779 			case BuiltinTypeSpec.Type.UShort:
3780 			case BuiltinTypeSpec.Type.Byte:
3781 				return true;
3782 			}
3783 
3784 			return t.IsPointer;
3785 		}
3786 
IsFloat(TypeSpec t)3787 		static bool IsFloat (TypeSpec t)
3788 		{
3789 			return t.BuiltinType == BuiltinTypeSpec.Type.Float || t.BuiltinType == BuiltinTypeSpec.Type.Double;
3790 		}
3791 
ResolveOperator(ResolveContext rc)3792 		public Expression ResolveOperator (ResolveContext rc)
3793 		{
3794 			eclass = ExprClass.Value;
3795 
3796 			TypeSpec l = left.Type;
3797 			TypeSpec r = right.Type;
3798 			Expression expr;
3799 			bool primitives_only = false;
3800 
3801 			//
3802 			// Handles predefined primitive types
3803 			//
3804 			if ((BuiltinTypeSpec.IsPrimitiveType (l) || (l.IsNullableType && BuiltinTypeSpec.IsPrimitiveType (Nullable.NullableInfo.GetUnderlyingType (l)))) &&
3805 				(BuiltinTypeSpec.IsPrimitiveType (r) || (r.IsNullableType && BuiltinTypeSpec.IsPrimitiveType (Nullable.NullableInfo.GetUnderlyingType (r))))) {
3806 				if ((oper & Operator.ShiftMask) == 0) {
3807 					if (!DoBinaryOperatorPromotion (rc))
3808 						return null;
3809 
3810 					primitives_only = BuiltinTypeSpec.IsPrimitiveType (l) && BuiltinTypeSpec.IsPrimitiveType (r);
3811 				}
3812 			} else {
3813 				// Pointers
3814 				if (l.IsPointer || r.IsPointer)
3815 					return ResolveOperatorPointer (rc, l, r);
3816 
3817 				// User operators
3818 				if ((state & State.UserOperatorsExcluded) == 0) {
3819 					expr = ResolveUserOperator (rc, left, right);
3820 					if (expr != null)
3821 						return expr;
3822 				}
3823 
3824 				bool lenum = l.IsEnum;
3825 				bool renum = r.IsEnum;
3826 				if ((oper & (Operator.ComparisonMask | Operator.BitwiseMask)) != 0) {
3827 					//
3828 					// Enumerations
3829 					//
3830 					if (IsEnumOrNullableEnum (l) || IsEnumOrNullableEnum (r)) {
3831 						expr = ResolveSingleEnumOperators (rc, lenum, renum, l, r);
3832 
3833 						if (expr == null)
3834 							return null;
3835 
3836 						if ((oper & Operator.BitwiseMask) != 0) {
3837 							expr = EmptyCast.Create (expr, type);
3838 							enum_conversion = GetEnumResultCast (type);
3839 
3840 							if (oper == Operator.BitwiseAnd && left.Type.IsEnum && right.Type.IsEnum) {
3841 								expr = OptimizeAndOperation (expr);
3842 							}
3843 						}
3844 
3845 						left = ConvertEnumOperandToUnderlyingType (rc, left, r.IsNullableType);
3846 						right = ConvertEnumOperandToUnderlyingType (rc, right, l.IsNullableType);
3847 						return expr;
3848 					}
3849 				} else if ((oper == Operator.Addition || oper == Operator.Subtraction)) {
3850 					if (IsEnumOrNullableEnum (l) || IsEnumOrNullableEnum (r)) {
3851 						//
3852 						// Enumerations
3853 						//
3854 						expr = ResolveEnumOperators (rc, lenum, renum, l, r);
3855 
3856 						//
3857 						// We cannot break here there is also Enum + String possible match
3858 						// which is not ambiguous with predefined enum operators
3859 						//
3860 						if (expr != null) {
3861 							left = ConvertEnumOperandToUnderlyingType (rc, left, false);
3862 							right = ConvertEnumOperandToUnderlyingType (rc, right, false);
3863 
3864 							return expr;
3865 						}
3866 					} else if (l.IsDelegate || r.IsDelegate) {
3867 						//
3868 						// Delegates
3869 						//
3870 						expr = ResolveOperatorDelegate (rc, l, r);
3871 
3872 						// TODO: Can this be ambiguous
3873 						if (expr != null)
3874 							return expr;
3875 					}
3876 				}
3877 			}
3878 
3879 			//
3880 			// Equality operators are more complicated
3881 			//
3882 			if ((oper & Operator.EqualityMask) != 0) {
3883 				return ResolveEquality (rc, l, r, primitives_only);
3884 			}
3885 
3886 			expr = ResolveOperatorPredefined (rc, rc.BuiltinTypes.OperatorsBinaryStandard, primitives_only);
3887 			if (expr != null)
3888 				return expr;
3889 
3890 			if (primitives_only)
3891 				return null;
3892 
3893 			//
3894 			// Lifted operators have lower priority
3895 			//
3896 			return ResolveOperatorPredefined (rc, rc.Module.OperatorsBinaryLifted, false);
3897 		}
3898 
IsEnumOrNullableEnum(TypeSpec type)3899 		static bool IsEnumOrNullableEnum (TypeSpec type)
3900 		{
3901 			return type.IsEnum || (type.IsNullableType && Nullable.NullableInfo.GetUnderlyingType (type).IsEnum);
3902 		}
3903 
3904 
3905 		// at least one of 'left' or 'right' is an enumeration constant (EnumConstant or SideEffectConstant or ...)
3906 		// if 'left' is not an enumeration constant, create one from the type of 'right'
EnumLiftUp(ResolveContext ec, Constant left, Constant right)3907 		Constant EnumLiftUp (ResolveContext ec, Constant left, Constant right)
3908 		{
3909 			switch (oper) {
3910 			case Operator.BitwiseOr:
3911 			case Operator.BitwiseAnd:
3912 			case Operator.ExclusiveOr:
3913 			case Operator.Equality:
3914 			case Operator.Inequality:
3915 			case Operator.LessThan:
3916 			case Operator.LessThanOrEqual:
3917 			case Operator.GreaterThan:
3918 			case Operator.GreaterThanOrEqual:
3919 				if (left.Type.IsEnum)
3920 					return left;
3921 
3922 				if (left.IsZeroInteger)
3923 					return left.Reduce (ec, right.Type);
3924 
3925 				break;
3926 
3927 			case Operator.Addition:
3928 			case Operator.Subtraction:
3929 				return left;
3930 
3931 			case Operator.Multiply:
3932 			case Operator.Division:
3933 			case Operator.Modulus:
3934 			case Operator.LeftShift:
3935 			case Operator.RightShift:
3936 				if (right.Type.IsEnum || left.Type.IsEnum)
3937 					break;
3938 				return left;
3939 			}
3940 
3941 			return null;
3942 		}
3943 
3944 		//
3945 		// The `|' operator used on types which were extended is dangerous
3946 		//
CheckBitwiseOrOnSignExtended(ResolveContext ec)3947 		void CheckBitwiseOrOnSignExtended (ResolveContext ec)
3948 		{
3949 			OpcodeCast lcast = left as OpcodeCast;
3950 			if (lcast != null) {
3951 				if (IsUnsigned (lcast.UnderlyingType))
3952 					lcast = null;
3953 			}
3954 
3955 			OpcodeCast rcast = right as OpcodeCast;
3956 			if (rcast != null) {
3957 				if (IsUnsigned (rcast.UnderlyingType))
3958 					rcast = null;
3959 			}
3960 
3961 			if (lcast == null && rcast == null)
3962 				return;
3963 
3964 			// FIXME: consider constants
3965 
3966 			var ltype = lcast != null ? lcast.UnderlyingType : rcast.UnderlyingType;
3967 			ec.Report.Warning (675, 3, loc,
3968 				"The operator `|' used on the sign-extended type `{0}'. Consider casting to a smaller unsigned type first",
3969 				ltype.GetSignatureForError ());
3970 		}
3971 
CreatePointerOperatorsTable(BuiltinTypes types)3972 		public static PredefinedOperator[] CreatePointerOperatorsTable (BuiltinTypes types)
3973 		{
3974 			return new PredefinedOperator[] {
3975 				//
3976 				// Pointer arithmetic:
3977 				//
3978 				// T* operator + (T* x, int y);		T* operator - (T* x, int y);
3979 				// T* operator + (T* x, uint y);	T* operator - (T* x, uint y);
3980 				// T* operator + (T* x, long y);	T* operator - (T* x, long y);
3981 				// T* operator + (T* x, ulong y);	T* operator - (T* x, ulong y);
3982 				//
3983 				new PredefinedPointerOperator (null, types.Int, Operator.AdditionMask | Operator.SubtractionMask),
3984 				new PredefinedPointerOperator (null, types.UInt, Operator.AdditionMask | Operator.SubtractionMask),
3985 				new PredefinedPointerOperator (null, types.Long, Operator.AdditionMask | Operator.SubtractionMask),
3986 				new PredefinedPointerOperator (null, types.ULong, Operator.AdditionMask | Operator.SubtractionMask),
3987 
3988 				//
3989 				// T* operator + (int y,   T* x);
3990 				// T* operator + (uint y,  T *x);
3991 				// T* operator + (long y,  T *x);
3992 				// T* operator + (ulong y, T *x);
3993 				//
3994 				new PredefinedPointerOperator (types.Int, null, Operator.AdditionMask, null),
3995 				new PredefinedPointerOperator (types.UInt, null, Operator.AdditionMask, null),
3996 				new PredefinedPointerOperator (types.Long, null, Operator.AdditionMask, null),
3997 				new PredefinedPointerOperator (types.ULong, null, Operator.AdditionMask, null),
3998 
3999 				//
4000 				// long operator - (T* x, T *y)
4001 				//
4002 				new PredefinedPointerOperator (null, Operator.SubtractionMask, types.Long)
4003 			};
4004 		}
4005 
CreateStandardOperatorsTable(BuiltinTypes types)4006 		public static PredefinedOperator[] CreateStandardOperatorsTable (BuiltinTypes types)
4007 		{
4008 			TypeSpec bool_type = types.Bool;
4009 
4010 			return new [] {
4011 				new PredefinedOperator (types.Int, Operator.ArithmeticMask | Operator.BitwiseMask | Operator.ShiftMask),
4012 				new PredefinedOperator (types.UInt, Operator.ArithmeticMask | Operator.BitwiseMask),
4013 				new PredefinedOperator (types.Long, Operator.ArithmeticMask | Operator.BitwiseMask),
4014 				new PredefinedOperator (types.ULong, Operator.ArithmeticMask | Operator.BitwiseMask),
4015 				new PredefinedOperator (types.Float, Operator.ArithmeticMask),
4016 				new PredefinedOperator (types.Double, Operator.ArithmeticMask),
4017 				new PredefinedOperator (types.Decimal, Operator.ArithmeticMask),
4018 
4019 				new PredefinedOperator (types.Int, Operator.ComparisonMask, bool_type),
4020 				new PredefinedOperator (types.UInt, Operator.ComparisonMask, bool_type),
4021 				new PredefinedOperator (types.Long, Operator.ComparisonMask, bool_type),
4022 				new PredefinedOperator (types.ULong, Operator.ComparisonMask, bool_type),
4023 				new PredefinedOperator (types.Float, Operator.ComparisonMask, bool_type),
4024 				new PredefinedOperator (types.Double, Operator.ComparisonMask, bool_type),
4025 				new PredefinedOperator (types.Decimal, Operator.ComparisonMask, bool_type),
4026 
4027 				new PredefinedStringOperator (types.String, Operator.AdditionMask, types.String),
4028 				// Remaining string operators are in lifted tables
4029 
4030 				new PredefinedOperator (bool_type, Operator.BitwiseMask | Operator.LogicalMask | Operator.EqualityMask, bool_type),
4031 
4032 				new PredefinedOperator (types.UInt, types.Int, Operator.ShiftMask),
4033 				new PredefinedOperator (types.Long, types.Int, Operator.ShiftMask),
4034 				new PredefinedOperator (types.ULong, types.Int, Operator.ShiftMask)
4035 			};
4036 
4037 		}
CreateStandardLiftedOperatorsTable(ModuleContainer module)4038 		public static PredefinedOperator[] CreateStandardLiftedOperatorsTable (ModuleContainer module)
4039 		{
4040 			var types = module.Compiler.BuiltinTypes;
4041 
4042 			//
4043 			// Not strictly lifted but need to be in second group otherwise expressions like
4044 			// int + null would resolve to +(object, string) instead of +(int?, int?)
4045 			//
4046 			var string_operators = new [] {
4047 				new PredefinedStringOperator (types.String, types.Object, Operator.AdditionMask, types.String),
4048 				new PredefinedStringOperator (types.Object, types.String, Operator.AdditionMask, types.String),
4049 			};
4050 
4051 			var nullable = module.PredefinedTypes.Nullable.TypeSpec;
4052 			if (nullable == null)
4053 				return string_operators;
4054 
4055 			var bool_type = types.Bool;
4056 
4057 			var nullable_bool = nullable.MakeGenericType (module, new[] { bool_type });
4058 			var nullable_int = nullable.MakeGenericType (module, new[] { types.Int });
4059 			var nullable_uint = nullable.MakeGenericType (module, new[] { types.UInt });
4060 			var nullable_long = nullable.MakeGenericType (module, new[] { types.Long });
4061 			var nullable_ulong = nullable.MakeGenericType (module, new[] { types.ULong });
4062 			var nullable_float = nullable.MakeGenericType (module, new[] { types.Float });
4063 			var nullable_double = nullable.MakeGenericType (module, new[] { types.Double });
4064 			var nullable_decimal = nullable.MakeGenericType (module, new[] { types.Decimal });
4065 
4066 			return new[] {
4067 				new PredefinedOperator (nullable_int, Operator.NullableMask | Operator.ArithmeticMask | Operator.BitwiseMask | Operator.ShiftMask),
4068 				new PredefinedOperator (nullable_uint, Operator.NullableMask | Operator.ArithmeticMask | Operator.BitwiseMask),
4069 				new PredefinedOperator (nullable_long, Operator.NullableMask | Operator.ArithmeticMask | Operator.BitwiseMask),
4070 				new PredefinedOperator (nullable_ulong, Operator.NullableMask | Operator.ArithmeticMask | Operator.BitwiseMask),
4071 				new PredefinedOperator (nullable_float, Operator.NullableMask | Operator.ArithmeticMask),
4072 				new PredefinedOperator (nullable_double, Operator.NullableMask | Operator.ArithmeticMask),
4073 				new PredefinedOperator (nullable_decimal, Operator.NullableMask | Operator.ArithmeticMask),
4074 
4075 				new PredefinedOperator (nullable_int, Operator.NullableMask | Operator.ComparisonMask, bool_type),
4076 				new PredefinedOperator (nullable_uint, Operator.NullableMask | Operator.ComparisonMask, bool_type),
4077 				new PredefinedOperator (nullable_long, Operator.NullableMask | Operator.ComparisonMask, bool_type),
4078 				new PredefinedOperator (nullable_ulong, Operator.NullableMask | Operator.ComparisonMask, bool_type),
4079 				new PredefinedOperator (nullable_float, Operator.NullableMask | Operator.ComparisonMask, bool_type),
4080 				new PredefinedOperator (nullable_double, Operator.NullableMask | Operator.ComparisonMask, bool_type),
4081 				new PredefinedOperator (nullable_decimal, Operator.NullableMask | Operator.ComparisonMask, bool_type),
4082 
4083 				new PredefinedOperator (nullable_bool, Operator.NullableMask | Operator.BitwiseMask, nullable_bool),
4084 
4085 				new PredefinedOperator (nullable_uint, nullable_int, Operator.NullableMask | Operator.ShiftMask),
4086 				new PredefinedOperator (nullable_long, nullable_int, Operator.NullableMask | Operator.ShiftMask),
4087 				new PredefinedOperator (nullable_ulong, nullable_int, Operator.NullableMask | Operator.ShiftMask),
4088 
4089 				string_operators [0],
4090 				string_operators [1]
4091 			};
4092 		}
4093 
CreateEqualityOperatorsTable(BuiltinTypes types)4094 		public static PredefinedOperator[] CreateEqualityOperatorsTable (BuiltinTypes types)
4095 		{
4096 			TypeSpec bool_type = types.Bool;
4097 
4098 			return new[] {
4099 				new PredefinedEqualityOperator (types.String, bool_type),
4100 				new PredefinedEqualityOperator (types.Delegate, bool_type),
4101 				new PredefinedOperator (bool_type, Operator.EqualityMask, bool_type),
4102 				new PredefinedOperator (types.Int, Operator.EqualityMask, bool_type),
4103 				new PredefinedOperator (types.UInt, Operator.EqualityMask, bool_type),
4104 				new PredefinedOperator (types.Long, Operator.EqualityMask, bool_type),
4105 				new PredefinedOperator (types.ULong, Operator.EqualityMask, bool_type),
4106 				new PredefinedOperator (types.Float, Operator.EqualityMask, bool_type),
4107 				new PredefinedOperator (types.Double, Operator.EqualityMask, bool_type),
4108 				new PredefinedOperator (types.Decimal, Operator.EqualityMask, bool_type),
4109 			};
4110 		}
4111 
CreateEqualityLiftedOperatorsTable(ModuleContainer module)4112 		public static PredefinedOperator[] CreateEqualityLiftedOperatorsTable (ModuleContainer module)
4113 		{
4114 			var nullable = module.PredefinedTypes.Nullable.TypeSpec;
4115 
4116 			if (nullable == null)
4117 				return new PredefinedOperator [0];
4118 
4119 			var types = module.Compiler.BuiltinTypes;
4120 			var bool_type = types.Bool;
4121 			var nullable_bool = nullable.MakeGenericType (module, new [] { bool_type });
4122 			var nullable_int = nullable.MakeGenericType (module, new[] { types.Int });
4123 			var nullable_uint = nullable.MakeGenericType (module, new[] { types.UInt });
4124 			var nullable_long = nullable.MakeGenericType (module, new[] { types.Long });
4125 			var nullable_ulong = nullable.MakeGenericType (module, new[] { types.ULong });
4126 			var nullable_float = nullable.MakeGenericType (module, new[] { types.Float });
4127 			var nullable_double = nullable.MakeGenericType (module, new[] { types.Double });
4128 			var nullable_decimal = nullable.MakeGenericType (module, new[] { types.Decimal });
4129 
4130 			return new [] {
4131 				new PredefinedOperator (nullable_bool, Operator.NullableMask | Operator.EqualityMask, bool_type),
4132 				new PredefinedOperator (nullable_int, Operator.NullableMask | Operator.EqualityMask, bool_type),
4133 				new PredefinedOperator (nullable_uint, Operator.NullableMask | Operator.EqualityMask, bool_type),
4134 				new PredefinedOperator (nullable_long, Operator.NullableMask | Operator.EqualityMask, bool_type),
4135 				new PredefinedOperator (nullable_ulong, Operator.NullableMask | Operator.EqualityMask, bool_type),
4136 				new PredefinedOperator (nullable_float, Operator.NullableMask | Operator.EqualityMask, bool_type),
4137 				new PredefinedOperator (nullable_double, Operator.NullableMask | Operator.EqualityMask, bool_type),
4138 				new PredefinedOperator (nullable_decimal, Operator.NullableMask | Operator.EqualityMask, bool_type)
4139 			};
4140 		}
4141 
4142 		//
4143 		// 7.2.6.2 Binary numeric promotions
4144 		//
DoBinaryOperatorPromotion(ResolveContext rc)4145 		bool DoBinaryOperatorPromotion (ResolveContext rc)
4146 		{
4147 			TypeSpec ltype = left.Type;
4148 			if (ltype.IsNullableType) {
4149 				ltype = Nullable.NullableInfo.GetUnderlyingType (ltype);
4150 			}
4151 
4152 			//
4153 			// This is numeric promotion code only
4154 			//
4155 			if (ltype.BuiltinType == BuiltinTypeSpec.Type.Bool)
4156 				return true;
4157 
4158 			TypeSpec rtype = right.Type;
4159 			if (rtype.IsNullableType) {
4160 				rtype = Nullable.NullableInfo.GetUnderlyingType (rtype);
4161 			}
4162 
4163 			var lb = ltype.BuiltinType;
4164 			var rb = rtype.BuiltinType;
4165 			TypeSpec type;
4166 			Expression expr;
4167 
4168 			if (lb == BuiltinTypeSpec.Type.Decimal || rb == BuiltinTypeSpec.Type.Decimal) {
4169 				type = rc.BuiltinTypes.Decimal;
4170 			} else if (lb == BuiltinTypeSpec.Type.Double || rb == BuiltinTypeSpec.Type.Double) {
4171 				type = rc.BuiltinTypes.Double;
4172 			} else if (lb == BuiltinTypeSpec.Type.Float || rb == BuiltinTypeSpec.Type.Float) {
4173 				type = rc.BuiltinTypes.Float;
4174 			} else if (lb == BuiltinTypeSpec.Type.ULong || rb == BuiltinTypeSpec.Type.ULong) {
4175 				type = rc.BuiltinTypes.ULong;
4176 
4177 				if (IsSignedType (lb)) {
4178 					expr = ConvertSignedConstant (left, type);
4179 					if (expr == null)
4180 						return false;
4181 					left = expr;
4182 				} else if (IsSignedType (rb)) {
4183 					expr = ConvertSignedConstant (right, type);
4184 					if (expr == null)
4185 						return false;
4186 					right = expr;
4187 				}
4188 
4189 			} else if (lb == BuiltinTypeSpec.Type.Long || rb == BuiltinTypeSpec.Type.Long) {
4190 				type = rc.BuiltinTypes.Long;
4191 			} else if (lb == BuiltinTypeSpec.Type.UInt || rb == BuiltinTypeSpec.Type.UInt) {
4192 				type = rc.BuiltinTypes.UInt;
4193 
4194 				if (IsSignedType (lb)) {
4195 					expr = ConvertSignedConstant (left, type);
4196 					if (expr == null)
4197 						type = rc.BuiltinTypes.Long;
4198 				} else if (IsSignedType (rb)) {
4199 					expr = ConvertSignedConstant (right, type);
4200 					if (expr == null)
4201 						type = rc.BuiltinTypes.Long;
4202 				}
4203 			} else {
4204 				type = rc.BuiltinTypes.Int;
4205 			}
4206 
4207 			if (ltype != type) {
4208 				expr = PromoteExpression (rc, left, type);
4209 				if (expr == null)
4210 					return false;
4211 
4212 				left = expr;
4213 			}
4214 
4215 			if (rtype != type) {
4216 				expr = PromoteExpression (rc, right, type);
4217 				if (expr == null)
4218 					return false;
4219 
4220 				right = expr;
4221 			}
4222 
4223 			return true;
4224 		}
4225 
IsSignedType(BuiltinTypeSpec.Type type)4226 		static bool IsSignedType (BuiltinTypeSpec.Type type)
4227 		{
4228 			switch (type) {
4229 			case BuiltinTypeSpec.Type.Int:
4230 			case BuiltinTypeSpec.Type.Short:
4231 			case BuiltinTypeSpec.Type.SByte:
4232 			case BuiltinTypeSpec.Type.Long:
4233 				return true;
4234 			default:
4235 				return false;
4236 			}
4237 		}
4238 
ConvertSignedConstant(Expression expr, TypeSpec type)4239 		static Expression ConvertSignedConstant (Expression expr, TypeSpec type)
4240 		{
4241 			var c = expr as Constant;
4242 			if (c == null)
4243 				return null;
4244 
4245 			return c.ConvertImplicitly (type);
4246 		}
4247 
PromoteExpression(ResolveContext rc, Expression expr, TypeSpec type)4248 		static Expression PromoteExpression (ResolveContext rc, Expression expr, TypeSpec type)
4249 		{
4250 			if (expr.Type.IsNullableType) {
4251 				return Convert.ImplicitConversionStandard (rc, expr,
4252 					rc.Module.PredefinedTypes.Nullable.TypeSpec.MakeGenericType (rc, new[] { type }), expr.Location);
4253 			}
4254 
4255 			var c = expr as Constant;
4256 			if (c != null)
4257 				return c.ConvertImplicitly (type);
4258 
4259 			return Convert.ImplicitNumericConversion (expr, type);
4260 		}
4261 
DoResolve(ResolveContext ec)4262 		protected override Expression DoResolve (ResolveContext ec)
4263 		{
4264 			if (left == null)
4265 				return null;
4266 
4267 			if ((oper == Operator.Subtraction) && (left is ParenthesizedExpression)) {
4268 				left = ((ParenthesizedExpression) left).Expr;
4269 				left = left.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type);
4270 				if (left == null)
4271 					return null;
4272 
4273 				if (left.eclass == ExprClass.Type) {
4274 					ec.Report.Error (75, loc, "To cast a negative value, you must enclose the value in parentheses");
4275 					return null;
4276 				}
4277 			} else
4278 				left = left.Resolve (ec);
4279 
4280 			if (left == null)
4281 				return null;
4282 
4283 			right = right.Resolve (ec);
4284 			if (right == null)
4285 				return null;
4286 
4287 			Constant lc = left as Constant;
4288 			Constant rc = right as Constant;
4289 
4290 			// The conversion rules are ignored in enum context but why
4291 			if (!ec.HasSet (ResolveContext.Options.EnumScope) && lc != null && rc != null && (left.Type.IsEnum || right.Type.IsEnum)) {
4292 				lc = EnumLiftUp (ec, lc, rc);
4293 				if (lc != null)
4294 					rc = EnumLiftUp (ec, rc, lc);
4295 			}
4296 
4297 			if (rc != null && lc != null) {
4298 				int prev_e = ec.Report.Errors;
4299 				Expression e = ConstantFold.BinaryFold (ec, oper, lc, rc, loc);
4300 				if (e != null || ec.Report.Errors != prev_e)
4301 					return e;
4302 			}
4303 
4304 			// Comparison warnings
4305 			if ((oper & Operator.ComparisonMask) != 0) {
4306 				if (left.Equals (right)) {
4307 					ec.Report.Warning (1718, 3, loc, "A comparison made to same variable. Did you mean to compare something else?");
4308 				}
4309 				CheckOutOfRangeComparison (ec, lc, right.Type);
4310 				CheckOutOfRangeComparison (ec, rc, left.Type);
4311 			}
4312 
4313 			var ltype = left.Type;
4314 			var rtype = right.Type;
4315 			if (ltype.BuiltinType == BuiltinTypeSpec.Type.Dynamic || rtype.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
4316 				return DoResolveDynamic (ec);
4317 
4318 			//
4319 			// Only default with == and != is explicitly allowed
4320 			//
4321 			if (ltype == InternalType.DefaultType || rtype == InternalType.DefaultType) {
4322 				if ((Oper & Operator.EqualityMask) == 0) {
4323 					ec.Report.Error (8310, loc, "Operator `{0}' cannot be applied to operand `default'", OperName (Oper));
4324 					return null;
4325 				}
4326 
4327 				if (ltype == rtype) {
4328 					ec.Report.Error (8315, loc, "Operator `{0}' is ambiguous on operands `default' and `default'", OperName (Oper));
4329 					return null;
4330 				}
4331 
4332 				if (rtype == InternalType.DefaultType) {
4333 					right = new DefaultValueExpression (new TypeExpression (ltype, right.Location), right.Location).Resolve (ec);
4334 				} else {
4335 					left = new DefaultValueExpression (new TypeExpression (rtype, left.Location), left.Location).Resolve (ec);
4336 				}
4337 			}
4338 
4339 			return DoResolveCore (ec, left, right);
4340 		}
4341 
DoResolveDynamic(ResolveContext rc)4342 		Expression DoResolveDynamic (ResolveContext rc)
4343 		{
4344 			var lt = left.Type;
4345 			var rt = right.Type;
4346 			if (lt.Kind == MemberKind.Void || lt == InternalType.MethodGroup || lt == InternalType.AnonymousMethod ||
4347 				rt.Kind == MemberKind.Void || rt == InternalType.MethodGroup || rt == InternalType.AnonymousMethod) {
4348 				Error_OperatorCannotBeApplied (rc, left, right);
4349 				return null;
4350 			}
4351 
4352 			Arguments args;
4353 
4354 			//
4355 			// Special handling for logical boolean operators which require rhs not to be
4356 			// evaluated based on lhs value
4357 			//
4358 			if ((oper & Operator.LogicalMask) != 0) {
4359 				Expression cond_left, cond_right, expr;
4360 
4361 				args = new Arguments (2);
4362 
4363 				if (lt.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
4364 					LocalVariable temp = LocalVariable.CreateCompilerGenerated (lt, rc.CurrentBlock, loc);
4365 
4366 					var cond_args = new Arguments (1);
4367 					cond_args.Add (new Argument (new SimpleAssign (temp.CreateReferenceExpression (rc, loc), left).Resolve (rc)));
4368 
4369 					//
4370 					// dynamic && bool => IsFalse (temp = left) ? temp : temp && right;
4371 					// dynamic || bool => IsTrue (temp = left) ? temp : temp || right;
4372 					//
4373 					left = temp.CreateReferenceExpression (rc, loc);
4374 					if (oper == Operator.LogicalAnd) {
4375 						expr = DynamicUnaryConversion.CreateIsFalse (rc, cond_args, loc);
4376 						cond_left = left;
4377 					} else {
4378 						expr = DynamicUnaryConversion.CreateIsTrue (rc, cond_args, loc);
4379 						cond_left = left;
4380 					}
4381 
4382 					args.Add (new Argument (left));
4383 					args.Add (new Argument (right));
4384 					cond_right = new DynamicExpressionStatement (this, args, loc);
4385 				} else {
4386 					LocalVariable temp = LocalVariable.CreateCompilerGenerated (rc.BuiltinTypes.Bool, rc.CurrentBlock, loc);
4387 
4388 					if (!Convert.ImplicitConversionExists (rc, left, temp.Type) && (oper == Operator.LogicalAnd ? GetOperatorFalse (rc, left, loc) : GetOperatorTrue (rc, left, loc)) == null) {
4389 						rc.Report.Error (7083, left.Location,
4390 							"Expression must be implicitly convertible to Boolean or its type `{0}' must define operator `{1}'",
4391 							lt.GetSignatureForError (), oper == Operator.LogicalAnd ? "false" : "true");
4392 						return null;
4393 					}
4394 
4395 					args.Add (new Argument (temp.CreateReferenceExpression (rc, loc).Resolve (rc)));
4396 					args.Add (new Argument (right));
4397 					right = new DynamicExpressionStatement (this, args, loc);
4398 
4399 					//
4400 					// bool && dynamic => (temp = left) ? temp && right : temp;
4401 					// bool || dynamic => (temp = left) ? temp : temp || right;
4402 					//
4403 					if (oper == Operator.LogicalAnd) {
4404 						cond_left = right;
4405 						cond_right = temp.CreateReferenceExpression (rc, loc);
4406 					} else {
4407 						cond_left = temp.CreateReferenceExpression (rc, loc);
4408 						cond_right = right;
4409 					}
4410 
4411 					expr = new BooleanExpression (new SimpleAssign (temp.CreateReferenceExpression (rc, loc), left));
4412 				}
4413 
4414 				return new Conditional (expr, cond_left, cond_right, loc).Resolve (rc);
4415 			}
4416 
4417 			args = new Arguments (2);
4418 			args.Add (new Argument (left));
4419 			args.Add (new Argument (right));
4420 			return new DynamicExpressionStatement (this, args, loc).Resolve (rc);
4421 		}
4422 
DoResolveCore(ResolveContext ec, Expression left_orig, Expression right_orig)4423 		Expression DoResolveCore (ResolveContext ec, Expression left_orig, Expression right_orig)
4424 		{
4425 			Expression expr = ResolveOperator (ec);
4426 			if (expr == null)
4427 				Error_OperatorCannotBeApplied (ec, left_orig, right_orig);
4428 
4429 			if (left == null || right == null)
4430 				throw new InternalErrorException ("Invalid conversion");
4431 
4432 			if (oper == Operator.BitwiseOr)
4433 				CheckBitwiseOrOnSignExtended (ec);
4434 
4435 			return expr;
4436 		}
4437 
MakeExpression(BuilderContext ctx)4438 		public override SLE.Expression MakeExpression (BuilderContext ctx)
4439 		{
4440 			return MakeExpression (ctx, left, right);
4441 		}
4442 
MakeExpression(BuilderContext ctx, Expression left, Expression right)4443 		public SLE.Expression MakeExpression (BuilderContext ctx, Expression left, Expression right)
4444 		{
4445 			var le = left.MakeExpression (ctx);
4446 			var re = right.MakeExpression (ctx);
4447 			bool is_checked = ctx.HasSet (BuilderContext.Options.CheckedScope);
4448 
4449 			switch (oper) {
4450 			case Operator.Addition:
4451 				return is_checked ? SLE.Expression.AddChecked (le, re) : SLE.Expression.Add (le, re);
4452 			case Operator.BitwiseAnd:
4453 				return SLE.Expression.And (le, re);
4454 			case Operator.BitwiseOr:
4455 				return SLE.Expression.Or (le, re);
4456 			case Operator.Division:
4457 				return SLE.Expression.Divide (le, re);
4458 			case Operator.Equality:
4459 				return SLE.Expression.Equal (le, re);
4460 			case Operator.ExclusiveOr:
4461 				return SLE.Expression.ExclusiveOr (le, re);
4462 			case Operator.GreaterThan:
4463 				return SLE.Expression.GreaterThan (le, re);
4464 			case Operator.GreaterThanOrEqual:
4465 				return SLE.Expression.GreaterThanOrEqual (le, re);
4466 			case Operator.Inequality:
4467 				return SLE.Expression.NotEqual (le, re);
4468 			case Operator.LeftShift:
4469 				return SLE.Expression.LeftShift (le, re);
4470 			case Operator.LessThan:
4471 				return SLE.Expression.LessThan (le, re);
4472 			case Operator.LessThanOrEqual:
4473 				return SLE.Expression.LessThanOrEqual (le, re);
4474 			case Operator.LogicalAnd:
4475 				return SLE.Expression.AndAlso (le, re);
4476 			case Operator.LogicalOr:
4477 				return SLE.Expression.OrElse (le, re);
4478 			case Operator.Modulus:
4479 				return SLE.Expression.Modulo (le, re);
4480 			case Operator.Multiply:
4481 				return is_checked ? SLE.Expression.MultiplyChecked (le, re) : SLE.Expression.Multiply (le, re);
4482 			case Operator.RightShift:
4483 				return SLE.Expression.RightShift (le, re);
4484 			case Operator.Subtraction:
4485 				return is_checked ? SLE.Expression.SubtractChecked (le, re) : SLE.Expression.Subtract (le, re);
4486 			default:
4487 				throw new NotImplementedException (oper.ToString ());
4488 			}
4489 		}
4490 
4491 		//
4492 		// D operator + (D x, D y)
4493 		// D operator - (D x, D y)
4494 		//
ResolveOperatorDelegate(ResolveContext ec, TypeSpec l, TypeSpec r)4495 		Expression ResolveOperatorDelegate (ResolveContext ec, TypeSpec l, TypeSpec r)
4496 		{
4497 			if (l != r && !TypeSpecComparer.Variant.IsEqual (r, l)) {
4498 				Expression tmp;
4499 				if (right.eclass == ExprClass.MethodGroup || r == InternalType.AnonymousMethod || r == InternalType.NullLiteral) {
4500 					tmp = Convert.ImplicitConversionRequired (ec, right, l, loc);
4501 					if (tmp == null)
4502 						return null;
4503 					right = tmp;
4504 					r = right.Type;
4505 				} else if (left.eclass == ExprClass.MethodGroup || (l == InternalType.AnonymousMethod || l == InternalType.NullLiteral)) {
4506 					tmp = Convert.ImplicitConversionRequired (ec, left, r, loc);
4507 					if (tmp == null)
4508 						return null;
4509 					left = tmp;
4510 					l = left.Type;
4511 				} else {
4512 					return null;
4513 				}
4514 			}
4515 
4516 			MethodSpec method = null;
4517 			Arguments args = new Arguments (2);
4518 			args.Add (new Argument (left));
4519 			args.Add (new Argument (right));
4520 
4521 			if (oper == Operator.Addition) {
4522 				method = ec.Module.PredefinedMembers.DelegateCombine.Resolve (loc);
4523 			} else if (oper == Operator.Subtraction) {
4524 				method = ec.Module.PredefinedMembers.DelegateRemove.Resolve (loc);
4525 			}
4526 
4527 			if (method == null)
4528 				return new EmptyExpression (ec.BuiltinTypes.Decimal);
4529 
4530 			Expression expr = new UserOperatorCall (method, args, CreateExpressionTree, loc);
4531 			return new ClassCast (expr, l);
4532 		}
4533 
4534 		//
4535 		// Resolves enumeration operators where only single predefined overload exists, handles lifted versions too
4536 		//
ResolveSingleEnumOperators(ResolveContext rc, bool lenum, bool renum, TypeSpec ltype, TypeSpec rtype)4537 		Expression ResolveSingleEnumOperators (ResolveContext rc, bool lenum, bool renum, TypeSpec ltype, TypeSpec rtype)
4538 		{
4539 			//
4540 			// bool operator == (E x, E y);
4541 			// bool operator != (E x, E y);
4542 			// bool operator < (E x, E y);
4543 			// bool operator > (E x, E y);
4544 			// bool operator <= (E x, E y);
4545 			// bool operator >= (E x, E y);
4546 			//
4547 			// E operator & (E x, E y);
4548 			// E operator | (E x, E y);
4549 			// E operator ^ (E x, E y);
4550 			//
4551 			Expression expr;
4552 			if ((oper & Operator.ComparisonMask) != 0) {
4553 				type = rc.BuiltinTypes.Bool;
4554 			} else {
4555 				if (lenum)
4556 					type = ltype;
4557 				else if (renum)
4558 					type = rtype;
4559 				else if (ltype.IsNullableType && Nullable.NullableInfo.GetUnderlyingType (ltype).IsEnum)
4560 					type = ltype;
4561 				else
4562 					type = rtype;
4563 			}
4564 
4565 			if (ltype == rtype) {
4566 				if (lenum || renum)
4567 					return this;
4568 
4569 				var lifted = new Nullable.LiftedBinaryOperator (this);
4570 				lifted.Left = left;
4571 				lifted.Right = right;
4572 				return lifted.Resolve (rc);
4573 			}
4574 
4575 			if (renum && !ltype.IsNullableType) {
4576 				expr = Convert.ImplicitConversion (rc, left, rtype, loc);
4577 				if (expr != null) {
4578 					left = expr;
4579 					return this;
4580 				}
4581 			} else if (lenum && !rtype.IsNullableType) {
4582 				expr = Convert.ImplicitConversion (rc, right, ltype, loc);
4583 				if (expr != null) {
4584 					right = expr;
4585 					return this;
4586 				}
4587 			}
4588 
4589 			//
4590 			// Now try lifted version of predefined operator
4591 			//
4592 			var nullable_type = rc.Module.PredefinedTypes.Nullable.TypeSpec;
4593 			if (nullable_type != null) {
4594 				if (renum && !ltype.IsNullableType) {
4595 					var lifted_type = nullable_type.MakeGenericType (rc.Module, new[] { rtype });
4596 
4597 					expr = Convert.ImplicitConversion (rc, left, lifted_type, loc);
4598 					if (expr != null) {
4599 						left = expr;
4600 						right = Convert.ImplicitConversion (rc, right, lifted_type, loc);
4601 					}
4602 
4603 					if ((oper & Operator.BitwiseMask) != 0)
4604 						type = lifted_type;
4605 
4606 					if (left.IsNull) {
4607 						if ((oper & Operator.BitwiseMask) != 0)
4608 							return Nullable.LiftedNull.CreateFromExpression (rc, this);
4609 
4610 						return CreateLiftedValueTypeResult (rc, rtype);
4611 					}
4612 
4613 					if (expr != null) {
4614 						var lifted = new Nullable.LiftedBinaryOperator (this);
4615 						lifted.Left = expr;
4616 						lifted.Right = right;
4617 						return lifted.Resolve (rc);
4618 					}
4619 				} else if (lenum && !rtype.IsNullableType) {
4620 					var lifted_type = nullable_type.MakeGenericType (rc.Module, new[] { ltype });
4621 
4622 					expr = Convert.ImplicitConversion (rc, right, lifted_type, loc);
4623 					if (expr != null) {
4624 						right = expr;
4625 						left = Convert.ImplicitConversion (rc, left, lifted_type, loc);
4626 					}
4627 
4628 					if ((oper & Operator.BitwiseMask) != 0)
4629 						type = lifted_type;
4630 
4631 					if (right.IsNull) {
4632 						if ((oper & Operator.BitwiseMask) != 0)
4633 							return Nullable.LiftedNull.CreateFromExpression (rc, this);
4634 
4635 						return CreateLiftedValueTypeResult (rc, ltype);
4636 					}
4637 
4638 					if (expr != null) {
4639 						var lifted = new Nullable.LiftedBinaryOperator (this);
4640 						lifted.Left = left;
4641 						lifted.Right = expr;
4642 						return lifted.Resolve (rc);
4643 					}
4644 				} else if (rtype.IsNullableType && Nullable.NullableInfo.GetUnderlyingType (rtype).IsEnum) {
4645 					Nullable.Unwrap unwrap = null;
4646 					if (left.IsNull || right.IsNull) {
4647 						if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion))
4648 							left = Convert.ImplicitConversion (rc, left, rtype, left.Location);
4649 
4650 						if ((oper & Operator.RelationalMask) != 0)
4651 							return CreateLiftedValueTypeResult (rc, rtype);
4652 
4653 						if ((oper & Operator.BitwiseMask) != 0)
4654 							return Nullable.LiftedNull.CreateFromExpression (rc, this);
4655 
4656 						if (right.IsNull)
4657 							return CreateLiftedValueTypeResult (rc, left.Type);
4658 
4659 						// Equality operators are valid between E? and null
4660 						expr = left;
4661 						unwrap = new Nullable.Unwrap (right);
4662 					} else {
4663 						expr = Convert.ImplicitConversion (rc, left, Nullable.NullableInfo.GetUnderlyingType (rtype), loc);
4664 						if (expr == null)
4665 							return null;
4666 
4667 						if ((oper & Operator.BitwiseMask) != 0)
4668 							type = rtype;
4669 					}
4670 
4671 					if (expr != null) {
4672 						var lifted = new Nullable.LiftedBinaryOperator (this);
4673 						lifted.Left = expr;
4674 						lifted.Right = right;
4675 						lifted.UnwrapRight = unwrap;
4676 						return lifted.Resolve (rc);
4677 					}
4678 				} else if (ltype.IsNullableType && Nullable.NullableInfo.GetUnderlyingType (ltype).IsEnum) {
4679 					Nullable.Unwrap unwrap = null;
4680 					if (right.IsNull || left.IsNull) {
4681 						if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion))
4682 							right = Convert.ImplicitConversion (rc, right, ltype, right.Location);
4683 
4684 						if ((oper & Operator.RelationalMask) != 0)
4685 							return CreateLiftedValueTypeResult (rc, ltype);
4686 
4687 						if ((oper & Operator.BitwiseMask) != 0)
4688 							return Nullable.LiftedNull.CreateFromExpression (rc, this);
4689 
4690 						if (left.IsNull)
4691 							return CreateLiftedValueTypeResult (rc, right.Type);
4692 
4693 						// Equality operators are valid between E? and null
4694 						expr = right;
4695 						unwrap = new Nullable.Unwrap (left);
4696 					} else {
4697 						expr = Convert.ImplicitConversion (rc, right, Nullable.NullableInfo.GetUnderlyingType (ltype), loc);
4698 						if (expr == null)
4699 							return null;
4700 
4701 						if ((oper & Operator.BitwiseMask) != 0)
4702 							type = ltype;
4703 					}
4704 
4705 					if (expr != null) {
4706 						var lifted = new Nullable.LiftedBinaryOperator (this);
4707 						lifted.Left = left;
4708 						lifted.UnwrapLeft = unwrap;
4709 						lifted.Right = expr;
4710 						return lifted.Resolve (rc);
4711 					}
4712 				}
4713 			}
4714 
4715 			return null;
4716 		}
4717 
ConvertEnumOperandToUnderlyingType(ResolveContext rc, Expression expr, bool liftType)4718 		static Expression ConvertEnumOperandToUnderlyingType (ResolveContext rc, Expression expr, bool liftType)
4719 		{
4720 			TypeSpec underlying_type;
4721 			if (expr.Type.IsNullableType) {
4722 				var nt = Nullable.NullableInfo.GetUnderlyingType (expr.Type);
4723 				if (nt.IsEnum)
4724 					underlying_type = EnumSpec.GetUnderlyingType (nt);
4725 				else
4726 					underlying_type = nt;
4727 			} else if (expr.Type.IsEnum) {
4728 				underlying_type = EnumSpec.GetUnderlyingType (expr.Type);
4729 			} else {
4730 				underlying_type = expr.Type;
4731 			}
4732 
4733 			switch (underlying_type.BuiltinType) {
4734 			case BuiltinTypeSpec.Type.SByte:
4735 			case BuiltinTypeSpec.Type.Byte:
4736 			case BuiltinTypeSpec.Type.Short:
4737 			case BuiltinTypeSpec.Type.UShort:
4738 				underlying_type = rc.BuiltinTypes.Int;
4739 				break;
4740 			}
4741 
4742 			if (expr.Type.IsNullableType || liftType)
4743 				underlying_type = rc.Module.PredefinedTypes.Nullable.TypeSpec.MakeGenericType (rc.Module, new[] { underlying_type });
4744 
4745 			if (expr.Type == underlying_type)
4746 				return expr;
4747 
4748 			return EmptyCast.Create (expr, underlying_type);
4749 		}
4750 
ResolveEnumOperators(ResolveContext rc, bool lenum, bool renum, TypeSpec ltype, TypeSpec rtype)4751 		Expression ResolveEnumOperators (ResolveContext rc, bool lenum, bool renum, TypeSpec ltype, TypeSpec rtype)
4752 		{
4753 			//
4754 			// U operator - (E e, E f)
4755 			// E operator - (E e, U x)  // Internal decomposition operator
4756 			// E operator - (U x, E e)	// Internal decomposition operator
4757 			//
4758 			// E operator + (E e, U x)
4759 			// E operator + (U x, E e)
4760 			//
4761 
4762 			TypeSpec enum_type;
4763 
4764 			if (lenum)
4765 				enum_type = ltype;
4766 			else if (renum)
4767 				enum_type = rtype;
4768 			else if (ltype.IsNullableType && Nullable.NullableInfo.GetUnderlyingType (ltype).IsEnum)
4769 				enum_type = ltype;
4770 			else
4771 				enum_type = rtype;
4772 
4773 			Expression expr;
4774 			if (!enum_type.IsNullableType) {
4775 				expr = ResolveOperatorPredefined (rc, rc.Module.GetPredefinedEnumAritmeticOperators (enum_type, false), false);
4776 				if (expr != null) {
4777 					if (oper == Operator.Subtraction)
4778 						expr = ConvertEnumSubtractionResult (rc, expr);
4779 					else
4780 						expr = ConvertEnumAdditionalResult (expr, enum_type);
4781 
4782 					enum_conversion = GetEnumResultCast (expr.Type);
4783 
4784 					return expr;
4785 				}
4786 
4787 				var nullable = rc.Module.PredefinedTypes.Nullable;
4788 
4789 				//
4790 				// Don't try nullable version when nullable type is undefined
4791 				//
4792 				if (!nullable.IsDefined)
4793 					return null;
4794 
4795 				enum_type = nullable.TypeSpec.MakeGenericType (rc.Module, new[] { enum_type });
4796 			}
4797 
4798 			expr = ResolveOperatorPredefined (rc, rc.Module.GetPredefinedEnumAritmeticOperators (enum_type, true), false);
4799 			if (expr != null) {
4800 				if (oper == Operator.Subtraction)
4801 					expr = ConvertEnumSubtractionResult (rc, expr);
4802 				else
4803 					expr = ConvertEnumAdditionalResult (expr, enum_type);
4804 
4805 				enum_conversion = GetEnumResultCast (expr.Type);
4806 			}
4807 
4808 			return expr;
4809 		}
4810 
ConvertEnumAdditionalResult(Expression expr, TypeSpec enumType)4811 		static Expression ConvertEnumAdditionalResult (Expression expr, TypeSpec enumType)
4812 		{
4813 			return EmptyCast.Create (expr, enumType);
4814 		}
4815 
ConvertEnumSubtractionResult(ResolveContext rc, Expression expr)4816 		Expression ConvertEnumSubtractionResult (ResolveContext rc, Expression expr)
4817 		{
4818 			//
4819 			// Enumeration subtraction has different result type based on
4820 			// best overload
4821 			//
4822 			TypeSpec result_type;
4823 			if (left.Type == right.Type) {
4824 				var c = right as EnumConstant;
4825 				if (c != null && c.IsZeroInteger && !right.Type.IsEnum) {
4826 					//
4827 					// LAMESPEC: This is quite unexpected for expression E - 0 the return type is
4828 					// E which is not what expressions E - 1 or 0 - E return
4829 					//
4830 					result_type = left.Type;
4831 				} else {
4832 					result_type = left.Type.IsNullableType ?
4833 						Nullable.NullableInfo.GetEnumUnderlyingType (rc.Module, left.Type) :
4834 						EnumSpec.GetUnderlyingType (left.Type);
4835 				}
4836 			} else {
4837 				if (IsEnumOrNullableEnum (left.Type)) {
4838 					result_type = left.Type;
4839 				} else {
4840 					result_type = right.Type;
4841 				}
4842 
4843 				if (expr is Nullable.LiftedBinaryOperator && !result_type.IsNullableType)
4844 					result_type = rc.Module.PredefinedTypes.Nullable.TypeSpec.MakeGenericType (rc.Module, new[] { result_type });
4845 			}
4846 
4847 			return EmptyCast.Create (expr, result_type);
4848 		}
4849 
GetEnumResultCast(TypeSpec type)4850 		public static ConvCast.Mode GetEnumResultCast (TypeSpec type)
4851 		{
4852 			if (type.IsNullableType)
4853 				type = Nullable.NullableInfo.GetUnderlyingType (type);
4854 
4855 			if (type.IsEnum)
4856 				type = EnumSpec.GetUnderlyingType (type);
4857 
4858 			switch (type.BuiltinType) {
4859 			case BuiltinTypeSpec.Type.SByte:
4860 				return ConvCast.Mode.I4_I1;
4861 			case BuiltinTypeSpec.Type.Byte:
4862 				return ConvCast.Mode.I4_U1;
4863 			case BuiltinTypeSpec.Type.Short:
4864 				return ConvCast.Mode.I4_I2;
4865 			case BuiltinTypeSpec.Type.UShort:
4866 				return ConvCast.Mode.I4_U2;
4867 			}
4868 
4869 			return 0;
4870 		}
4871 
4872 		//
4873 		// Equality operators rules
4874 		//
ResolveEquality(ResolveContext ec, TypeSpec l, TypeSpec r, bool primitives_only)4875 		Expression ResolveEquality (ResolveContext ec, TypeSpec l, TypeSpec r, bool primitives_only)
4876 		{
4877 			Expression result;
4878 			type = ec.BuiltinTypes.Bool;
4879 			bool no_arg_conv = false;
4880 
4881 			if (!primitives_only) {
4882 
4883 				//
4884 				// a, Both operands are reference-type values or the value null
4885 				// b, One operand is a value of type T where T is a type-parameter and
4886 				// the other operand is the value null. Furthermore T does not have the
4887 				// value type constraint
4888 				//
4889 				// LAMESPEC: Very confusing details in the specification, basically any
4890 				// reference like type-parameter is allowed
4891 				//
4892 				var tparam_l = l as TypeParameterSpec;
4893 				var tparam_r = r as TypeParameterSpec;
4894 				if (tparam_l != null) {
4895 					if (right is NullLiteral) {
4896 						if (tparam_l.GetEffectiveBase ().BuiltinType == BuiltinTypeSpec.Type.ValueType)
4897 							return null;
4898 
4899 						left = new BoxedCast (left, ec.BuiltinTypes.Object);
4900 						return this;
4901 					}
4902 
4903 					if (!tparam_l.IsReferenceType)
4904 						return null;
4905 
4906 					l = tparam_l.GetEffectiveBase ();
4907 					left = new BoxedCast (left, l);
4908 				} else if (left is NullLiteral && tparam_r == null) {
4909 					if (TypeSpec.IsReferenceType (r))
4910 						return this;
4911 
4912 					if (r.Kind == MemberKind.InternalCompilerType)
4913 						return null;
4914 				}
4915 
4916 				if (tparam_r != null) {
4917 					if (left is NullLiteral) {
4918 						if (tparam_r.GetEffectiveBase ().BuiltinType == BuiltinTypeSpec.Type.ValueType)
4919 							return null;
4920 
4921 						right = new BoxedCast (right, ec.BuiltinTypes.Object);
4922 						return this;
4923 					}
4924 
4925 					if (!tparam_r.IsReferenceType)
4926 						return null;
4927 
4928 					r = tparam_r.GetEffectiveBase ();
4929 					right = new BoxedCast (right, r);
4930 				} else if (right is NullLiteral) {
4931 					if (TypeSpec.IsReferenceType (l))
4932 						return this;
4933 
4934 					if (l.Kind == MemberKind.InternalCompilerType)
4935 						return null;
4936 				}
4937 
4938 				//
4939 				// LAMESPEC: method groups can be compared when they convert to other side delegate
4940 				//
4941 				if (l.IsDelegate) {
4942 					if (right.eclass == ExprClass.MethodGroup) {
4943 						result = Convert.ImplicitConversion (ec, right, l, loc);
4944 						if (result == null)
4945 							return null;
4946 
4947 						right = result;
4948 						r = l;
4949 					} else if (r.IsDelegate && l != r) {
4950 						return null;
4951 					}
4952 				} else if (left.eclass == ExprClass.MethodGroup && r.IsDelegate) {
4953 					result = Convert.ImplicitConversionRequired (ec, left, r, loc);
4954 					if (result == null)
4955 						return null;
4956 
4957 					left = result;
4958 					l = r;
4959 				} else {
4960 					no_arg_conv = l == r && !l.IsStruct;
4961 				}
4962 			}
4963 
4964 			//
4965 			// bool operator != (string a, string b)
4966 			// bool operator == (string a, string b)
4967 			//
4968 			// bool operator != (Delegate a, Delegate b)
4969 			// bool operator == (Delegate a, Delegate b)
4970 			//
4971 			// bool operator != (bool a, bool b)
4972 			// bool operator == (bool a, bool b)
4973 			//
4974 			// LAMESPEC: Reference equality comparison can apply to value/reference types when
4975 			// they implement an implicit conversion to any of types above. This does
4976 			// not apply when both operands are of same reference type
4977 			//
4978 			if (r.BuiltinType != BuiltinTypeSpec.Type.Object && l.BuiltinType != BuiltinTypeSpec.Type.Object) {
4979 				result = ResolveOperatorPredefined (ec, ec.BuiltinTypes.OperatorsBinaryEquality, no_arg_conv);
4980 				if (result != null)
4981 					return result;
4982 
4983 				//
4984 				// Now try lifted version of predefined operators
4985 				//
4986 				if (no_arg_conv && !l.IsNullableType) {
4987 					//
4988 					// Optimizes cases which won't match
4989 					//
4990 				} else {
4991 					result = ResolveOperatorPredefined (ec, ec.Module.OperatorsBinaryEqualityLifted, no_arg_conv);
4992 					if (result != null)
4993 						return result;
4994 				}
4995 
4996 				//
4997 				// The == and != operators permit one operand to be a value of a nullable
4998 				// type and the other to be the null literal, even if no predefined or user-defined
4999 				// operator (in unlifted or lifted form) exists for the operation.
5000 				//
5001 				if ((l.IsNullableType && right.IsNull) || (r.IsNullableType && left.IsNull)) {
5002 					var lifted = new Nullable.LiftedBinaryOperator (this);
5003 					lifted.Left = left;
5004 					lifted.Right = right;
5005 					return lifted.Resolve (ec);
5006 				}
5007 			}
5008 
5009 			//
5010 			// bool operator != (object a, object b)
5011 			// bool operator == (object a, object b)
5012 			//
5013 			// An explicit reference conversion exists from the
5014 			// type of either operand to the type of the other operand.
5015 			//
5016 
5017 			// Optimize common path
5018 			if (l == r) {
5019 				return l.Kind == MemberKind.InternalCompilerType || l.Kind == MemberKind.Struct ? null : this;
5020 			}
5021 
5022 			if (!Convert.ExplicitReferenceConversionExists (l, r) &&
5023 				!Convert.ExplicitReferenceConversionExists (r, l))
5024 				return null;
5025 
5026 			// Reject allowed explicit conversions like int->object
5027 			if (!TypeSpec.IsReferenceType (l) || !TypeSpec.IsReferenceType (r))
5028 				return null;
5029 
5030 			if (l.BuiltinType == BuiltinTypeSpec.Type.String || l.BuiltinType == BuiltinTypeSpec.Type.Delegate || l.IsDelegate || MemberCache.GetUserOperator (l, CSharp.Operator.OpType.Equality, false) != null)
5031 				ec.Report.Warning (253, 2, loc,
5032 					"Possible unintended reference comparison. Consider casting the right side expression to type `{0}' to get value comparison",
5033 					l.GetSignatureForError ());
5034 
5035 			if (r.BuiltinType == BuiltinTypeSpec.Type.String || r.BuiltinType == BuiltinTypeSpec.Type.Delegate || r.IsDelegate || MemberCache.GetUserOperator (r, CSharp.Operator.OpType.Equality, false) != null)
5036 				ec.Report.Warning (252, 2, loc,
5037 					"Possible unintended reference comparison. Consider casting the left side expression to type `{0}' to get value comparison",
5038 					r.GetSignatureForError ());
5039 
5040 			return this;
5041 		}
5042 
5043 
ResolveOperatorPointer(ResolveContext ec, TypeSpec l, TypeSpec r)5044 		Expression ResolveOperatorPointer (ResolveContext ec, TypeSpec l, TypeSpec r)
5045 		{
5046 			//
5047 			// bool operator == (void* x, void* y);
5048 			// bool operator != (void* x, void* y);
5049 			// bool operator < (void* x, void* y);
5050 			// bool operator > (void* x, void* y);
5051 			// bool operator <= (void* x, void* y);
5052 			// bool operator >= (void* x, void* y);
5053 			//
5054 			if ((oper & Operator.ComparisonMask) != 0) {
5055 				Expression temp;
5056 				if (!l.IsPointer) {
5057 					temp = Convert.ImplicitConversion (ec, left, r, left.Location);
5058 					if (temp == null)
5059 						return null;
5060 					left = temp;
5061 				}
5062 
5063 				if (!r.IsPointer) {
5064 					temp = Convert.ImplicitConversion (ec, right, l, right.Location);
5065 					if (temp == null)
5066 						return null;
5067 					right = temp;
5068 				}
5069 
5070 				type = ec.BuiltinTypes.Bool;
5071 				return this;
5072 			}
5073 
5074 			return ResolveOperatorPredefined (ec, ec.BuiltinTypes.OperatorsBinaryUnsafe, false);
5075 		}
5076 
5077 		//
5078 		// Build-in operators method overloading
5079 		//
ResolveOperatorPredefined(ResolveContext ec, PredefinedOperator [] operators, bool primitives_only)5080 		Expression ResolveOperatorPredefined (ResolveContext ec, PredefinedOperator [] operators, bool primitives_only)
5081 		{
5082 			PredefinedOperator best_operator = null;
5083 			TypeSpec l = left.Type;
5084 			TypeSpec r = right.Type;
5085 			Operator oper_mask = oper & ~Operator.ValuesOnlyMask;
5086 
5087 			foreach (PredefinedOperator po in operators) {
5088 				if ((po.OperatorsMask & oper_mask) == 0)
5089 					continue;
5090 
5091 				if (primitives_only) {
5092 					if (!po.IsPrimitiveApplicable (l, r))
5093 						continue;
5094 				} else {
5095 					if (!po.IsApplicable (ec, left, right))
5096 						continue;
5097 				}
5098 
5099 				if (best_operator == null) {
5100 					best_operator = po;
5101 					if (primitives_only)
5102 						break;
5103 
5104 					continue;
5105 				}
5106 
5107 				best_operator = po.ResolveBetterOperator (ec, best_operator);
5108 
5109 				if (best_operator == null) {
5110 					ec.Report.Error (34, loc, "Operator `{0}' is ambiguous on operands of type `{1}' and `{2}'",
5111 						OperName (oper), l.GetSignatureForError (), r.GetSignatureForError ());
5112 
5113 					best_operator = po;
5114 					break;
5115 				}
5116 			}
5117 
5118 			if (best_operator == null)
5119 				return null;
5120 
5121 			return best_operator.ConvertResult (ec, this);
5122 		}
5123 
5124 		//
5125 		// Optimize & constant expressions with 0 value
5126 		//
OptimizeAndOperation(Expression expr)5127 		Expression OptimizeAndOperation (Expression expr)
5128 		{
5129 			Constant rc = right as Constant;
5130 			Constant lc = left as Constant;
5131 			if ((lc != null && lc.IsDefaultValue) || (rc != null && rc.IsDefaultValue)) {
5132 				//
5133 				// The result is a constant with side-effect
5134 				//
5135 				Constant side_effect = rc == null ?
5136 					new SideEffectConstant (lc, right, loc) :
5137 					new SideEffectConstant (rc, left, loc);
5138 
5139 				return ReducedExpression.Create (side_effect, expr);
5140 			}
5141 
5142 			return expr;
5143 		}
5144 
5145 		//
5146 		// Value types can be compared with the null literal because of the lifting
5147 		// language rules. However the result is always true or false.
5148 		//
CreateLiftedValueTypeResult(ResolveContext rc, TypeSpec valueType)5149 		public Expression CreateLiftedValueTypeResult (ResolveContext rc, TypeSpec valueType)
5150 		{
5151 			if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion)) {
5152 				type = rc.BuiltinTypes.Bool;
5153 				return this;
5154 			}
5155 
5156 			// FIXME: Handle side effect constants
5157 			Constant c = new BoolConstant (rc.BuiltinTypes, Oper == Operator.Inequality, loc);
5158 
5159 			if ((Oper & Operator.EqualityMask) != 0) {
5160 				rc.Report.Warning (472, 2, loc, "The result of comparing value type `{0}' with null is always `{1}'",
5161 					valueType.GetSignatureForError (), c.GetValueAsLiteral ());
5162 			} else {
5163 				rc.Report.Warning (464, 2, loc, "The result of comparing type `{0}' with null is always `{1}'",
5164 					valueType.GetSignatureForError (), c.GetValueAsLiteral ());
5165 			}
5166 
5167 			return c;
5168 		}
5169 
5170 		//
5171 		// Performs user-operator overloading
5172 		//
ResolveUserOperator(ResolveContext rc, Expression left, Expression right)5173 		Expression ResolveUserOperator (ResolveContext rc, Expression left, Expression right)
5174 		{
5175 			Expression oper_expr;
5176 
5177 			var op = ConvertBinaryToUserOperator (oper);
5178 			var l = left.Type;
5179 			if (l.IsNullableType)
5180 				l = Nullable.NullableInfo.GetUnderlyingType (l);
5181 			var r = right.Type;
5182 			if (r.IsNullableType)
5183 				r = Nullable.NullableInfo.GetUnderlyingType (r);
5184 
5185 			IList<MemberSpec> left_operators = MemberCache.GetUserOperator (l, op, false);
5186 			IList<MemberSpec> right_operators = null;
5187 
5188 			if (l != r) {
5189 				right_operators = MemberCache.GetUserOperator (r, op, false);
5190 				if (right_operators == null && left_operators == null)
5191 					return null;
5192 			} else if (left_operators == null) {
5193 				return null;
5194 			}
5195 
5196 			Arguments args = new Arguments (2);
5197 			Argument larg = new Argument (left);
5198 			args.Add (larg);
5199 			Argument rarg = new Argument (right);
5200 			args.Add (rarg);
5201 
5202 			//
5203 			// User-defined operator implementations always take precedence
5204 			// over predefined operator implementations
5205 			//
5206 			if (left_operators != null && right_operators != null) {
5207 				left_operators = CombineUserOperators (left_operators, right_operators);
5208 			} else if (right_operators != null) {
5209 				left_operators = right_operators;
5210 			}
5211 
5212 			const OverloadResolver.Restrictions restr = OverloadResolver.Restrictions.ProbingOnly |
5213 				OverloadResolver.Restrictions.NoBaseMembers | OverloadResolver.Restrictions.BaseMembersIncluded;
5214 
5215 			var res = new OverloadResolver (left_operators, restr, loc);
5216 
5217 			var oper_method = res.ResolveOperator (rc, ref args);
5218 			if (oper_method == null) {
5219 				//
5220 				// Logical && and || cannot be lifted
5221 				//
5222 				if ((oper & Operator.LogicalMask) != 0)
5223 					return null;
5224 
5225 				//
5226 				// Apply lifted user operators only for liftable types. Implicit conversion
5227 				// to nullable types is not allowed
5228 				//
5229 				if (!IsLiftedOperatorApplicable ())
5230 					return null;
5231 
5232 				// TODO: Cache the result in module container
5233 				var lifted_methods = CreateLiftedOperators (rc, left_operators);
5234 				if (lifted_methods == null)
5235 					return null;
5236 
5237 				res = new OverloadResolver (lifted_methods, restr | OverloadResolver.Restrictions.ProbingOnly, loc);
5238 
5239 				oper_method = res.ResolveOperator (rc, ref args);
5240 				if (oper_method == null)
5241 					return null;
5242 
5243 				MethodSpec best_original = null;
5244 				foreach (MethodSpec ms in left_operators) {
5245 					if (ms.MemberDefinition == oper_method.MemberDefinition) {
5246 						best_original = ms;
5247 						break;
5248 					}
5249 				}
5250 
5251 				if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion)) {
5252 					//
5253 					// Expression trees use lifted notation in this case
5254 					//
5255 					this.left = Convert.ImplicitConversion (rc, left, oper_method.Parameters.Types[0], left.Location);
5256 					this.right = Convert.ImplicitConversion (rc, right, oper_method.Parameters.Types[1], left.Location);
5257 				}
5258 
5259 				var ptypes = best_original.Parameters.Types;
5260 
5261 				if (left.IsNull || right.IsNull) {
5262 					//
5263 					// The lifted operator produces a null value if one or both operands are null
5264 					//
5265 					if ((oper & (Operator.ArithmeticMask | Operator.ShiftMask | Operator.BitwiseMask)) != 0) {
5266 						type = oper_method.ReturnType;
5267 						return Nullable.LiftedNull.CreateFromExpression (rc, this);
5268 					}
5269 
5270 					//
5271 					// The lifted operator produces the value false if one or both operands are null for
5272 					// relational operators.
5273 					//
5274 					if ((oper & Operator.RelationalMask) != 0) {
5275 						//
5276 						// CSC BUG: This should be different warning, csc reports CS0458 with bool? which is wrong
5277 						// because return type is actually bool
5278 						//
5279 						return CreateLiftedValueTypeResult (rc, left.IsNull ? ptypes [1] : ptypes [0]);
5280 					}
5281 
5282 					if ((oper & Operator.EqualityMask) != 0 && ((left.IsNull && !right.Type.IsNullableType) || !left.Type.IsNullableType)) {
5283 						return CreateLiftedValueTypeResult (rc, left.IsNull ? ptypes [1] : ptypes [0]);
5284 					}
5285 				}
5286 
5287 				type = oper_method.ReturnType;
5288 				var lifted = new Nullable.LiftedBinaryOperator (this);
5289 				lifted.UserOperator = best_original;
5290 
5291 				if (left.Type.IsNullableType && !ptypes[0].IsNullableType) {
5292 					lifted.UnwrapLeft = new Nullable.Unwrap (left);
5293 				}
5294 
5295 				if (right.Type.IsNullableType && !ptypes[1].IsNullableType) {
5296 					lifted.UnwrapRight = new Nullable.Unwrap (right);
5297 				}
5298 
5299 				lifted.Left = Convert.ImplicitConversion (rc, lifted.UnwrapLeft ?? left, ptypes[0], left.Location);
5300 				lifted.Right = Convert.ImplicitConversion (rc, lifted.UnwrapRight ?? right, ptypes[1], right.Location);
5301 
5302 				return lifted.Resolve (rc);
5303 			}
5304 
5305 			if ((oper & Operator.LogicalMask) != 0) {
5306 				// TODO: CreateExpressionTree is allocated every time
5307 				oper_expr = new ConditionalLogicalOperator (oper_method, args, CreateExpressionTree,
5308 					oper == Operator.LogicalAnd, loc).Resolve (rc);
5309 			} else {
5310 				oper_expr = new UserOperatorCall (oper_method, args, CreateExpressionTree, loc);
5311 			}
5312 
5313 			this.left = larg.Expr;
5314 			this.right = rarg.Expr;
5315 
5316 			return oper_expr;
5317 		}
5318 
IsLiftedOperatorApplicable()5319 		bool IsLiftedOperatorApplicable ()
5320 		{
5321 			if (left.Type.IsNullableType) {
5322 				if ((oper & Operator.EqualityMask) != 0)
5323 					return !right.IsNull;
5324 
5325 				return true;
5326 			}
5327 
5328 			if (right.Type.IsNullableType) {
5329 				if ((oper & Operator.EqualityMask) != 0)
5330 					return !left.IsNull;
5331 
5332 				return true;
5333 			}
5334 
5335 			if (TypeSpec.IsValueType (left.Type))
5336 				return right.IsNull;
5337 
5338 			if (TypeSpec.IsValueType (right.Type))
5339 				return left.IsNull;
5340 
5341 			return false;
5342 		}
5343 
CreateLiftedOperators(ResolveContext rc, IList<MemberSpec> operators)5344 		List<MemberSpec> CreateLiftedOperators (ResolveContext rc, IList<MemberSpec> operators)
5345 		{
5346 			var nullable_type = rc.Module.PredefinedTypes.Nullable.TypeSpec;
5347 			if (nullable_type == null)
5348 				return null;
5349 
5350 			//
5351 			// Lifted operators permit predefined and user-defined operators that operate
5352 			// on non-nullable value types to also be used with nullable forms of those types.
5353 			// Lifted operators are constructed from predefined and user-defined operators
5354 			// that meet certain requirements
5355 			//
5356 			List<MemberSpec> lifted = null;
5357 			foreach (MethodSpec oper in operators) {
5358 				TypeSpec rt;
5359 				if ((Oper & Operator.ComparisonMask) != 0) {
5360 					//
5361 					// Result type must be of type bool for lifted comparison operators
5362 					//
5363 					rt = oper.ReturnType;
5364 					if (rt.BuiltinType != BuiltinTypeSpec.Type.Bool)
5365 						continue;
5366 				} else {
5367 					if (!TypeSpec.IsNonNullableValueType (oper.ReturnType))
5368 						continue;
5369 
5370 					rt = null;
5371 				}
5372 
5373 				var ptypes = oper.Parameters.Types;
5374 				if (!TypeSpec.IsNonNullableValueType (ptypes [0]) || !TypeSpec.IsNonNullableValueType (ptypes [1]))
5375 					continue;
5376 
5377 				//
5378 				// LAMESPEC: I am not sure why but for equality operators to be lifted
5379 				// both types have to match
5380 				//
5381 				if ((Oper & Operator.EqualityMask) != 0 && ptypes [0] != ptypes [1])
5382 					continue;
5383 
5384 				if (lifted == null)
5385 					lifted = new List<MemberSpec> ();
5386 
5387 				//
5388 				// The lifted form is constructed by adding a single ? modifier to each operand and
5389 				// result type except for comparison operators where return type is bool
5390 				//
5391 				if (rt == null)
5392 					rt = nullable_type.MakeGenericType (rc.Module, new[] { oper.ReturnType });
5393 
5394 				var parameters = ParametersCompiled.CreateFullyResolved (
5395 					nullable_type.MakeGenericType (rc.Module, new [] { ptypes[0] }),
5396 					nullable_type.MakeGenericType (rc.Module, new [] { ptypes[1] }));
5397 
5398 				var lifted_op = new MethodSpec (oper.Kind, oper.DeclaringType, oper.MemberDefinition,
5399 					rt, parameters, oper.Modifiers);
5400 
5401 				lifted.Add (lifted_op);
5402 			}
5403 
5404 			return lifted;
5405 		}
5406 
5407 		//
5408 		// Merge two sets of user operators into one, they are mostly distinguish
5409 		// except when they share base type and it contains an operator
5410 		//
CombineUserOperators(IList<MemberSpec> left, IList<MemberSpec> right)5411 		static IList<MemberSpec> CombineUserOperators (IList<MemberSpec> left, IList<MemberSpec> right)
5412 		{
5413 			var combined = new List<MemberSpec> (left.Count + right.Count);
5414 			combined.AddRange (left);
5415 			foreach (var r in right) {
5416 				bool same = false;
5417 				foreach (var l in left) {
5418 					if (l.DeclaringType == r.DeclaringType) {
5419 						same = true;
5420 						break;
5421 					}
5422 				}
5423 
5424 				if (!same)
5425 					combined.Add (r);
5426 			}
5427 
5428 			return combined;
5429 		}
5430 
CheckOutOfRangeComparison(ResolveContext ec, Constant c, TypeSpec type)5431 		void CheckOutOfRangeComparison (ResolveContext ec, Constant c, TypeSpec type)
5432 		{
5433 			if (c is IntegralConstant || c is CharConstant) {
5434 				try {
5435 					c.ConvertExplicitly (true, type);
5436 				} catch (OverflowException) {
5437 					ec.Report.Warning (652, 2, loc,
5438 						"A comparison between a constant and a variable is useless. The constant is out of the range of the variable type `{0}'",
5439 						type.GetSignatureForError ());
5440 				}
5441 			}
5442 		}
5443 
5444 		/// <remarks>
5445 		///   EmitBranchable is called from Statement.EmitBoolExpression in the
5446 		///   context of a conditional bool expression.  This function will return
5447 		///   false if it is was possible to use EmitBranchable, or true if it was.
5448 		///
5449 		///   The expression's code is generated, and we will generate a branch to `target'
5450 		///   if the resulting expression value is equal to isTrue
5451 		/// </remarks>
EmitBranchable(EmitContext ec, Label target, bool on_true)5452 		public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
5453 		{
5454 			if (ec.HasSet (BuilderContext.Options.AsyncBody) && right.ContainsEmitWithAwait ()) {
5455 				left = left.EmitToField (ec);
5456 
5457 				if ((oper & Operator.LogicalMask) == 0) {
5458 					right = right.EmitToField (ec);
5459 				}
5460 			}
5461 
5462 			//
5463 			// This is more complicated than it looks, but its just to avoid
5464 			// duplicated tests: basically, we allow ==, !=, >, <, >= and <=
5465 			// but on top of that we want for == and != to use a special path
5466 			// if we are comparing against null
5467 			//
5468 			if ((oper & Operator.EqualityMask) != 0 && (left is Constant || right is Constant)) {
5469 				bool my_on_true = oper == Operator.Inequality ? on_true : !on_true;
5470 
5471 				//
5472 				// put the constant on the rhs, for simplicity
5473 				//
5474 				if (left is Constant) {
5475 					Expression swap = right;
5476 					right = left;
5477 					left = swap;
5478 				}
5479 
5480 				//
5481 				// brtrue/brfalse works with native int only
5482 				//
5483 				if (((Constant) right).IsZeroInteger && right.Type.BuiltinType != BuiltinTypeSpec.Type.Long && right.Type.BuiltinType != BuiltinTypeSpec.Type.ULong) {
5484 					left.EmitBranchable (ec, target, my_on_true);
5485 					return;
5486 				}
5487 				if (right.Type.BuiltinType == BuiltinTypeSpec.Type.Bool) {
5488 					// right is a boolean, and it's not 'false' => it is 'true'
5489 					left.EmitBranchable (ec, target, !my_on_true);
5490 					return;
5491 				}
5492 
5493 			} else if (oper == Operator.LogicalAnd) {
5494 
5495 				if (on_true) {
5496 					Label tests_end = ec.DefineLabel ();
5497 
5498 					left.EmitBranchable (ec, tests_end, false);
5499 					right.EmitBranchable (ec, target, true);
5500 					ec.MarkLabel (tests_end);
5501 				} else {
5502 					//
5503 					// This optimizes code like this
5504 					// if (true && i > 4)
5505 					//
5506 					if (!(left is Constant))
5507 						left.EmitBranchable (ec, target, false);
5508 
5509 					if (!(right is Constant))
5510 						right.EmitBranchable (ec, target, false);
5511 				}
5512 
5513 				return;
5514 
5515 			} else if (oper == Operator.LogicalOr){
5516 				if (on_true) {
5517 					left.EmitBranchable (ec, target, true);
5518 					right.EmitBranchable (ec, target, true);
5519 
5520 				} else {
5521 					Label tests_end = ec.DefineLabel ();
5522 					left.EmitBranchable (ec, tests_end, true);
5523 					right.EmitBranchable (ec, target, false);
5524 					ec.MarkLabel (tests_end);
5525 				}
5526 
5527 				return;
5528 
5529 			} else if ((oper & Operator.ComparisonMask) == 0) {
5530 				base.EmitBranchable (ec, target, on_true);
5531 				return;
5532 			}
5533 
5534 			left.Emit (ec);
5535 			right.Emit (ec);
5536 
5537 			TypeSpec t = left.Type;
5538 			bool is_float = IsFloat (t);
5539 			bool is_unsigned = is_float || IsUnsigned (t);
5540 
5541 			switch (oper){
5542 			case Operator.Equality:
5543 				if (on_true)
5544 					ec.Emit (OpCodes.Beq, target);
5545 				else
5546 					ec.Emit (OpCodes.Bne_Un, target);
5547 				break;
5548 
5549 			case Operator.Inequality:
5550 				if (on_true)
5551 					ec.Emit (OpCodes.Bne_Un, target);
5552 				else
5553 					ec.Emit (OpCodes.Beq, target);
5554 				break;
5555 
5556 			case Operator.LessThan:
5557 				if (on_true)
5558 					if (is_unsigned && !is_float)
5559 						ec.Emit (OpCodes.Blt_Un, target);
5560 					else
5561 						ec.Emit (OpCodes.Blt, target);
5562 				else
5563 					if (is_unsigned)
5564 						ec.Emit (OpCodes.Bge_Un, target);
5565 					else
5566 						ec.Emit (OpCodes.Bge, target);
5567 				break;
5568 
5569 			case Operator.GreaterThan:
5570 				if (on_true)
5571 					if (is_unsigned && !is_float)
5572 						ec.Emit (OpCodes.Bgt_Un, target);
5573 					else
5574 						ec.Emit (OpCodes.Bgt, target);
5575 				else
5576 					if (is_unsigned)
5577 						ec.Emit (OpCodes.Ble_Un, target);
5578 					else
5579 						ec.Emit (OpCodes.Ble, target);
5580 				break;
5581 
5582 			case Operator.LessThanOrEqual:
5583 				if (on_true)
5584 					if (is_unsigned && !is_float)
5585 						ec.Emit (OpCodes.Ble_Un, target);
5586 					else
5587 						ec.Emit (OpCodes.Ble, target);
5588 				else
5589 					if (is_unsigned)
5590 						ec.Emit (OpCodes.Bgt_Un, target);
5591 					else
5592 						ec.Emit (OpCodes.Bgt, target);
5593 				break;
5594 
5595 
5596 			case Operator.GreaterThanOrEqual:
5597 				if (on_true)
5598 					if (is_unsigned && !is_float)
5599 						ec.Emit (OpCodes.Bge_Un, target);
5600 					else
5601 						ec.Emit (OpCodes.Bge, target);
5602 				else
5603 					if (is_unsigned)
5604 						ec.Emit (OpCodes.Blt_Un, target);
5605 					else
5606 						ec.Emit (OpCodes.Blt, target);
5607 				break;
5608 			default:
5609 				throw new InternalErrorException (oper.ToString ());
5610 			}
5611 		}
5612 
Emit(EmitContext ec)5613 		public override void Emit (EmitContext ec)
5614 		{
5615 			if (ec.HasSet (BuilderContext.Options.AsyncBody) && right.ContainsEmitWithAwait ()) {
5616 				left = left.EmitToField (ec);
5617 
5618 				if ((oper & Operator.LogicalMask) == 0) {
5619 					right = right.EmitToField (ec);
5620 				}
5621 			}
5622 
5623 			//
5624 			// Handle short-circuit operators differently
5625 			// than the rest
5626 			//
5627 			if ((oper & Operator.LogicalMask) != 0) {
5628 				Label load_result = ec.DefineLabel ();
5629 				Label end = ec.DefineLabel ();
5630 
5631 				bool is_or = oper == Operator.LogicalOr;
5632 				left.EmitBranchable (ec, load_result, is_or);
5633 				right.Emit (ec);
5634 				ec.Emit (OpCodes.Br_S, end);
5635 
5636 				ec.MarkLabel (load_result);
5637 				ec.EmitInt (is_or ? 1 : 0);
5638 				ec.MarkLabel (end);
5639 				return;
5640 			}
5641 
5642 			//
5643 			// Optimize zero-based operations which cannot be optimized at expression level
5644 			//
5645 			if (oper == Operator.Subtraction) {
5646 				var lc = left as IntegralConstant;
5647 				if (lc != null && lc.IsDefaultValue) {
5648 					right.Emit (ec);
5649 					ec.Emit (OpCodes.Neg);
5650 					return;
5651 				}
5652 			}
5653 
5654 			EmitOperator (ec, left, right);
5655 		}
5656 
EmitOperator(EmitContext ec, Expression left, Expression right)5657 		public void EmitOperator (EmitContext ec, Expression left, Expression right)
5658 		{
5659 			left.Emit (ec);
5660 			right.Emit (ec);
5661 
5662 			EmitOperatorOpcode (ec, oper, left.Type, right);
5663 
5664 			//
5665 			// Emit result enumerable conversion this way because it's quite complicated get it
5666 			// to resolved tree because expression tree cannot see it.
5667 			//
5668 			if (enum_conversion != 0)
5669 				ConvCast.Emit (ec, enum_conversion);
5670 		}
5671 
EmitSideEffect(EmitContext ec)5672 		public override void EmitSideEffect (EmitContext ec)
5673 		{
5674 			if ((oper & Operator.LogicalMask) != 0 ||
5675 				(ec.HasSet (EmitContext.Options.CheckedScope) && (oper == Operator.Multiply || oper == Operator.Addition || oper == Operator.Subtraction))) {
5676 				base.EmitSideEffect (ec);
5677 			} else {
5678 				left.EmitSideEffect (ec);
5679 				right.EmitSideEffect (ec);
5680 			}
5681 		}
5682 
EmitToField(EmitContext ec)5683 		public override Expression EmitToField (EmitContext ec)
5684 		{
5685 			if ((oper & Operator.LogicalMask) == 0) {
5686 				var await_expr = left as Await;
5687 				if (await_expr != null && right.IsSideEffectFree) {
5688 					await_expr.Statement.EmitPrologue (ec);
5689 					left = await_expr.Statement.GetResultExpression (ec);
5690 					return this;
5691 				}
5692 
5693 				await_expr = right as Await;
5694 				if (await_expr != null && left.IsSideEffectFree) {
5695 					await_expr.Statement.EmitPrologue (ec);
5696 					right = await_expr.Statement.GetResultExpression (ec);
5697 					return this;
5698 				}
5699 			}
5700 
5701 			return base.EmitToField (ec);
5702 		}
5703 
CloneTo(CloneContext clonectx, Expression t)5704 		protected override void CloneTo (CloneContext clonectx, Expression t)
5705 		{
5706 			Binary target = (Binary) t;
5707 
5708 			target.left = left.Clone (clonectx);
5709 			target.right = right.Clone (clonectx);
5710 		}
5711 
CreateCallSiteBinder(ResolveContext ec, Arguments args)5712 		public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args)
5713 		{
5714 			Arguments binder_args = new Arguments (4);
5715 
5716 			MemberAccess sle = new MemberAccess (new MemberAccess (
5717 				new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Linq", loc), "Expressions", loc);
5718 
5719 			CSharpBinderFlags flags = 0;
5720 			if (ec.HasSet (ResolveContext.Options.CheckedScope))
5721 				flags = CSharpBinderFlags.CheckedContext;
5722 
5723 			if ((oper & Operator.LogicalMask) != 0)
5724 				flags |= CSharpBinderFlags.BinaryOperationLogical;
5725 
5726 			binder_args.Add (new Argument (new EnumConstant (new IntLiteral (ec.BuiltinTypes, (int) flags, loc), ec.Module.PredefinedTypes.BinderFlags.Resolve ())));
5727 			binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), GetOperatorExpressionTypeName (), loc)));
5728 			binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc)));
5729 			binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc)));
5730 
5731 			return new Invocation (new MemberAccess (new TypeExpression (ec.Module.PredefinedTypes.Binder.TypeSpec, loc), "BinaryOperation", loc), binder_args);
5732 		}
5733 
CreateExpressionTree(ResolveContext ec)5734 		public override Expression CreateExpressionTree (ResolveContext ec)
5735 		{
5736 			return CreateExpressionTree (ec, null);
5737 		}
5738 
CreateExpressionTree(ResolveContext ec, Expression method)5739 		public Expression CreateExpressionTree (ResolveContext ec, Expression method)
5740 		{
5741 			string method_name;
5742 			bool lift_arg = false;
5743 
5744 			switch (oper) {
5745 			case Operator.Addition:
5746 				if (method == null && ec.HasSet (ResolveContext.Options.CheckedScope) && !IsFloat (type))
5747 					method_name = "AddChecked";
5748 				else
5749 					method_name = "Add";
5750 				break;
5751 			case Operator.BitwiseAnd:
5752 				method_name = "And";
5753 				break;
5754 			case Operator.BitwiseOr:
5755 				method_name = "Or";
5756 				break;
5757 			case Operator.Division:
5758 				method_name = "Divide";
5759 				break;
5760 			case Operator.Equality:
5761 				method_name = "Equal";
5762 				lift_arg = true;
5763 				break;
5764 			case Operator.ExclusiveOr:
5765 				method_name = "ExclusiveOr";
5766 				break;
5767 			case Operator.GreaterThan:
5768 				method_name = "GreaterThan";
5769 				lift_arg = true;
5770 				break;
5771 			case Operator.GreaterThanOrEqual:
5772 				method_name = "GreaterThanOrEqual";
5773 				lift_arg = true;
5774 				break;
5775 			case Operator.Inequality:
5776 				method_name = "NotEqual";
5777 				lift_arg = true;
5778 				break;
5779 			case Operator.LeftShift:
5780 				method_name = "LeftShift";
5781 				break;
5782 			case Operator.LessThan:
5783 				method_name = "LessThan";
5784 				lift_arg = true;
5785 				break;
5786 			case Operator.LessThanOrEqual:
5787 				method_name = "LessThanOrEqual";
5788 				lift_arg = true;
5789 				break;
5790 			case Operator.LogicalAnd:
5791 				method_name = "AndAlso";
5792 				break;
5793 			case Operator.LogicalOr:
5794 				method_name = "OrElse";
5795 				break;
5796 			case Operator.Modulus:
5797 				method_name = "Modulo";
5798 				break;
5799 			case Operator.Multiply:
5800 				if (method == null && ec.HasSet (ResolveContext.Options.CheckedScope) && !IsFloat (type))
5801 					method_name = "MultiplyChecked";
5802 				else
5803 					method_name = "Multiply";
5804 				break;
5805 			case Operator.RightShift:
5806 				method_name = "RightShift";
5807 				break;
5808 			case Operator.Subtraction:
5809 				if (method == null && ec.HasSet (ResolveContext.Options.CheckedScope) && !IsFloat (type))
5810 					method_name = "SubtractChecked";
5811 				else
5812 					method_name = "Subtract";
5813 				break;
5814 
5815 			default:
5816 				throw new InternalErrorException ("Unknown expression tree binary operator " + oper);
5817 			}
5818 
5819 			Arguments args = new Arguments (2);
5820 			args.Add (new Argument (left.CreateExpressionTree (ec)));
5821 			args.Add (new Argument (right.CreateExpressionTree (ec)));
5822 			if (method != null) {
5823 				if (lift_arg)
5824 					args.Add (new Argument (new BoolLiteral (ec.BuiltinTypes, false, loc)));
5825 
5826 				args.Add (new Argument (method));
5827 			}
5828 
5829 			return CreateExpressionFactoryCall (ec, method_name, args);
5830 		}
5831 
Accept(StructuralVisitor visitor)5832 		public override object Accept (StructuralVisitor visitor)
5833 		{
5834 			return visitor.Visit (this);
5835 		}
5836 
5837 	}
5838 
5839 	//
5840 	// Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string
5841 	// b, c, d... may be strings or objects.
5842 	//
5843 	public class StringConcat : Expression
5844 	{
5845 		Arguments arguments;
5846 
StringConcat(Location loc)5847 		StringConcat (Location loc)
5848 		{
5849 			this.loc = loc;
5850 			arguments = new Arguments (2);
5851 		}
5852 
ContainsEmitWithAwait()5853 		public override bool ContainsEmitWithAwait ()
5854 		{
5855 			return arguments.ContainsEmitWithAwait ();
5856 		}
5857 
Create(ResolveContext rc, Expression left, Expression right, Location loc)5858 		public static StringConcat Create (ResolveContext rc, Expression left, Expression right, Location loc)
5859 		{
5860 			if (left.eclass == ExprClass.Unresolved || right.eclass == ExprClass.Unresolved)
5861 				throw new ArgumentException ();
5862 
5863 			var s = new StringConcat (loc);
5864 			s.type = rc.BuiltinTypes.String;
5865 			s.eclass = ExprClass.Value;
5866 
5867 			s.Append (rc, left);
5868 			s.Append (rc, right);
5869 			return s;
5870 		}
5871 
CreateExpressionTree(ResolveContext ec)5872 		public override Expression CreateExpressionTree (ResolveContext ec)
5873 		{
5874 			Argument arg = arguments [0];
5875 			return CreateExpressionAddCall (ec, arg, arg.CreateExpressionTree (ec), 1);
5876 		}
5877 
5878 		//
5879 		// Creates nested calls tree from an array of arguments used for IL emit
5880 		//
CreateExpressionAddCall(ResolveContext ec, Argument left, Expression left_etree, int pos)5881 		Expression CreateExpressionAddCall (ResolveContext ec, Argument left, Expression left_etree, int pos)
5882 		{
5883 			Arguments concat_args = new Arguments (2);
5884 			Arguments add_args = new Arguments (3);
5885 
5886 			concat_args.Add (left);
5887 			add_args.Add (new Argument (left_etree));
5888 
5889 			concat_args.Add (arguments [pos]);
5890 			add_args.Add (new Argument (arguments [pos].CreateExpressionTree (ec)));
5891 
5892 			var methods = GetConcatMethodCandidates ();
5893 			if (methods == null)
5894 				return null;
5895 
5896 			var res = new OverloadResolver (methods, OverloadResolver.Restrictions.NoBaseMembers, loc);
5897 			var method = res.ResolveMember<MethodSpec> (ec, ref concat_args);
5898 			if (method == null)
5899 				return null;
5900 
5901 			add_args.Add (new Argument (new TypeOfMethod (method, loc)));
5902 
5903 			Expression expr = CreateExpressionFactoryCall (ec, "Add", add_args);
5904 			if (++pos == arguments.Count)
5905 				return expr;
5906 
5907 			left = new Argument (new EmptyExpression (method.ReturnType));
5908 			return CreateExpressionAddCall (ec, left, expr, pos);
5909 		}
5910 
DoResolve(ResolveContext ec)5911 		protected override Expression DoResolve (ResolveContext ec)
5912 		{
5913 			return this;
5914 		}
5915 
Append(ResolveContext rc, Expression operand)5916 		void Append (ResolveContext rc, Expression operand)
5917 		{
5918 			//
5919 			// Constant folding
5920 			//
5921 			StringConstant sc = operand as StringConstant;
5922 			if (sc != null) {
5923 				if (arguments.Count != 0) {
5924 					Argument last_argument = arguments [arguments.Count - 1];
5925 					StringConstant last_expr_constant = last_argument.Expr as StringConstant;
5926 					if (last_expr_constant != null) {
5927 						last_argument.Expr = new StringConstant (rc.BuiltinTypes, last_expr_constant.Value + sc.Value, sc.Location);
5928 						return;
5929 					}
5930 				}
5931 			} else {
5932 				//
5933 				// Multiple (3+) concatenation are resolved as multiple StringConcat instances
5934 				//
5935 				StringConcat concat_oper = operand as StringConcat;
5936 				if (concat_oper != null) {
5937 					arguments.AddRange (concat_oper.arguments);
5938 					return;
5939 				}
5940 			}
5941 
5942 			arguments.Add (new Argument (operand));
5943 		}
5944 
GetConcatMethodCandidates()5945 		IList<MemberSpec> GetConcatMethodCandidates ()
5946 		{
5947 			return MemberCache.FindMembers (type, "Concat", true);
5948 		}
5949 
Emit(EmitContext ec)5950 		public override void Emit (EmitContext ec)
5951 		{
5952 			// Optimize by removing any extra null arguments, they are no-op
5953 			for (int i = 0; i < arguments.Count; ++i) {
5954 				if (arguments[i].Expr is NullConstant)
5955 					arguments.RemoveAt (i--);
5956 			}
5957 
5958 			var members = GetConcatMethodCandidates ();
5959 			var res = new OverloadResolver (members, OverloadResolver.Restrictions.NoBaseMembers, loc);
5960 			var method = res.ResolveMember<MethodSpec> (new ResolveContext (ec.MemberContext), ref arguments);
5961 			if (method != null) {
5962 				var call = new CallEmitter ();
5963 				call.EmitPredefined (ec, method, arguments, false);
5964 			}
5965 		}
5966 
FlowAnalysis(FlowAnalysisContext fc)5967 		public override void FlowAnalysis (FlowAnalysisContext fc)
5968 		{
5969 			arguments.FlowAnalysis (fc);
5970 		}
5971 
MakeExpression(BuilderContext ctx)5972 		public override SLE.Expression MakeExpression (BuilderContext ctx)
5973 		{
5974 			if (arguments.Count != 2)
5975 				throw new NotImplementedException ("arguments.Count != 2");
5976 
5977 			var concat = typeof (string).GetMethod ("Concat", new[] { typeof (object), typeof (object) });
5978 			return SLE.Expression.Add (arguments[0].Expr.MakeExpression (ctx), arguments[1].Expr.MakeExpression (ctx), concat);
5979 		}
5980 	}
5981 
5982 	//
5983 	// User-defined conditional logical operator
5984 	//
5985 	public class ConditionalLogicalOperator : UserOperatorCall
5986 	{
5987 		readonly bool is_and;
5988 		Expression oper_expr;
5989 
ConditionalLogicalOperator(MethodSpec oper, Arguments arguments, Func<ResolveContext, Expression, Expression> expr_tree, bool is_and, Location loc)5990 		public ConditionalLogicalOperator (MethodSpec oper, Arguments arguments, Func<ResolveContext, Expression, Expression> expr_tree, bool is_and, Location loc)
5991 			: base (oper, arguments, expr_tree, loc)
5992 		{
5993 			this.is_and = is_and;
5994 			eclass = ExprClass.Unresolved;
5995 		}
5996 
DoResolve(ResolveContext ec)5997 		protected override Expression DoResolve (ResolveContext ec)
5998 		{
5999 			AParametersCollection pd = oper.Parameters;
6000 			if (!TypeSpecComparer.IsEqual (type, pd.Types[0]) || !TypeSpecComparer.IsEqual (type, pd.Types[1])) {
6001 				ec.Report.Error (217, loc,
6002 					"A user-defined operator `{0}' must have each parameter type and return type of the same type in order to be applicable as a short circuit operator",
6003 					oper.GetSignatureForError ());
6004 				return null;
6005 			}
6006 
6007 			Expression left_dup = new EmptyExpression (type);
6008 			Expression op_true = GetOperatorTrue (ec, left_dup, loc);
6009 			Expression op_false = GetOperatorFalse (ec, left_dup, loc);
6010 			if (op_true == null || op_false == null) {
6011 				ec.Report.Error (218, loc,
6012 					"The type `{0}' must have operator `true' and operator `false' defined when `{1}' is used as a short circuit operator",
6013 					type.GetSignatureForError (), oper.GetSignatureForError ());
6014 				return null;
6015 			}
6016 
6017 			oper_expr = is_and ? op_false : op_true;
6018 			eclass = ExprClass.Value;
6019 			return this;
6020 		}
6021 
Emit(EmitContext ec)6022 		public override void Emit (EmitContext ec)
6023 		{
6024 			Label end_target = ec.DefineLabel ();
6025 
6026 			//
6027 			// Emit and duplicate left argument
6028 			//
6029 			bool right_contains_await = ec.HasSet (BuilderContext.Options.AsyncBody) && arguments[1].Expr.ContainsEmitWithAwait ();
6030 			if (right_contains_await) {
6031 				arguments[0] = arguments[0].EmitToField (ec, false);
6032 				arguments[0].Expr.Emit (ec);
6033 			} else {
6034 				arguments[0].Expr.Emit (ec);
6035 				ec.Emit (OpCodes.Dup);
6036 				arguments.RemoveAt (0);
6037 			}
6038 
6039 			oper_expr.EmitBranchable (ec, end_target, true);
6040 
6041 			base.Emit (ec);
6042 
6043 			if (right_contains_await) {
6044 				//
6045 				// Special handling when right expression contains await and left argument
6046 				// could not be left on stack before logical branch
6047 				//
6048 				Label skip_left_load = ec.DefineLabel ();
6049 				ec.Emit (OpCodes.Br_S, skip_left_load);
6050 				ec.MarkLabel (end_target);
6051 				arguments[0].Expr.Emit (ec);
6052 				ec.MarkLabel (skip_left_load);
6053 			} else {
6054 				ec.MarkLabel (end_target);
6055 			}
6056 		}
6057 	}
6058 
6059 	public class PointerArithmetic : Expression {
6060 		Expression left, right;
6061 		readonly Binary.Operator op;
6062 
6063 		//
6064 		// We assume that `l' is always a pointer
6065 		//
PointerArithmetic(Binary.Operator op, Expression l, Expression r, TypeSpec t, Location loc)6066 		public PointerArithmetic (Binary.Operator op, Expression l, Expression r, TypeSpec t, Location loc)
6067 		{
6068 			type = t;
6069 			this.loc = loc;
6070 			left = l;
6071 			right = r;
6072 			this.op = op;
6073 		}
6074 
ContainsEmitWithAwait()6075 		public override bool ContainsEmitWithAwait ()
6076 		{
6077 			throw new NotImplementedException ();
6078 		}
6079 
CreateExpressionTree(ResolveContext ec)6080 		public override Expression CreateExpressionTree (ResolveContext ec)
6081 		{
6082 			Error_PointerInsideExpressionTree (ec);
6083 			return null;
6084 		}
6085 
DoResolve(ResolveContext ec)6086 		protected override Expression DoResolve (ResolveContext ec)
6087 		{
6088 			eclass = ExprClass.Variable;
6089 
6090 			var pc = left.Type as PointerContainer;
6091 			if (pc != null && pc.Element.Kind == MemberKind.Void) {
6092 				Error_VoidPointerOperation (ec);
6093 				return null;
6094 			}
6095 
6096 			return this;
6097 		}
6098 
Emit(EmitContext ec)6099 		public override void Emit (EmitContext ec)
6100 		{
6101 			TypeSpec op_type = left.Type;
6102 
6103 			// It must be either array or fixed buffer
6104 			TypeSpec element;
6105 			if (TypeManager.HasElementType (op_type)) {
6106 				element = TypeManager.GetElementType (op_type);
6107 			} else {
6108 				FieldExpr fe = left as FieldExpr;
6109 				if (fe != null)
6110 					element = ((FixedFieldSpec) (fe.Spec)).ElementType;
6111 				else
6112 					element = op_type;
6113 			}
6114 
6115 			int size = BuiltinTypeSpec.GetSize(element);
6116 			TypeSpec rtype = right.Type;
6117 
6118 			if ((op & Binary.Operator.SubtractionMask) != 0 && rtype.IsPointer){
6119 				//
6120 				// handle (pointer - pointer)
6121 				//
6122 				left.Emit (ec);
6123 				right.Emit (ec);
6124 				ec.Emit (OpCodes.Sub);
6125 
6126 				if (size != 1){
6127 					if (size == 0)
6128 						ec.Emit (OpCodes.Sizeof, element);
6129 					else
6130 						ec.EmitInt (size);
6131 					ec.Emit (OpCodes.Div);
6132 				}
6133 				ec.Emit (OpCodes.Conv_I8);
6134 			} else {
6135 				//
6136 				// handle + and - on (pointer op int)
6137 				//
6138 				Constant left_const = left as Constant;
6139 				if (left_const != null) {
6140 					//
6141 					// Optimize ((T*)null) pointer operations
6142 					//
6143 					if (left_const.IsDefaultValue) {
6144 						left = EmptyExpression.Null;
6145 					} else {
6146 						left_const = null;
6147 					}
6148 				}
6149 
6150 				left.Emit (ec);
6151 
6152 				var right_const = right as Constant;
6153 				if (right_const != null) {
6154 					//
6155 					// Optimize 0-based arithmetic
6156 					//
6157 					if (right_const.IsDefaultValue)
6158 						return;
6159 
6160 					if (size != 0)
6161 						right = new IntConstant (ec.BuiltinTypes, size, right.Location);
6162 					else
6163 						right = new SizeOf (new TypeExpression (element, right.Location), right.Location);
6164 
6165 					// TODO: Should be the checks resolve context sensitive?
6166 					ResolveContext rc = new ResolveContext (ec.MemberContext, ResolveContext.Options.UnsafeScope);
6167 					right = new Binary (Binary.Operator.Multiply, right, right_const).Resolve (rc);
6168 					if (right == null)
6169 						return;
6170 				}
6171 
6172 				right.Emit (ec);
6173 				if (right_const == null) {
6174 					switch (rtype.BuiltinType) {
6175 					case BuiltinTypeSpec.Type.SByte:
6176 					case BuiltinTypeSpec.Type.Byte:
6177 					case BuiltinTypeSpec.Type.Short:
6178 					case BuiltinTypeSpec.Type.UShort:
6179 					case BuiltinTypeSpec.Type.Int:
6180 						ec.Emit (OpCodes.Conv_I);
6181 						break;
6182 					case BuiltinTypeSpec.Type.UInt:
6183 						ec.Emit (OpCodes.Conv_U);
6184 						break;
6185 					}
6186 				}
6187 
6188 				if (right_const == null && size != 1){
6189 					if (size == 0)
6190 						ec.Emit (OpCodes.Sizeof, element);
6191 					else
6192 						ec.EmitInt (size);
6193 					if (rtype.BuiltinType == BuiltinTypeSpec.Type.Long || rtype.BuiltinType == BuiltinTypeSpec.Type.ULong)
6194 						ec.Emit (OpCodes.Conv_I8);
6195 
6196 					Binary.EmitOperatorOpcode (ec, Binary.Operator.Multiply, rtype, right);
6197 				}
6198 
6199 				if (left_const == null) {
6200 					if (rtype.BuiltinType == BuiltinTypeSpec.Type.Long)
6201 						ec.Emit (OpCodes.Conv_I);
6202 					else if (rtype.BuiltinType == BuiltinTypeSpec.Type.ULong)
6203 						ec.Emit (OpCodes.Conv_U);
6204 
6205 					Binary.EmitOperatorOpcode (ec, op, op_type, right);
6206 				}
6207 			}
6208 		}
6209 	}
6210 
6211 	//
6212 	// A boolean-expression is an expression that yields a result
6213 	// of type bool
6214 	//
6215 	public class BooleanExpression : ShimExpression
6216 	{
BooleanExpression(Expression expr)6217 		public BooleanExpression (Expression expr)
6218 			: base (expr)
6219 		{
6220 			this.loc = expr.Location;
6221 		}
6222 
CreateExpressionTree(ResolveContext ec)6223 		public override Expression CreateExpressionTree (ResolveContext ec)
6224 		{
6225 			// TODO: We should emit IsTrue (v4) instead of direct user operator
6226 			// call but that would break csc compatibility
6227 			return base.CreateExpressionTree (ec);
6228 		}
6229 
DoResolve(ResolveContext ec)6230 		protected override Expression DoResolve (ResolveContext ec)
6231 		{
6232 			// A boolean-expression is required to be of a type
6233 			// that can be implicitly converted to bool or of
6234 			// a type that implements operator true
6235 
6236 			expr = expr.Resolve (ec);
6237 			if (expr == null)
6238 				return null;
6239 
6240 			Assign ass = expr as Assign;
6241 			if (ass != null && ass.Source is Constant) {
6242 				ec.Report.Warning (665, 3, loc,
6243 					"Assignment in conditional expression is always constant. Did you mean to use `==' instead ?");
6244 			}
6245 
6246 			if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Bool)
6247 				return expr;
6248 
6249 			if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
6250 				Arguments args = new Arguments (1);
6251 				args.Add (new Argument (expr));
6252 				return DynamicUnaryConversion.CreateIsTrue (ec, args, loc).Resolve (ec);
6253 			}
6254 
6255 			type = ec.BuiltinTypes.Bool;
6256 			Expression converted = Convert.ImplicitConversion (ec, expr, type, loc);
6257 			if (converted != null)
6258 				return converted;
6259 
6260 			//
6261 			// If no implicit conversion to bool exists, try using `operator true'
6262 			//
6263 			converted = GetOperatorTrue (ec, expr, loc);
6264 			if (converted == null) {
6265 				expr.Error_ValueCannotBeConverted (ec, type, false);
6266 				return null;
6267 			}
6268 
6269 			return converted;
6270 		}
6271 
Accept(StructuralVisitor visitor)6272 		public override object Accept (StructuralVisitor visitor)
6273 		{
6274 			return visitor.Visit (this);
6275 		}
6276 	}
6277 
6278 	public class BooleanExpressionFalse : Unary
6279 	{
BooleanExpressionFalse(Expression expr)6280 		public BooleanExpressionFalse (Expression expr)
6281 			: base (Operator.LogicalNot, expr, expr.Location)
6282 		{
6283 		}
6284 
ResolveOperator(ResolveContext ec, Expression expr)6285 		protected override Expression ResolveOperator (ResolveContext ec, Expression expr)
6286 		{
6287 			return GetOperatorFalse (ec, expr, loc) ?? base.ResolveOperator (ec, expr);
6288 		}
6289 	}
6290 
6291 	/// <summary>
6292 	///   Implements the ternary conditional operator (?:)
6293 	/// </summary>
6294 	public class Conditional : Expression {
6295 		Expression expr, true_expr, false_expr;
6296 
Conditional(Expression expr, Expression true_expr, Expression false_expr, Location loc)6297 		public Conditional (Expression expr, Expression true_expr, Expression false_expr, Location loc)
6298 		{
6299 			this.expr = expr;
6300 			this.true_expr = true_expr;
6301 			this.false_expr = false_expr;
6302 			this.loc = loc;
6303 		}
6304 
6305 		#region Properties
6306 
6307 		public Expression Expr {
6308 			get {
6309 				return expr;
6310 			}
6311 		}
6312 
6313 		public Expression TrueExpr {
6314 			get {
6315 				return true_expr;
6316 			}
6317 		}
6318 
6319 		public Expression FalseExpr {
6320 			get {
6321 				return false_expr;
6322 			}
6323 		}
6324 
6325 		#endregion
6326 
ContainsEmitWithAwait()6327 		public override bool ContainsEmitWithAwait ()
6328 		{
6329 			return Expr.ContainsEmitWithAwait () || true_expr.ContainsEmitWithAwait () || false_expr.ContainsEmitWithAwait ();
6330 		}
6331 
CreateExpressionTree(ResolveContext ec)6332 		public override Expression CreateExpressionTree (ResolveContext ec)
6333 		{
6334 			Arguments args = new Arguments (3);
6335 			args.Add (new Argument (expr.CreateExpressionTree (ec)));
6336 			args.Add (new Argument (true_expr.CreateExpressionTree (ec)));
6337 			args.Add (new Argument (false_expr.CreateExpressionTree (ec)));
6338 			return CreateExpressionFactoryCall (ec, "Condition", args);
6339 		}
6340 
DoResolve(ResolveContext ec)6341 		protected override Expression DoResolve (ResolveContext ec)
6342 		{
6343 			expr = expr.Resolve (ec);
6344 			true_expr = true_expr.Resolve (ec);
6345 			false_expr = false_expr.Resolve (ec);
6346 
6347 			if (true_expr == null || false_expr == null || expr == null)
6348 				return null;
6349 
6350 			eclass = ExprClass.Value;
6351 			TypeSpec true_type = true_expr.Type;
6352 			TypeSpec false_type = false_expr.Type;
6353 			type = true_type;
6354 
6355 			//
6356 			// First, if an implicit conversion exists from true_expr
6357 			// to false_expr, then the result type is of type false_expr.Type
6358 			//
6359 			if (!TypeSpecComparer.IsEqual (true_type, false_type)) {
6360 				Expression conv = Convert.ImplicitConversion (ec, true_expr, false_type, loc);
6361 				if (conv != null && true_type.BuiltinType != BuiltinTypeSpec.Type.Dynamic) {
6362 					//
6363 					// Check if both can convert implicitly to each other's type
6364 					//
6365 					type = false_type;
6366 
6367 					if (false_type.BuiltinType != BuiltinTypeSpec.Type.Dynamic) {
6368 						var conv_false_expr = Convert.ImplicitConversion (ec, false_expr, true_type, loc);
6369 						//
6370 						// LAMESPEC: There seems to be hardcoded promotition to int type when
6371 						// both sides are numeric constants and one side is int constant and
6372 						// other side is numeric constant convertible to int.
6373 						//
6374 						// var res = condition ? (short)1 : 1;
6375 						//
6376 						// Type of res is int even if according to the spec the conversion is
6377 						// ambiguous because 1 literal can be converted to short.
6378 						//
6379 						if (conv_false_expr != null) {
6380 							if (conv_false_expr.Type.BuiltinType == BuiltinTypeSpec.Type.Int && conv is Constant) {
6381 								type = true_type;
6382 								conv_false_expr = null;
6383 							} else if (type.BuiltinType == BuiltinTypeSpec.Type.Int && conv_false_expr is Constant) {
6384 								conv_false_expr = null;
6385 							}
6386 						}
6387 
6388 						if (conv_false_expr != null) {
6389 							ec.Report.Error (172, true_expr.Location,
6390 								"Type of conditional expression cannot be determined as `{0}' and `{1}' convert implicitly to each other",
6391 									true_type.GetSignatureForError (), false_type.GetSignatureForError ());
6392 						}
6393 					}
6394 
6395 					true_expr = conv;
6396 					if (true_expr.Type != type)
6397 						true_expr = EmptyCast.Create (true_expr, type);
6398 				} else if ((conv = Convert.ImplicitConversion (ec, false_expr, true_type, loc)) != null) {
6399 					false_expr = conv;
6400 				} else {
6401 					if (false_type != InternalType.ErrorType) {
6402 						ec.Report.Error (173, true_expr.Location,
6403 							"Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'",
6404 							true_type.GetSignatureForError (), false_type.GetSignatureForError ());
6405 					}
6406 					return null;
6407 				}
6408 			}
6409 
6410 			Constant c = expr as Constant;
6411 			if (c != null) {
6412 				bool is_false = c.IsDefaultValue;
6413 
6414 				//
6415 				// Don't issue the warning for constant expressions
6416 				//
6417 				if (!(is_false ? true_expr is Constant : false_expr is Constant)) {
6418 					// CSC: Missing warning
6419 					Warning_UnreachableExpression (ec, is_false ? true_expr.Location : false_expr.Location);
6420 				}
6421 
6422 				return ReducedExpression.Create (
6423 					is_false ? false_expr : true_expr, this,
6424 					false_expr is Constant && true_expr is Constant).Resolve (ec);
6425 			}
6426 
6427 			return this;
6428 		}
6429 
Emit(EmitContext ec)6430 		public override void Emit (EmitContext ec)
6431 		{
6432 			Label false_target = ec.DefineLabel ();
6433 			Label end_target = ec.DefineLabel ();
6434 
6435 			expr.EmitBranchable (ec, false_target, false);
6436 			true_expr.Emit (ec);
6437 
6438 			//
6439 			// Verifier doesn't support interface merging. When there are two types on
6440 			// the stack without common type hint and the common type is an interface.
6441 			// Use temporary local to give verifier hint on what type to unify the stack
6442 			//
6443 			if (type.IsInterface && true_expr is EmptyCast && false_expr is EmptyCast) {
6444 				var temp = ec.GetTemporaryLocal (type);
6445 				ec.Emit (OpCodes.Stloc, temp);
6446 				ec.Emit (OpCodes.Ldloc, temp);
6447 				ec.FreeTemporaryLocal (temp, type);
6448 			}
6449 
6450 			ec.Emit (OpCodes.Br, end_target);
6451 			ec.MarkLabel (false_target);
6452 			false_expr.Emit (ec);
6453 			ec.MarkLabel (end_target);
6454 		}
6455 
FlowAnalysis(FlowAnalysisContext fc)6456 		public override void FlowAnalysis (FlowAnalysisContext fc)
6457 		{
6458 			expr.FlowAnalysisConditional (fc);
6459 			var expr_true = fc.DefiniteAssignmentOnTrue;
6460 			var expr_false = fc.DefiniteAssignmentOnFalse;
6461 
6462 			fc.BranchDefiniteAssignment (expr_true);
6463 			true_expr.FlowAnalysis (fc);
6464 			var true_fc = fc.DefiniteAssignment;
6465 
6466 			fc.BranchDefiniteAssignment (expr_false);
6467 			false_expr.FlowAnalysis (fc);
6468 
6469 			fc.DefiniteAssignment &= true_fc;
6470 		}
6471 
FlowAnalysisConditional(FlowAnalysisContext fc)6472 		public override void FlowAnalysisConditional (FlowAnalysisContext fc)
6473 		{
6474 			expr.FlowAnalysisConditional (fc);
6475 			var expr_true = fc.DefiniteAssignmentOnTrue;
6476 			var expr_false = fc.DefiniteAssignmentOnFalse;
6477 
6478 			fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment = new DefiniteAssignmentBitSet (expr_true);
6479 			true_expr.FlowAnalysisConditional (fc);
6480 			var true_fc = fc.DefiniteAssignment;
6481 			var true_da_true = fc.DefiniteAssignmentOnTrue;
6482 			var true_da_false = fc.DefiniteAssignmentOnFalse;
6483 
6484 			fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment = new DefiniteAssignmentBitSet (expr_false);
6485 			false_expr.FlowAnalysisConditional (fc);
6486 
6487 			fc.DefiniteAssignment &= true_fc;
6488 			fc.DefiniteAssignmentOnTrue = true_da_true & fc.DefiniteAssignmentOnTrue;
6489 			fc.DefiniteAssignmentOnFalse = true_da_false & fc.DefiniteAssignmentOnFalse;
6490 		}
6491 
CloneTo(CloneContext clonectx, Expression t)6492 		protected override void CloneTo (CloneContext clonectx, Expression t)
6493 		{
6494 			Conditional target = (Conditional) t;
6495 
6496 			target.expr = expr.Clone (clonectx);
6497 			target.true_expr = true_expr.Clone (clonectx);
6498 			target.false_expr = false_expr.Clone (clonectx);
6499 		}
6500 	}
6501 
6502 	public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation, IVariableReference
6503 	{
6504 		LocalTemporary temp;
6505 
6506 		#region Abstract
GetHoistedVariable(AnonymousExpression ae)6507 		public abstract HoistedVariable GetHoistedVariable (AnonymousExpression ae);
SetHasAddressTaken()6508 		public abstract void SetHasAddressTaken ();
6509 
6510 		public abstract bool IsLockedByStatement { get; set; }
6511 
6512 		public abstract bool IsFixed { get; }
6513 		public abstract bool IsRef { get; }
6514 		public abstract string Name { get; }
6515 
6516 		//
6517 		// Variable IL data, it has to be protected to encapsulate hoisted variables
6518 		//
6519 		protected abstract ILocalVariable Variable { get; }
6520 
6521 		//
6522 		// Variable flow-analysis data
6523 		//
6524 		public abstract VariableInfo VariableInfo { get; }
6525 		#endregion
6526 
AddressOf(EmitContext ec, AddressOp mode)6527 		public virtual void AddressOf (EmitContext ec, AddressOp mode)
6528 		{
6529 			HoistedVariable hv = GetHoistedVariable (ec);
6530 			if (hv != null) {
6531 				hv.AddressOf (ec, mode);
6532 				return;
6533 			}
6534 
6535 			Variable.EmitAddressOf (ec);
6536 		}
6537 
ContainsEmitWithAwait()6538 		public override bool ContainsEmitWithAwait ()
6539 		{
6540 			return false;
6541 		}
6542 
CreateExpressionTree(ResolveContext ec)6543 		public override Expression CreateExpressionTree (ResolveContext ec)
6544 		{
6545 			HoistedVariable hv = GetHoistedVariable (ec);
6546 			if (hv != null)
6547 				return hv.CreateExpressionTree ();
6548 
6549 			Arguments arg = new Arguments (1);
6550 			arg.Add (new Argument (this));
6551 			return CreateExpressionFactoryCall (ec, "Constant", arg);
6552 		}
6553 
DoResolveLValue(ResolveContext rc, Expression right_side)6554 		public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
6555 		{
6556 			if (IsLockedByStatement) {
6557 				rc.Report.Warning (728, 2, loc,
6558 					"Possibly incorrect assignment to `{0}' which is the argument to a using or lock statement",
6559 					Name);
6560 			}
6561 
6562 			return this;
6563 		}
6564 
Emit(EmitContext ec)6565 		public override void Emit (EmitContext ec)
6566 		{
6567 			Emit (ec, false);
6568 		}
6569 
EmitSideEffect(EmitContext ec)6570 		public override void EmitSideEffect (EmitContext ec)
6571 		{
6572 			// do nothing
6573 		}
6574 
6575 		//
6576 		// This method is used by parameters that are references, that are
6577 		// being passed as references:  we only want to pass the pointer (that
6578 		// is already stored in the parameter, not the address of the pointer,
6579 		// and not the value of the variable).
6580 		//
EmitLoad(EmitContext ec)6581 		public void EmitLoad (EmitContext ec)
6582 		{
6583 			Variable.Emit (ec);
6584 		}
6585 
Emit(EmitContext ec, bool leave_copy)6586 		public void Emit (EmitContext ec, bool leave_copy)
6587 		{
6588 			HoistedVariable hv = GetHoistedVariable (ec);
6589 			if (hv != null) {
6590 				hv.Emit (ec, leave_copy);
6591 				return;
6592 			}
6593 
6594 			EmitLoad (ec);
6595 
6596 			if (IsRef) {
6597 				//
6598 				// If we are a reference, we loaded on the stack a pointer
6599 				// Now lets load the real value
6600 				//
6601 				ec.EmitLoadFromPtr (type);
6602 			}
6603 
6604 			if (leave_copy) {
6605 				ec.Emit (OpCodes.Dup);
6606 
6607 				if (IsRef) {
6608 					temp = new LocalTemporary (Type);
6609 					temp.Store (ec);
6610 				}
6611 			}
6612 		}
6613 
EmitAssign(EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)6614 		public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
6615 					bool prepare_for_load)
6616 		{
6617 			HoistedVariable hv = GetHoistedVariable (ec);
6618 			if (hv != null) {
6619 				hv.EmitAssign (ec, source, leave_copy, prepare_for_load);
6620 				return;
6621 			}
6622 
6623 			bool dereference = IsRef && !(source is ReferenceExpression);
6624 			New n_source = source as New;
6625 			if (n_source != null && n_source.CanEmitOptimizedLocalTarget (ec)) {
6626 				if (!n_source.Emit (ec, this)) {
6627 					if (leave_copy) {
6628 						EmitLoad (ec);
6629 						if (dereference)
6630 							ec.EmitLoadFromPtr (type);
6631 					}
6632 					return;
6633 				}
6634 			} else {
6635 				if (dereference)
6636 					EmitLoad (ec);
6637 
6638 				source.Emit (ec);
6639 			}
6640 
6641 			if (leave_copy) {
6642 				ec.Emit (OpCodes.Dup);
6643 				if (dereference) {
6644 					temp = new LocalTemporary (Type);
6645 					temp.Store (ec);
6646 				}
6647 			}
6648 
6649 			if (dereference)
6650 				ec.EmitStoreFromPtr (type);
6651 			else
6652 				Variable.EmitAssign (ec);
6653 
6654 			if (temp != null) {
6655 				temp.Emit (ec);
6656 				temp.Release (ec);
6657 			}
6658 		}
6659 
EmitToField(EmitContext ec)6660 		public override Expression EmitToField (EmitContext ec)
6661 		{
6662 			HoistedVariable hv = GetHoistedVariable (ec);
6663 			if (hv != null) {
6664 				return hv.EmitToField (ec);
6665 			}
6666 
6667 			return base.EmitToField (ec);
6668 		}
6669 
GetHoistedVariable(ResolveContext rc)6670 		public HoistedVariable GetHoistedVariable (ResolveContext rc)
6671 		{
6672 			return GetHoistedVariable (rc.CurrentAnonymousMethod);
6673 		}
6674 
GetHoistedVariable(EmitContext ec)6675 		public HoistedVariable GetHoistedVariable (EmitContext ec)
6676 		{
6677 			return GetHoistedVariable (ec.CurrentAnonymousMethod);
6678 		}
6679 
GetSignatureForError()6680 		public override string GetSignatureForError ()
6681 		{
6682 			return Name;
6683 		}
6684 
6685 		public bool IsHoisted {
6686 			get { return GetHoistedVariable ((AnonymousExpression) null) != null; }
6687 		}
6688 	}
6689 
6690 	//
6691 	// Resolved reference to a local variable
6692 	//
6693 	public class LocalVariableReference : VariableReference
6694 	{
6695 		public LocalVariable local_info;
6696 
LocalVariableReference(LocalVariable li, Location l)6697 		public LocalVariableReference (LocalVariable li, Location l)
6698 		{
6699 			this.local_info = li;
6700 			loc = l;
6701 		}
6702 
6703 		public override VariableInfo VariableInfo {
6704 			get { return local_info.VariableInfo; }
6705 		}
6706 
GetHoistedVariable(AnonymousExpression ae)6707 		public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
6708 		{
6709 			return local_info.HoistedVariant;
6710 		}
6711 
6712 		#region Properties
6713 
6714 		//
6715 		// A local variable is always fixed
6716 		//
6717 		public override bool IsFixed {
6718 			get {
6719 				return true;
6720 			}
6721 		}
6722 
6723 		public override bool IsLockedByStatement {
6724 			get {
6725 				return local_info.IsLocked;
6726 			}
6727 			set {
6728 				local_info.IsLocked = value;
6729 			}
6730 		}
6731 
6732 		public override bool IsRef {
6733 			get { return local_info.IsByRef; }
6734 		}
6735 
6736 		public override string Name {
6737 			get { return local_info.Name; }
6738 		}
6739 
6740 		#endregion
6741 
FlowAnalysis(FlowAnalysisContext fc)6742 		public override void FlowAnalysis (FlowAnalysisContext fc)
6743 		{
6744 			VariableInfo variable_info = VariableInfo;
6745 			if (variable_info == null)
6746 				return;
6747 
6748 			if (fc.IsDefinitelyAssigned (variable_info))
6749 				return;
6750 
6751 			fc.Report.Error (165, loc, "Use of unassigned local variable `{0}'", Name);
6752 			variable_info.SetAssigned (fc.DefiniteAssignment, true);
6753 		}
6754 
SetHasAddressTaken()6755 		public override void SetHasAddressTaken ()
6756 		{
6757 			local_info.SetHasAddressTaken ();
6758 		}
6759 
DoResolveBase(ResolveContext ec)6760 		void DoResolveBase (ResolveContext ec)
6761 		{
6762 			eclass = ExprClass.Variable;
6763 			type = local_info.Type;
6764 
6765 			//
6766 			// If we are referencing a variable from the external block
6767 			// flag it for capturing
6768 			//
6769 			if (ec.MustCaptureVariable (local_info)) {
6770 				if (local_info.AddressTaken) {
6771 					AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, this, loc);
6772 				} else if (local_info.IsFixed) {
6773 					ec.Report.Error (1764, loc,
6774 						"Cannot use fixed variable `{0}' inside an anonymous method, lambda expression or query expression",
6775 						GetSignatureForError ());
6776 				} else if (local_info.IsByRef || local_info.Type.IsByRefLike) {
6777 					if (ec.CurrentAnonymousMethod is StateMachineInitializer) {
6778 						// It's reported later as 4012/4013
6779 					} else {
6780 						ec.Report.Error (8175, loc,
6781 							"Cannot use by-reference variable `{0}' inside an anonymous method, lambda expression, or query expression",
6782 							GetSignatureForError ());
6783 					}
6784 				}
6785 
6786 				if (ec.IsVariableCapturingRequired) {
6787 					AnonymousMethodStorey storey = local_info.Block.Explicit.CreateAnonymousMethodStorey (ec);
6788 					storey.CaptureLocalVariable (ec, local_info);
6789 				}
6790 			}
6791 		}
6792 
DoResolve(ResolveContext ec)6793 		protected override Expression DoResolve (ResolveContext ec)
6794 		{
6795 			local_info.SetIsUsed ();
6796 
6797 			DoResolveBase (ec);
6798 
6799 			if (local_info.Type == InternalType.VarOutType) {
6800 				ec.Report.Error (8048, loc, "Cannot use uninitialized variable `{0}'",
6801 					GetSignatureForError ());
6802 
6803 				type = InternalType.ErrorType;
6804 			}
6805 
6806 			return this;
6807 		}
6808 
DoResolveLValue(ResolveContext ec, Expression rhs)6809 		public override Expression DoResolveLValue (ResolveContext ec, Expression rhs)
6810 		{
6811 			//
6812 			// Don't be too pedantic when variable is used as out param or for some broken code
6813 			// which uses property/indexer access to run some initialization
6814 			//
6815 			if (rhs == EmptyExpression.OutAccess || rhs.eclass == ExprClass.PropertyAccess || rhs.eclass == ExprClass.IndexerAccess)
6816 				local_info.SetIsUsed ();
6817 
6818 			if (local_info.IsReadonly && !ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.UsingInitializerScope)) {
6819 				if (local_info.IsByRef) {
6820 					// OK because it cannot be reassigned
6821 				} else if (rhs == EmptyExpression.LValueMemberAccess) {
6822 					// CS1654 already reported
6823 				} else {
6824 					int code;
6825 					string msg;
6826 					if (rhs == EmptyExpression.OutAccess) {
6827 						code = 1657; msg = "Cannot pass `{0}' as a ref or out argument because it is a `{1}'";
6828 					} else if (rhs == EmptyExpression.LValueMemberOutAccess) {
6829 						code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'";
6830 					} else if (rhs == EmptyExpression.UnaryAddress) {
6831 						code = 459; msg = "Cannot take the address of {1} `{0}'";
6832 					} else {
6833 						code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'";
6834 					}
6835 					ec.Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ());
6836 				}
6837 			}
6838 
6839 			if (eclass == ExprClass.Unresolved)
6840 				DoResolveBase (ec);
6841 
6842 			return base.DoResolveLValue (ec, rhs);
6843 		}
6844 
GetHashCode()6845 		public override int GetHashCode ()
6846 		{
6847 			return local_info.GetHashCode ();
6848 		}
6849 
Equals(object obj)6850 		public override bool Equals (object obj)
6851 		{
6852 			LocalVariableReference lvr = obj as LocalVariableReference;
6853 			if (lvr == null)
6854 				return false;
6855 
6856 			return local_info == lvr.local_info;
6857 		}
6858 
6859 		protected override ILocalVariable Variable {
6860 			get { return local_info; }
6861 		}
6862 
ToString()6863 		public override string ToString ()
6864 		{
6865 			return String.Format ("{0} ({1}:{2})", GetType (), Name, loc);
6866 		}
6867 
CloneTo(CloneContext clonectx, Expression t)6868 		protected override void CloneTo (CloneContext clonectx, Expression t)
6869 		{
6870 			// Nothing
6871 		}
6872 	}
6873 
6874 	/// <summary>
6875 	///   This represents a reference to a parameter in the intermediate
6876 	///   representation.
6877 	/// </summary>
6878 	public class ParameterReference : VariableReference
6879 	{
6880 		protected ParametersBlock.ParameterInfo pi;
6881 
ParameterReference(ParametersBlock.ParameterInfo pi, Location loc)6882 		public ParameterReference (ParametersBlock.ParameterInfo pi, Location loc)
6883 		{
6884 			this.pi = pi;
6885 			this.loc = loc;
6886 		}
6887 
6888 		#region Properties
6889 
6890 		public override bool IsLockedByStatement {
6891 			get {
6892 				return pi.IsLocked;
6893 			}
6894 			set	{
6895 				pi.IsLocked = value;
6896 			}
6897 		}
6898 
6899 		public override bool IsRef {
6900 			get { return (pi.Parameter.ModFlags & Parameter.Modifier.RefOutMask) != 0; }
6901 		}
6902 
6903 		bool HasOutModifier {
6904 			get { return (pi.Parameter.ModFlags & Parameter.Modifier.OUT) != 0; }
6905 		}
6906 
GetHoistedVariable(AnonymousExpression ae)6907 		public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
6908 		{
6909 			return pi.Parameter.HoistedVariant;
6910 		}
6911 
6912 		//
6913 		// A ref or out parameter is classified as a moveable variable, even
6914 		// if the argument given for the parameter is a fixed variable
6915 		//
6916 		public override bool IsFixed {
6917 			get { return !IsRef; }
6918 		}
6919 
6920 		public override string Name {
6921 			get { return Parameter.Name; }
6922 		}
6923 
6924 		public Parameter Parameter {
6925 			get { return pi.Parameter; }
6926 		}
6927 
6928 		public override VariableInfo VariableInfo {
6929 			get { return pi.VariableInfo; }
6930 		}
6931 
6932 		protected override ILocalVariable Variable {
6933 			get { return Parameter; }
6934 		}
6935 
6936 		#endregion
6937 
AddressOf(EmitContext ec, AddressOp mode)6938 		public override void AddressOf (EmitContext ec, AddressOp mode)
6939 		{
6940 			//
6941 			// ParameterReferences might already be a reference
6942 			//
6943 			if (IsRef) {
6944 				EmitLoad (ec);
6945 				return;
6946 			}
6947 
6948 			base.AddressOf (ec, mode);
6949 		}
6950 
SetHasAddressTaken()6951 		public override void SetHasAddressTaken ()
6952 		{
6953 			Parameter.HasAddressTaken = true;
6954 		}
6955 
DoResolveBase(ResolveContext ec)6956 		bool DoResolveBase (ResolveContext ec)
6957 		{
6958 			if (eclass != ExprClass.Unresolved)
6959 				return true;
6960 
6961 			type = pi.ParameterType;
6962 			eclass = ExprClass.Variable;
6963 
6964 			//
6965 			// If we are referencing a parameter from the external block
6966 			// flag it for capturing
6967 			//
6968 			if (ec.MustCaptureVariable (pi)) {
6969 				if (Parameter.HasAddressTaken)
6970 					AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, this, loc);
6971 
6972 				if (IsRef) {
6973 					ec.Report.Error (1628, loc,
6974 						"Parameter `{0}' cannot be used inside `{1}' when using `ref' or `out' modifier",
6975 						Name, ec.CurrentAnonymousMethod.ContainerType);
6976 				}
6977 
6978 				if (ec.IsVariableCapturingRequired && !pi.Block.ParametersBlock.IsExpressionTree) {
6979 					AnonymousMethodStorey storey = pi.Block.Explicit.CreateAnonymousMethodStorey (ec);
6980 					storey.CaptureParameter (ec, pi, this);
6981 				}
6982 			}
6983 
6984 			return true;
6985 		}
6986 
GetHashCode()6987 		public override int GetHashCode ()
6988 		{
6989 			return Name.GetHashCode ();
6990 		}
6991 
Equals(object obj)6992 		public override bool Equals (object obj)
6993 		{
6994 			ParameterReference pr = obj as ParameterReference;
6995 			if (pr == null)
6996 				return false;
6997 
6998 			return Name == pr.Name;
6999 		}
7000 
CloneTo(CloneContext clonectx, Expression target)7001 		protected override void CloneTo (CloneContext clonectx, Expression target)
7002 		{
7003 			// Nothing to clone
7004 			return;
7005 		}
7006 
CreateExpressionTree(ResolveContext ec)7007 		public override Expression CreateExpressionTree (ResolveContext ec)
7008 		{
7009 			HoistedVariable hv = GetHoistedVariable (ec);
7010 			if (hv != null)
7011 				return hv.CreateExpressionTree ();
7012 
7013 			return Parameter.ExpressionTreeVariableReference ();
7014 		}
7015 
DoResolve(ResolveContext ec)7016 		protected override Expression DoResolve (ResolveContext ec)
7017 		{
7018 			if (!DoResolveBase (ec))
7019 				return null;
7020 
7021 			return this;
7022 		}
7023 
DoResolveLValue(ResolveContext ec, Expression right_side)7024 		public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
7025 		{
7026 			if (!DoResolveBase (ec))
7027 				return null;
7028 
7029 			if (Parameter.HoistedVariant != null)
7030 				Parameter.HoistedVariant.IsAssigned = true;
7031 
7032 			return base.DoResolveLValue (ec, right_side);
7033 		}
7034 
FlowAnalysis(FlowAnalysisContext fc)7035 		public override void FlowAnalysis (FlowAnalysisContext fc)
7036 		{
7037 			VariableInfo variable_info = VariableInfo;
7038 			if (variable_info == null)
7039 				return;
7040 
7041 			if (fc.IsDefinitelyAssigned (variable_info))
7042 				return;
7043 
7044 			fc.Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name);
7045 			fc.SetVariableAssigned (variable_info);
7046 		}
7047 	}
7048 
7049 	/// <summary>
7050 	///   Invocation of methods or delegates.
7051 	/// </summary>
7052 	public class Invocation : ExpressionStatement
7053 	{
7054 		public class Predefined : Invocation
7055 		{
Predefined(MethodGroupExpr expr, Arguments arguments)7056 			public Predefined (MethodGroupExpr expr, Arguments arguments)
7057 				: base (expr, arguments)
7058 			{
7059 				this.mg = expr;
7060 			}
7061 
DoResolveOverload(ResolveContext rc)7062 			protected override MethodGroupExpr DoResolveOverload (ResolveContext rc)
7063 			{
7064 				mg.BestCandidate.CheckObsoleteness (rc, loc);
7065 
7066 				return mg;
7067 			}
7068 		}
7069 
7070 		protected Arguments arguments;
7071 		protected Expression expr;
7072 		protected MethodGroupExpr mg;
7073 		bool conditional_access_receiver;
7074 
Invocation(Expression expr, Arguments arguments)7075 		public Invocation (Expression expr, Arguments arguments)
7076 		{
7077 			this.expr = expr;
7078 			this.arguments = arguments;
7079 			if (expr != null) {
7080 				loc = expr.Location;
7081 			}
7082 		}
7083 
7084 		#region Properties
7085 		public Arguments Arguments {
7086 			get {
7087 				return arguments;
7088 			}
7089 		}
7090 
7091 		public Expression Exp {
7092 			get {
7093 				return expr;
7094 			}
7095 		}
7096 
7097 		public MethodGroupExpr MethodGroup {
7098 			get {
7099 				return mg;
7100 			}
7101 		}
7102 
7103 		public override Location StartLocation {
7104 			get {
7105 				return expr.StartLocation;
7106 			}
7107 		}
7108 
7109 		#endregion
7110 
CanReduceLambda(AnonymousMethodBody body)7111 		public override MethodGroupExpr CanReduceLambda (AnonymousMethodBody body)
7112 		{
7113 			if (MethodGroup == null)
7114 				return null;
7115 
7116 			var candidate = MethodGroup.BestCandidate;
7117 			if (candidate == null || !(candidate.IsStatic || Exp is This))
7118 				return null;
7119 
7120 			var args_count = arguments == null ? 0 : arguments.Count;
7121 			if (args_count != body.Parameters.Count)
7122 				return null;
7123 
7124 			var lambda_parameters = body.Block.Parameters.FixedParameters;
7125 			for (int i = 0; i < args_count; ++i) {
7126 				var pr = arguments[i].Expr as ParameterReference;
7127 				if (pr == null)
7128 					return null;
7129 
7130 				if (lambda_parameters[i] != pr.Parameter)
7131 					return null;
7132 
7133 				if ((lambda_parameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (pr.Parameter.ModFlags & Parameter.Modifier.RefOutMask))
7134 					return null;
7135 			}
7136 
7137 			var emg = MethodGroup as ExtensionMethodGroupExpr;
7138 			if (emg != null) {
7139 				var mg = MethodGroupExpr.CreatePredefined (candidate, candidate.DeclaringType, MethodGroup.Location);
7140 				if (candidate.IsGeneric) {
7141 					var targs = new TypeExpression [candidate.Arity];
7142 					for (int i = 0; i < targs.Length; ++i) {
7143 						targs[i] = new TypeExpression (candidate.TypeArguments[i], MethodGroup.Location);
7144 					}
7145 
7146 					mg.SetTypeArguments (null, new TypeArguments (targs));
7147 				}
7148 
7149 				return mg;
7150 			}
7151 
7152 			return MethodGroup;
7153 		}
7154 
CloneTo(CloneContext clonectx, Expression t)7155 		protected override void CloneTo (CloneContext clonectx, Expression t)
7156 		{
7157 			Invocation target = (Invocation) t;
7158 
7159 			if (arguments != null)
7160 				target.arguments = arguments.Clone (clonectx);
7161 
7162 			target.expr = expr.Clone (clonectx);
7163 		}
7164 
ContainsEmitWithAwait()7165 		public override bool ContainsEmitWithAwait ()
7166 		{
7167 			if (arguments != null && arguments.ContainsEmitWithAwait ())
7168 				return true;
7169 
7170 			return mg.ContainsEmitWithAwait ();
7171 		}
7172 
CreateExpressionTree(ResolveContext ec)7173 		public override Expression CreateExpressionTree (ResolveContext ec)
7174 		{
7175 			Expression instance = mg.IsInstance ?
7176 				mg.InstanceExpression.CreateExpressionTree (ec) :
7177 				new NullLiteral (loc);
7178 
7179 			var args = Arguments.CreateForExpressionTree (ec, arguments,
7180 				instance,
7181 				mg.CreateExpressionTree (ec));
7182 
7183 			return CreateExpressionFactoryCall (ec, "Call", args);
7184 		}
7185 
ResolveConditionalAccessReceiver(ResolveContext rc)7186 		void ResolveConditionalAccessReceiver (ResolveContext rc)
7187 		{
7188 			if (!rc.HasSet (ResolveContext.Options.DontSetConditionalAccessReceiver) && expr.HasConditionalAccess ()) {
7189 				conditional_access_receiver = true;
7190 			}
7191 		}
7192 
7193 		bool statement_resolve;
ResolveStatement(BlockContext bc)7194 		public override ExpressionStatement ResolveStatement (BlockContext bc)
7195 		{
7196 			statement_resolve = true;
7197 			var es = base.ResolveStatement (bc);
7198 			statement_resolve = false;
7199 
7200 			return es;
7201 		}
7202 
DoResolve(ResolveContext rc)7203 		protected override Expression DoResolve (ResolveContext rc)
7204 		{
7205 			ResolveConditionalAccessReceiver (rc);
7206 			return DoResolveInvocation (rc, null);
7207 		}
7208 
DoResolveLValue(ResolveContext rc, Expression right_side)7209 		public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
7210 		{
7211 			var sn = expr as SimpleName;
7212 			if (sn != null && sn.Name == "var" && sn.Arity == 0 && arguments?.Count > 1) {
7213 				var variables = new List<BlockVariable> (arguments.Count);
7214 				foreach (var arg in arguments) {
7215 					var arg_sn = arg.Expr as SimpleName;
7216 					if (arg_sn == null || arg_sn.Arity != 0) {
7217 						rc.Report.Error (8199, loc, "The syntax `var (...)' as an lvalue is reserved");
7218 						return ErrorExpression.Instance;
7219 					}
7220 
7221 					var lv = new LocalVariable (rc.CurrentBlock, arg_sn.Name, arg.Expr.Location);
7222 					rc.CurrentBlock.AddLocalName (lv);
7223 					variables.Add (new BlockVariable (new VarExpr (lv.Location), lv));
7224 				}
7225 
7226 				var res = new TupleDeconstruct (variables, right_side, loc);
7227 				return res.Resolve (rc);
7228 			}
7229 
7230 			if (right_side != null) {
7231 				if (eclass != ExprClass.Unresolved)
7232 					return this;
7233 
7234 				var res = DoResolveInvocation (rc, right_side);
7235 				if (res == null)
7236 					return null;
7237 
7238 				return res;
7239 			}
7240 
7241 			return base.DoResolveLValue (rc, right_side);
7242 		}
7243 
DoResolveInvocation(ResolveContext ec, Expression rhs)7244 		Expression DoResolveInvocation (ResolveContext ec, Expression rhs)
7245 		{
7246 			Expression member_expr;
7247 			var atn = expr as ATypeNameExpression;
7248 
7249 			var flags = default (ResolveContext.FlagsHandle);
7250 			if (conditional_access_receiver)
7251 				flags = ec.Set (ResolveContext.Options.DontSetConditionalAccessReceiver);
7252 
7253 			if (atn != null) {
7254 				member_expr = atn.LookupNameExpression (ec, MemberLookupRestrictions.InvocableOnly | MemberLookupRestrictions.ReadAccess);
7255 				if (member_expr != null) {
7256 					var name_of = member_expr as NameOf;
7257 					if (name_of != null) {
7258 						return name_of.ResolveOverload (ec, arguments);
7259 					}
7260 
7261 					member_expr = member_expr.Resolve (ec);
7262 				}
7263 			} else {
7264 				member_expr = expr.Resolve (ec);
7265 			}
7266 
7267 			if (conditional_access_receiver)
7268 				flags.Dispose ();
7269 
7270 			if (member_expr == null)
7271 				return null;
7272 
7273 			//
7274 			// Next, evaluate all the expressions in the argument list
7275 			//
7276 			bool dynamic_arg = false;
7277 			if (arguments != null) {
7278 				using (ec.With (ResolveContext.Options.DontSetConditionalAccessReceiver, false)) {
7279 					arguments.Resolve (ec, out dynamic_arg);
7280 				}
7281 			}
7282 
7283 			TypeSpec expr_type = member_expr.Type;
7284 			if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
7285 				return DoResolveDynamic (ec, member_expr);
7286 
7287 			mg = member_expr as MethodGroupExpr;
7288 			Expression invoke = null;
7289 
7290 			if (mg == null) {
7291 				if (expr_type != null && expr_type.IsDelegate) {
7292 					invoke = new DelegateInvocation (member_expr, arguments, conditional_access_receiver, loc);
7293 					invoke = invoke.Resolve (ec);
7294 					if (invoke == null || !dynamic_arg)
7295 						return invoke;
7296 				} else {
7297 					if (member_expr is RuntimeValueExpression) {
7298 						ec.Report.Error (Report.RuntimeErrorId, loc, "Cannot invoke a non-delegate type `{0}'",
7299 							member_expr.Type.GetSignatureForError ());
7300 						return null;
7301 					}
7302 
7303 					MemberExpr me = member_expr as MemberExpr;
7304 					if (me == null) {
7305 						member_expr.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup, loc);
7306 						return null;
7307 					}
7308 
7309 					ec.Report.Error (1955, loc, "The member `{0}' cannot be used as method or delegate",
7310 							member_expr.GetSignatureForError ());
7311 					return null;
7312 				}
7313 			}
7314 
7315 			if (invoke == null) {
7316 				mg = DoResolveOverload (ec);
7317 				if (mg == null)
7318 					return null;
7319 			}
7320 
7321 			if (dynamic_arg)
7322 				return DoResolveDynamic (ec, member_expr);
7323 
7324 			var method = mg.BestCandidate;
7325 			type = mg.BestCandidateReturnType;
7326 			if (conditional_access_receiver && !statement_resolve)
7327 				type = LiftMemberType (ec, type);
7328 
7329 			if (arguments == null && method.DeclaringType.BuiltinType == BuiltinTypeSpec.Type.Object && method.Name == Destructor.MetadataName) {
7330 				if (mg.IsBase)
7331 					ec.Report.Error (250, loc, "Do not directly call your base class Finalize method. It is called automatically from your destructor");
7332 				else
7333 					ec.Report.Error (245, loc, "Destructors and object.Finalize cannot be called directly. Consider calling IDisposable.Dispose if available");
7334 				return null;
7335 			}
7336 
7337 			IsSpecialMethodInvocation (ec, method, loc);
7338 
7339 			eclass = ExprClass.Value;
7340 
7341 			if (type.Kind == MemberKind.ByRef && rhs != EmptyExpression.OutAccess)
7342 				return ByRefDereference.Create (this).Resolve (ec);
7343 
7344 			return this;
7345 		}
7346 
DoResolveDynamic(ResolveContext ec, Expression memberExpr)7347 		protected virtual Expression DoResolveDynamic (ResolveContext ec, Expression memberExpr)
7348 		{
7349 			Arguments args;
7350 			DynamicMemberBinder dmb = memberExpr as DynamicMemberBinder;
7351 			if (dmb != null) {
7352 				args = dmb.Arguments;
7353 				if (arguments != null)
7354 					args.AddRange (arguments);
7355 			} else if (mg == null) {
7356 				if (arguments == null)
7357 					args = new Arguments (1);
7358 				else
7359 					args = arguments;
7360 
7361 				args.Insert (0, new Argument (memberExpr));
7362 				this.expr = null;
7363 			} else {
7364 				if (mg.IsBase) {
7365 					ec.Report.Error (1971, loc,
7366 						"The base call to method `{0}' cannot be dynamically dispatched. Consider casting the dynamic arguments or eliminating the base access",
7367 						mg.Name);
7368 					return null;
7369 				}
7370 
7371 				if (arguments == null)
7372 					args = new Arguments (1);
7373 				else
7374 					args = arguments;
7375 
7376 				MemberAccess ma = expr as MemberAccess;
7377 				if (ma != null) {
7378 					var inst = mg.InstanceExpression;
7379 					var left_type = inst as TypeExpr;
7380 					if (left_type != null) {
7381 						args.Insert (0, new Argument (new TypeOf (left_type.Type, loc).Resolve (ec), Argument.AType.DynamicTypeName));
7382 					} else if (inst != null) {
7383 						//
7384 						// Any value type has to be pass as by-ref to get back the same
7385 						// instance on which the member was called
7386 						//
7387 						var mod = inst is IMemoryLocation && TypeSpec.IsValueType (inst.Type) ?
7388 							Argument.AType.Ref : Argument.AType.None;
7389 						args.Insert (0, new Argument (inst.Resolve (ec), mod));
7390 					}
7391 				} else {	// is SimpleName
7392 					if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer)) {
7393 						args.Insert (0, new Argument (new TypeOf (ec.CurrentType, loc).Resolve (ec), Argument.AType.DynamicTypeName));
7394 					} else {
7395 						args.Insert (0, new Argument (new This (loc).Resolve (ec)));
7396 					}
7397 				}
7398 			}
7399 
7400 			return new DynamicInvocation (expr as ATypeNameExpression, args, conditional_access_receiver, loc).Resolve (ec);
7401 		}
7402 
DoResolveOverload(ResolveContext ec)7403 		protected virtual MethodGroupExpr DoResolveOverload (ResolveContext ec)
7404 		{
7405 			return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.None);
7406 		}
7407 
FlowAnalysis(FlowAnalysisContext fc)7408 		public override void FlowAnalysis (FlowAnalysisContext fc)
7409 		{
7410 			if (mg.IsConditionallyExcluded)
7411 				return;
7412 
7413 			var da = conditional_access_receiver ? fc.BranchDefiniteAssignment () : null;
7414 
7415   			mg.FlowAnalysis (fc);
7416 
7417 			if (arguments != null)
7418 				arguments.FlowAnalysis (fc);
7419 
7420 			if (conditional_access_receiver)
7421 				fc.DefiniteAssignment = da;
7422 		}
7423 
GetSignatureForError()7424 		public override string GetSignatureForError ()
7425 		{
7426 			return mg.GetSignatureForError ();
7427 		}
7428 
HasConditionalAccess()7429 		public override bool HasConditionalAccess ()
7430 		{
7431 			return expr.HasConditionalAccess ();
7432 		}
7433 
7434 		//
7435 		// If a member is a method or event, or if it is a constant, field or property of either a delegate type
7436 		// or the type dynamic, then the member is invocable
7437 		//
IsMemberInvocable(MemberSpec member)7438 		public static bool IsMemberInvocable (MemberSpec member)
7439 		{
7440 			switch (member.Kind) {
7441 			case MemberKind.Event:
7442 				return true;
7443 			case MemberKind.Field:
7444 			case MemberKind.Property:
7445 				var m = member as IInterfaceMemberSpec;
7446 				return m.MemberType.IsDelegate || m.MemberType.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
7447 			default:
7448 				return false;
7449 			}
7450 		}
7451 
IsSpecialMethodInvocation(ResolveContext ec, MethodSpec method, Location loc)7452 		public static bool IsSpecialMethodInvocation (ResolveContext ec, MethodSpec method, Location loc)
7453 		{
7454 			if (!method.IsReservedMethod)
7455 				return false;
7456 
7457 			if (ec.HasSet (ResolveContext.Options.InvokeSpecialName) || ec.CurrentMemberDefinition.IsCompilerGenerated)
7458 				return false;
7459 
7460 			ec.Report.SymbolRelatedToPreviousError (method);
7461 			ec.Report.Error (571, loc, "`{0}': cannot explicitly call operator or accessor",
7462 				method.GetSignatureForError ());
7463 
7464 			return true;
7465 		}
7466 
Emit(EmitContext ec)7467 		public override void Emit (EmitContext ec)
7468 		{
7469 			if (mg.IsConditionallyExcluded)
7470 				return;
7471 
7472 			if (conditional_access_receiver)
7473 				mg.EmitCall (ec, arguments, type, false);
7474 			else
7475 				mg.EmitCall (ec, arguments, false);
7476 		}
7477 
EmitPrepare(EmitContext ec)7478 		public override void EmitPrepare (EmitContext ec)
7479 		{
7480 			mg.EmitPrepare (ec);
7481 
7482 			arguments?.EmitPrepare (ec);
7483 		}
7484 
EmitStatement(EmitContext ec)7485 		public override void EmitStatement (EmitContext ec)
7486 		{
7487 			if (mg.IsConditionallyExcluded)
7488 				return;
7489 
7490 			if (conditional_access_receiver)
7491 				mg.EmitCall (ec, arguments, type, true);
7492 			else
7493 				mg.EmitCall (ec, arguments, true);
7494 		}
7495 
MakeExpression(BuilderContext ctx)7496 		public override SLE.Expression MakeExpression (BuilderContext ctx)
7497 		{
7498 			return MakeExpression (ctx, mg.InstanceExpression, mg.BestCandidate, arguments);
7499 		}
7500 
MakeExpression(BuilderContext ctx, Expression instance, MethodSpec mi, Arguments args)7501 		public static SLE.Expression MakeExpression (BuilderContext ctx, Expression instance, MethodSpec mi, Arguments args)
7502 		{
7503 #if STATIC
7504 			throw new NotSupportedException ();
7505 #else
7506 			var instance_expr = instance == null ? null : instance.MakeExpression (ctx);
7507 			return SLE.Expression.Call (instance_expr, (MethodInfo) mi.GetMetaInfo (), Arguments.MakeExpression (args, ctx));
7508 #endif
7509 		}
7510 
Accept(StructuralVisitor visitor)7511 		public override object Accept (StructuralVisitor visitor)
7512 		{
7513 			return visitor.Visit (this);
7514 		}
7515 	}
7516 
7517 	//
7518 	// Implements simple new expression
7519 	//
7520 	public class New : ExpressionStatement, IMemoryLocation
7521 	{
7522 		protected Arguments arguments;
7523 
7524 		//
7525 		// During bootstrap, it contains the RequestedType,
7526 		// but if `type' is not null, it *might* contain a NewDelegate
7527 		// (because of field multi-initialization)
7528 		//
7529 		protected Expression RequestedType;
7530 
7531 		protected MethodSpec method;
7532 
New(Expression requested_type, Arguments arguments, Location l)7533 		public New (Expression requested_type, Arguments arguments, Location l)
7534 		{
7535 			RequestedType = requested_type;
7536 			this.arguments = arguments;
7537 			loc = l;
7538 		}
7539 
7540 		#region Properties
7541 		public Arguments Arguments {
7542 			get {
7543 				return arguments;
7544 			}
7545 		}
7546 
7547 		//
7548 		// Returns true for resolved `new S()' when S does not declare parameterless constructor
7549 		//
7550 		public bool IsGeneratedStructConstructor {
7551 			get {
7552 				return arguments == null && method == null && type.IsStruct && GetType () == typeof (New);
7553 			}
7554 		}
7555 
7556 		public Expression TypeExpression {
7557 			get {
7558 				return RequestedType;
7559 			}
7560 		}
7561 
7562 		#endregion
7563 
7564 		/// <summary>
7565 		/// Converts complex core type syntax like 'new int ()' to simple constant
7566 		/// </summary>
Constantify(TypeSpec t, Location loc)7567 		public static Constant Constantify (TypeSpec t, Location loc)
7568 		{
7569 			switch (t.BuiltinType) {
7570 			case BuiltinTypeSpec.Type.Int:
7571 				return new IntConstant (t, 0, loc);
7572 			case BuiltinTypeSpec.Type.UInt:
7573 				return new UIntConstant (t, 0, loc);
7574 			case BuiltinTypeSpec.Type.Long:
7575 				return new LongConstant (t, 0, loc);
7576 			case BuiltinTypeSpec.Type.ULong:
7577 				return new ULongConstant (t, 0, loc);
7578 			case BuiltinTypeSpec.Type.Float:
7579 				return new FloatConstant (t, 0, loc);
7580 			case BuiltinTypeSpec.Type.Double:
7581 				return new DoubleConstant (t, 0, loc);
7582 			case BuiltinTypeSpec.Type.Short:
7583 				return new ShortConstant (t, 0, loc);
7584 			case BuiltinTypeSpec.Type.UShort:
7585 				return new UShortConstant (t, 0, loc);
7586 			case BuiltinTypeSpec.Type.SByte:
7587 				return new SByteConstant (t, 0, loc);
7588 			case BuiltinTypeSpec.Type.Byte:
7589 				return new ByteConstant (t, 0, loc);
7590 			case BuiltinTypeSpec.Type.Char:
7591 				return new CharConstant (t, '\0', loc);
7592 			case BuiltinTypeSpec.Type.Bool:
7593 				return new BoolConstant (t, false, loc);
7594 			case BuiltinTypeSpec.Type.Decimal:
7595 				return new DecimalConstant (t, 0, loc);
7596 			}
7597 
7598 			if (t.IsEnum)
7599 				return new EnumConstant (Constantify (EnumSpec.GetUnderlyingType (t), loc), t);
7600 
7601 			if (t.IsNullableType)
7602 				return Nullable.LiftedNull.Create (t, loc);
7603 
7604 			return null;
7605 		}
7606 
ContainsEmitWithAwait()7607 		public override bool ContainsEmitWithAwait ()
7608 		{
7609 			return arguments != null && arguments.ContainsEmitWithAwait ();
7610 		}
7611 
7612 		//
7613 		// Checks whether the type is an interface that has the
7614 		// [ComImport, CoClass] attributes and must be treated
7615 		// specially
7616 		//
CheckComImport(ResolveContext ec)7617 		public Expression CheckComImport (ResolveContext ec)
7618 		{
7619 			if (!type.IsInterface)
7620 				return null;
7621 
7622 			//
7623 			// Turn the call into:
7624 			// (the-interface-stated) (new class-referenced-in-coclassattribute ())
7625 			//
7626 			var real_class = type.MemberDefinition.GetAttributeCoClass ();
7627 			if (real_class == null)
7628 				return null;
7629 
7630 			New proxy = new New (new TypeExpression (real_class, loc), arguments, loc);
7631 			Cast cast = new Cast (new TypeExpression (type, loc), proxy, loc);
7632 			return cast.Resolve (ec);
7633 		}
7634 
CreateExpressionTree(ResolveContext ec)7635 		public override Expression CreateExpressionTree (ResolveContext ec)
7636 		{
7637 			Arguments args;
7638 			if (method == null) {
7639 				args = new Arguments (1);
7640 				args.Add (new Argument (new TypeOf (type, loc)));
7641 			} else {
7642 				args = Arguments.CreateForExpressionTree (ec,
7643 					arguments, new TypeOfMethod (method, loc));
7644 			}
7645 
7646 			return CreateExpressionFactoryCall (ec, "New", args);
7647 		}
7648 
DoResolve(ResolveContext ec)7649 		protected override Expression DoResolve (ResolveContext ec)
7650 		{
7651 			if (RequestedType is TupleTypeExpr) {
7652 				ec.Report.Error (8181, loc, "Tuple type cannot be used in an object creation expression. Use a tuple literal expression instead.");
7653 			}
7654 
7655 			type = RequestedType.ResolveAsType (ec);
7656 			if (type == null)
7657 				return null;
7658 
7659 			eclass = ExprClass.Value;
7660 
7661 			if (type.IsPointer) {
7662 				ec.Report.Error (1919, loc, "Unsafe type `{0}' cannot be used in an object creation expression",
7663 					type.GetSignatureForError ());
7664 				return null;
7665 			}
7666 
7667 			if (arguments == null) {
7668 				Constant c = Constantify (type, RequestedType.Location);
7669 				if (c != null)
7670 					return ReducedExpression.Create (c, this);
7671 			}
7672 
7673 			if (type.IsDelegate) {
7674 				return (new NewDelegate (type, arguments, loc)).Resolve (ec);
7675 			}
7676 
7677 			var tparam = type as TypeParameterSpec;
7678 			if (tparam != null) {
7679 				//
7680 				// Check whether the type of type parameter can be constructed. BaseType can be a struct for method overrides
7681 				// where type parameter constraint is inflated to struct
7682 				//
7683 				if ((tparam.SpecialConstraint & (SpecialConstraint.Struct | SpecialConstraint.Constructor)) == 0 && !TypeSpec.IsValueType (tparam)) {
7684 					ec.Report.Error (304, loc,
7685 						"Cannot create an instance of the variable type `{0}' because it does not have the new() constraint",
7686 						type.GetSignatureForError ());
7687 				}
7688 
7689 				if ((arguments != null) && (arguments.Count != 0)) {
7690 					ec.Report.Error (417, loc,
7691 						"`{0}': cannot provide arguments when creating an instance of a variable type",
7692 						type.GetSignatureForError ());
7693 				}
7694 
7695 				return this;
7696 			}
7697 
7698 			if (type.IsStatic) {
7699 				ec.Report.SymbolRelatedToPreviousError (type);
7700 				ec.Report.Error (712, loc, "Cannot create an instance of the static class `{0}'", type.GetSignatureForError ());
7701 				return null;
7702 			}
7703 
7704 			if (type.IsInterface || type.IsAbstract){
7705 				if (!TypeManager.IsGenericType (type)) {
7706 					RequestedType = CheckComImport (ec);
7707 					if (RequestedType != null)
7708 						return RequestedType;
7709 				}
7710 
7711 				ec.Report.SymbolRelatedToPreviousError (type);
7712 				ec.Report.Error (144, loc, "Cannot create an instance of the abstract class or interface `{0}'", type.GetSignatureForError ());
7713 				return null;
7714 			}
7715 
7716 			bool dynamic;
7717 			if (arguments != null) {
7718 				arguments.Resolve (ec, out dynamic);
7719 			} else {
7720 				dynamic = false;
7721 			}
7722 
7723 			method = ConstructorLookup (ec, type, ref arguments, loc);
7724 
7725 			if (dynamic) {
7726 				arguments.Insert (0, new Argument (new TypeOf (type, loc).Resolve (ec), Argument.AType.DynamicTypeName));
7727 				return new DynamicConstructorBinder (type, arguments, loc).Resolve (ec);
7728 			}
7729 
7730 			return this;
7731 		}
7732 
DoEmitTypeParameter(EmitContext ec)7733 		void DoEmitTypeParameter (EmitContext ec)
7734 		{
7735 			var m = ec.Module.PredefinedMembers.ActivatorCreateInstance.Resolve (loc);
7736 			if (m == null)
7737 				return;
7738 
7739 			var ctor_factory = m.MakeGenericMethod (ec.MemberContext, type);
7740 			ec.Emit (OpCodes.Call, ctor_factory);
7741 		}
7742 
7743 		//
7744 		// This Emit can be invoked in two contexts:
7745 		//    * As a mechanism that will leave a value on the stack (new object)
7746 		//    * As one that wont (init struct)
7747 		//
7748 		// If we are dealing with a ValueType, we have a few
7749 		// situations to deal with:
7750 		//
7751 		//    * The target is a ValueType, and we have been provided
7752 		//      the instance (this is easy, we are being assigned).
7753 		//
7754 		//    * The target of New is being passed as an argument,
7755 		//      to a boxing operation or a function that takes a
7756 		//      ValueType.
7757 		//
7758 		//      In this case, we need to create a temporary variable
7759 		//      that is the argument of New.
7760 		//
7761 		// Returns whether a value is left on the stack
7762 		//
7763 		// *** Implementation note ***
7764 		//
7765 		// To benefit from this optimization, each assignable expression
7766 		// has to manually cast to New and call this Emit.
7767 		//
7768 		// TODO: It's worth to implement it for arrays and fields
7769 		//
Emit(EmitContext ec, IMemoryLocation target)7770 		public virtual bool Emit (EmitContext ec, IMemoryLocation target)
7771 		{
7772 			bool is_value_type = type.IsStructOrEnum;
7773 			VariableReference vr = target as VariableReference;
7774 
7775 			bool prepare_await = ec.HasSet (BuilderContext.Options.AsyncBody) && arguments?.ContainsEmitWithAwait () == true;
7776 
7777 			if (target != null && is_value_type && (vr != null || method == null)) {
7778 				if (prepare_await) {
7779 					arguments = arguments.Emit (ec, false, true);
7780 					prepare_await = false;
7781 				}
7782 
7783 				target.AddressOf (ec, AddressOp.Store);
7784 			} else if (vr != null && vr.IsRef) {
7785 				vr.EmitLoad (ec);
7786 			}
7787 
7788 			if (arguments != null) {
7789 				if (prepare_await)
7790 					arguments = arguments.Emit (ec, false, true);
7791 
7792 				arguments.Emit (ec);
7793 			}
7794 
7795 			if (is_value_type) {
7796 				if (method == null) {
7797 					ec.Emit (OpCodes.Initobj, type);
7798 					return false;
7799 				}
7800 
7801 				if (vr != null) {
7802 					ec.MarkCallEntry (loc);
7803 					ec.Emit (OpCodes.Call, method);
7804 					return false;
7805 				}
7806 			}
7807 
7808 			if (type is TypeParameterSpec) {
7809 				DoEmitTypeParameter (ec);
7810 				return true;
7811 			}
7812 
7813 			ec.MarkCallEntry (loc);
7814 			ec.Emit (OpCodes.Newobj, method);
7815 			return true;
7816 		}
7817 
Emit(EmitContext ec)7818 		public override void Emit (EmitContext ec)
7819 		{
7820 			LocalTemporary v = null;
7821 			if (method == null && type.IsStructOrEnum) {
7822 				// TODO: Use temporary variable from pool
7823 				v = new LocalTemporary (type);
7824 			}
7825 
7826 			if (!Emit (ec, v))
7827 				v.Emit (ec);
7828 		}
7829 
EmitStatement(EmitContext ec)7830 		public override void EmitStatement (EmitContext ec)
7831 		{
7832 			LocalTemporary v = null;
7833 			if (method == null && TypeSpec.IsValueType (type)) {
7834 				// TODO: Use temporary variable from pool
7835 				v = new LocalTemporary (type);
7836 			}
7837 
7838 			if (Emit (ec, v))
7839 				ec.Emit (OpCodes.Pop);
7840 		}
7841 
CanEmitOptimizedLocalTarget(EmitContext ec)7842 		public virtual bool CanEmitOptimizedLocalTarget (EmitContext ec)
7843 		{
7844 			return true;
7845 		}
7846 
FlowAnalysis(FlowAnalysisContext fc)7847 		public override void FlowAnalysis (FlowAnalysisContext fc)
7848 		{
7849 			if (arguments != null)
7850 				arguments.FlowAnalysis (fc);
7851 		}
7852 
AddressOf(EmitContext ec, AddressOp mode)7853 		public void AddressOf (EmitContext ec, AddressOp mode)
7854 		{
7855 			EmitAddressOf (ec, mode);
7856 		}
7857 
EmitAddressOf(EmitContext ec, AddressOp mode)7858 		protected virtual IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp mode)
7859 		{
7860 			LocalTemporary value_target = new LocalTemporary (type);
7861 
7862 			if (type is TypeParameterSpec) {
7863 				DoEmitTypeParameter (ec);
7864 				value_target.Store (ec);
7865 				value_target.AddressOf (ec, mode);
7866 				return value_target;
7867 			}
7868 
7869 			value_target.AddressOf (ec, AddressOp.Store);
7870 
7871 			if (method == null) {
7872 				ec.Emit (OpCodes.Initobj, type);
7873 			} else {
7874 				if (arguments != null)
7875 					arguments.Emit (ec);
7876 
7877 				ec.Emit (OpCodes.Call, method);
7878 			}
7879 
7880 			value_target.AddressOf (ec, mode);
7881 			return value_target;
7882 		}
7883 
CloneTo(CloneContext clonectx, Expression t)7884 		protected override void CloneTo (CloneContext clonectx, Expression t)
7885 		{
7886 			New target = (New) t;
7887 
7888 			target.RequestedType = RequestedType.Clone (clonectx);
7889 			if (arguments != null){
7890 				target.arguments = arguments.Clone (clonectx);
7891 			}
7892 		}
7893 
MakeExpression(BuilderContext ctx)7894 		public override SLE.Expression MakeExpression (BuilderContext ctx)
7895 		{
7896 #if STATIC
7897 			return base.MakeExpression (ctx);
7898 #else
7899 			return SLE.Expression.New ((ConstructorInfo) method.GetMetaInfo (), Arguments.MakeExpression (arguments, ctx));
7900 #endif
7901 		}
7902 
Accept(StructuralVisitor visitor)7903 		public override object Accept (StructuralVisitor visitor)
7904 		{
7905 			return visitor.Visit (this);
7906 		}
7907 	}
7908 
7909 	//
7910 	// Array initializer expression, the expression is allowed in
7911 	// variable or field initialization only which makes it tricky as
7912 	// the type has to be infered based on the context either from field
7913 	// type or variable type (think of multiple declarators)
7914 	//
7915 	public class ArrayInitializer : Expression
7916 	{
7917 		List<Expression> elements;
7918 		BlockVariable variable;
7919 
ArrayInitializer(List<Expression> init, Location loc)7920 		public ArrayInitializer (List<Expression> init, Location loc)
7921 		{
7922 			elements = init;
7923 			this.loc = loc;
7924 		}
7925 
ArrayInitializer(int count, Location loc)7926 		public ArrayInitializer (int count, Location loc)
7927 			: this (new List<Expression> (count), loc)
7928 		{
7929 		}
7930 
ArrayInitializer(Location loc)7931 		public ArrayInitializer (Location loc)
7932 			: this (4, loc)
7933 		{
7934 		}
7935 
7936 		#region Properties
7937 
7938 		public int Count {
7939 			get { return elements.Count; }
7940 		}
7941 
7942 		public List<Expression> Elements {
7943 			get {
7944 				return elements;
7945 			}
7946 		}
7947 
7948 		public Expression this [int index] {
7949 			get {
7950 				return elements [index];
7951 			}
7952 		}
7953 
7954 		public BlockVariable VariableDeclaration {
7955 			get {
7956 				return variable;
7957 			}
7958 			set {
7959 				variable = value;
7960 			}
7961 		}
7962 
7963 		#endregion
7964 
Add(Expression expr)7965 		public void Add (Expression expr)
7966 		{
7967 			elements.Add (expr);
7968 		}
7969 
ContainsEmitWithAwait()7970 		public override bool ContainsEmitWithAwait ()
7971 		{
7972 			throw new NotSupportedException ();
7973 		}
7974 
CreateExpressionTree(ResolveContext ec)7975 		public override Expression CreateExpressionTree (ResolveContext ec)
7976 		{
7977 			throw new NotSupportedException ("ET");
7978 		}
7979 
CloneTo(CloneContext clonectx, Expression t)7980 		protected override void CloneTo (CloneContext clonectx, Expression t)
7981 		{
7982 			var target = (ArrayInitializer) t;
7983 
7984 			target.elements = new List<Expression> (elements.Count);
7985 			foreach (var element in elements)
7986 				target.elements.Add (element.Clone (clonectx));
7987 		}
7988 
DoResolve(ResolveContext rc)7989 		protected override Expression DoResolve (ResolveContext rc)
7990 		{
7991 			var current_field = rc.CurrentMemberDefinition as FieldBase;
7992 			TypeExpression type;
7993 			if (current_field != null && rc.CurrentAnonymousMethod == null) {
7994 				type = new TypeExpression (current_field.MemberType, current_field.Location);
7995 			} else if (variable != null) {
7996 				if (variable.TypeExpression is VarExpr) {
7997 					rc.Report.Error (820, loc, "An implicitly typed local variable declarator cannot use an array initializer");
7998 					return EmptyExpression.Null;
7999 				}
8000 
8001 				type = new TypeExpression (variable.Variable.Type, variable.Variable.Location);
8002 			} else {
8003 				throw new NotImplementedException ("Unexpected array initializer context");
8004 			}
8005 
8006 			return new ArrayCreation (type, this).Resolve (rc);
8007 		}
8008 
Emit(EmitContext ec)8009 		public override void Emit (EmitContext ec)
8010 		{
8011 			throw new InternalErrorException ("Missing Resolve call");
8012 		}
8013 
FlowAnalysis(FlowAnalysisContext fc)8014 		public override void FlowAnalysis (FlowAnalysisContext fc)
8015 		{
8016 			throw new InternalErrorException ("Missing Resolve call");
8017 		}
8018 
Accept(StructuralVisitor visitor)8019 		public override object Accept (StructuralVisitor visitor)
8020 		{
8021 			return visitor.Visit (this);
8022 		}
8023 	}
8024 
8025 	/// <summary>
8026 	///   14.5.10.2: Represents an array creation expression.
8027 	/// </summary>
8028 	///
8029 	/// <remarks>
8030 	///   There are two possible scenarios here: one is an array creation
8031 	///   expression that specifies the dimensions and optionally the
8032 	///   initialization data and the other which does not need dimensions
8033 	///   specified but where initialization data is mandatory.
8034 	/// </remarks>
8035 	public class ArrayCreation : Expression
8036 	{
8037 		FullNamedExpression requested_base_type;
8038 		ArrayInitializer initializers;
8039 
8040 		//
8041 		// The list of Argument types.
8042 		// This is used to construct the `newarray' or constructor signature
8043 		//
8044 		protected List<Expression> arguments;
8045 
8046 		protected TypeSpec array_element_type;
8047 		int num_arguments;
8048 		protected int dimensions;
8049 		protected readonly ComposedTypeSpecifier rank;
8050 		Expression first_emit;
8051 		LocalTemporary first_emit_temp;
8052 
8053 		protected List<Expression> array_data;
8054 
8055 		Dictionary<int, int> bounds;
8056 
8057 #if STATIC
8058 		// The number of constants in array initializers
8059 		int const_initializers_count;
8060 		bool only_constant_initializers;
8061 #endif
ArrayCreation(FullNamedExpression requested_base_type, List<Expression> exprs, ComposedTypeSpecifier rank, ArrayInitializer initializers, Location l)8062 		public ArrayCreation (FullNamedExpression requested_base_type, List<Expression> exprs, ComposedTypeSpecifier rank, ArrayInitializer initializers, Location l)
8063 			: this (requested_base_type, rank, initializers, l)
8064 		{
8065 			arguments = new List<Expression> (exprs);
8066 			num_arguments = arguments.Count;
8067 		}
8068 
8069 		//
8070 		// For expressions like int[] foo = new int[] { 1, 2, 3 };
8071 		//
ArrayCreation(FullNamedExpression requested_base_type, ComposedTypeSpecifier rank, ArrayInitializer initializers, Location loc)8072 		public ArrayCreation (FullNamedExpression requested_base_type, ComposedTypeSpecifier rank, ArrayInitializer initializers, Location loc)
8073 		{
8074 			this.requested_base_type = requested_base_type;
8075 			this.rank = rank;
8076 			this.initializers = initializers;
8077 			this.loc = loc;
8078 
8079 			if (rank != null)
8080 				num_arguments = rank.Dimension;
8081 		}
8082 
8083 		//
8084 		// For compiler generated single dimensional arrays only
8085 		//
ArrayCreation(FullNamedExpression requested_base_type, ArrayInitializer initializers, Location loc)8086 		public ArrayCreation (FullNamedExpression requested_base_type, ArrayInitializer initializers, Location loc)
8087 			: this (requested_base_type, ComposedTypeSpecifier.SingleDimension, initializers, loc)
8088 		{
8089 		}
8090 
8091 		//
8092 		// For expressions like int[] foo = { 1, 2, 3 };
8093 		//
ArrayCreation(FullNamedExpression requested_base_type, ArrayInitializer initializers)8094 		public ArrayCreation (FullNamedExpression requested_base_type, ArrayInitializer initializers)
8095 			: this (requested_base_type, null, initializers, initializers.Location)
8096 		{
8097 		}
8098 
8099 		public bool NoEmptyInterpolation { get; set; }
8100 
8101 		public ComposedTypeSpecifier Rank {
8102 			get {
8103 				return this.rank;
8104 			}
8105 		}
8106 
8107 		public FullNamedExpression TypeExpression {
8108 			get {
8109 				return this.requested_base_type;
8110 			}
8111 		}
8112 
8113 		public ArrayInitializer Initializers {
8114 			get {
8115 				return this.initializers;
8116 			}
8117 		}
8118 
CheckIndices(ResolveContext ec, ArrayInitializer probe, int idx, bool specified_dims, int child_bounds)8119 		bool CheckIndices (ResolveContext ec, ArrayInitializer probe, int idx, bool specified_dims, int child_bounds)
8120 		{
8121 			if (initializers != null && bounds == null) {
8122 				//
8123 				// We use this to store all the data values in the order in which we
8124 				// will need to store them in the byte blob later
8125 				//
8126 				array_data = new List<Expression> (probe.Count);
8127 				bounds = new Dictionary<int, int> ();
8128 			}
8129 
8130 			if (specified_dims) {
8131 				Expression a = arguments [idx];
8132 				a = a.Resolve (ec);
8133 				if (a == null)
8134 					return false;
8135 
8136 				a = ConvertExpressionToArrayIndex (ec, a);
8137 				if (a == null)
8138 					return false;
8139 
8140 				arguments[idx] = a;
8141 
8142 				if (initializers != null) {
8143 					Constant c = a as Constant;
8144 					if (c == null && a is ArrayIndexCast)
8145 						c = ((ArrayIndexCast) a).Child as Constant;
8146 
8147 					if (c == null) {
8148 						ec.Report.Error (150, a.Location, "A constant value is expected");
8149 						return false;
8150 					}
8151 
8152 					int value;
8153 					try {
8154 						value = System.Convert.ToInt32 (c.GetValue ());
8155 					} catch {
8156 						ec.Report.Error (150, a.Location, "A constant value is expected");
8157 						return false;
8158 					}
8159 
8160 					// TODO: probe.Count does not fit ulong in
8161 					if (value != probe.Count) {
8162 						ec.Report.Error (847, loc, "An array initializer of length `{0}' was expected", value.ToString ());
8163 						return false;
8164 					}
8165 
8166 					bounds[idx] = value;
8167 				}
8168 			}
8169 
8170 			if (initializers == null)
8171 				return true;
8172 
8173 			for (int i = 0; i < probe.Count; ++i) {
8174 				var o = probe [i];
8175 				if (o is ArrayInitializer) {
8176 					var sub_probe = o as ArrayInitializer;
8177 					if (idx + 1 >= dimensions){
8178 						ec.Report.Error (623, loc, "Array initializers can only be used in a variable or field initializer. Try using a new expression instead");
8179 						return false;
8180 					}
8181 
8182 					// When we don't have explicitly specified dimensions, record whatever dimension we first encounter at each level
8183 					if (!bounds.ContainsKey(idx + 1))
8184 						bounds[idx + 1] = sub_probe.Count;
8185 
8186 					if (bounds[idx + 1] != sub_probe.Count) {
8187 						ec.Report.Error(847, sub_probe.Location, "An array initializer of length `{0}' was expected", bounds[idx + 1].ToString());
8188 						return false;
8189 					}
8190 
8191 					bool ret = CheckIndices (ec, sub_probe, idx + 1, specified_dims, child_bounds - 1);
8192 					if (!ret)
8193 						return false;
8194 				} else if (child_bounds > 1) {
8195 					ec.Report.Error (846, o.Location, "A nested array initializer was expected");
8196 				} else {
8197 					Expression element = ResolveArrayElement (ec, o);
8198 					if (element == null)
8199 						continue;
8200 #if STATIC
8201 					// Initializers with the default values can be ignored
8202 					Constant c = element as Constant;
8203 					if (c != null) {
8204 						if (!c.IsDefaultInitializer (array_element_type)) {
8205 							++const_initializers_count;
8206 						}
8207 					} else {
8208 						only_constant_initializers = false;
8209 					}
8210 #endif
8211 					array_data.Add (element);
8212 				}
8213 			}
8214 
8215 			return true;
8216 		}
8217 
ContainsEmitWithAwait()8218 		public override bool ContainsEmitWithAwait ()
8219 		{
8220 			foreach (var arg in arguments) {
8221 				if (arg.ContainsEmitWithAwait ())
8222 					return true;
8223 			}
8224 
8225 			return InitializersContainAwait ();
8226 		}
8227 
CreateExpressionTree(ResolveContext ec)8228 		public override Expression CreateExpressionTree (ResolveContext ec)
8229 		{
8230 			Arguments args;
8231 
8232 			if (array_data == null) {
8233 				args = new Arguments (arguments.Count + 1);
8234 				args.Add (new Argument (new TypeOf (array_element_type, loc)));
8235 				foreach (Expression a in arguments)
8236 					args.Add (new Argument (a.CreateExpressionTree (ec)));
8237 
8238 				return CreateExpressionFactoryCall (ec, "NewArrayBounds", args);
8239 			}
8240 
8241 			if (dimensions > 1) {
8242 				ec.Report.Error (838, loc, "An expression tree cannot contain a multidimensional array initializer");
8243 				return null;
8244 			}
8245 
8246 			args = new Arguments (array_data == null ? 1 : array_data.Count + 1);
8247 			args.Add (new Argument (new TypeOf (array_element_type, loc)));
8248 			if (array_data != null) {
8249 				for (int i = 0; i < array_data.Count; ++i) {
8250 					Expression e = array_data [i];
8251 					args.Add (new Argument (e.CreateExpressionTree (ec)));
8252 				}
8253 			}
8254 
8255 			return CreateExpressionFactoryCall (ec, "NewArrayInit", args);
8256 		}
8257 
UpdateIndices(ResolveContext rc)8258 		void UpdateIndices (ResolveContext rc)
8259 		{
8260 			int i = 0;
8261 			for (var probe = initializers; probe != null;) {
8262 				Expression e = new IntConstant (rc.BuiltinTypes, probe.Count, Location.Null);
8263 				arguments.Add (e);
8264 				bounds[i++] = probe.Count;
8265 
8266 				if (probe.Count > 0 && probe [0] is ArrayInitializer) {
8267 					probe = (ArrayInitializer) probe[0];
8268 				} else if (dimensions > i) {
8269 					continue;
8270 				} else {
8271 					return;
8272 				}
8273 			}
8274 		}
8275 
Error_NegativeArrayIndex(ResolveContext ec, Location loc)8276 		protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc)
8277 		{
8278 			ec.Report.Error (248, loc, "Cannot create an array with a negative size");
8279 		}
8280 
FlowAnalysis(FlowAnalysisContext fc)8281 		public override void FlowAnalysis (FlowAnalysisContext fc)
8282 		{
8283 			foreach (var arg in arguments)
8284 				arg.FlowAnalysis (fc);
8285 
8286 			if (array_data != null) {
8287 				foreach (var ad in array_data)
8288 					ad.FlowAnalysis (fc);
8289 			}
8290 		}
8291 
InitializersContainAwait()8292 		bool InitializersContainAwait ()
8293 		{
8294 			if (array_data == null)
8295 				return false;
8296 
8297 			foreach (var expr in array_data) {
8298 				if (expr.ContainsEmitWithAwait ())
8299 					return true;
8300 			}
8301 
8302 			return false;
8303 		}
8304 
ResolveArrayElement(ResolveContext ec, Expression element)8305 		protected virtual Expression ResolveArrayElement (ResolveContext ec, Expression element)
8306 		{
8307 			element = element.Resolve (ec);
8308 			if (element == null)
8309 				return null;
8310 
8311 			var te = element as CompoundAssign.TargetExpression;
8312 			if (te != null) {
8313 				for (int i = 1; i < initializers.Count; ++i) {
8314 					if (initializers [i].ContainsEmitWithAwait ()) {
8315 						te.RequiresEmitWithAwait = true;
8316 						break;
8317 					}
8318 				}
8319 
8320 				if (!te.RequiresEmitWithAwait) {
8321 					if (first_emit != null)
8322 						throw new InternalErrorException ("Can only handle one mutator at a time");
8323 					first_emit = element;
8324 					element = first_emit_temp = new LocalTemporary (element.Type);
8325 				}
8326 			}
8327 
8328 			return Convert.ImplicitConversionRequired (
8329 				ec, element, array_element_type, loc);
8330 		}
8331 
ResolveInitializers(ResolveContext ec)8332 		protected bool ResolveInitializers (ResolveContext ec)
8333 		{
8334 #if STATIC
8335 			only_constant_initializers = true;
8336 #endif
8337 
8338 			if (arguments != null) {
8339 				bool res = true;
8340 				for (int i = 0; i < arguments.Count; ++i) {
8341 					res &= CheckIndices (ec, initializers, i, true, dimensions);
8342 					if (initializers != null)
8343 						break;
8344 				}
8345 
8346 				return res;
8347 			}
8348 
8349 			arguments = new List<Expression> ();
8350 
8351 			if (!CheckIndices (ec, initializers, 0, false, dimensions))
8352 				return false;
8353 
8354 			UpdateIndices (ec);
8355 
8356 			return true;
8357 		}
8358 
8359 		//
8360 		// Resolved the type of the array
8361 		//
ResolveArrayType(ResolveContext ec)8362 		bool ResolveArrayType (ResolveContext ec)
8363 		{
8364 			//
8365 			// Lookup the type
8366 			//
8367 			FullNamedExpression array_type_expr;
8368 			if (num_arguments > 0) {
8369 				array_type_expr = new ComposedCast (requested_base_type, rank);
8370 			} else {
8371 				array_type_expr = requested_base_type;
8372 			}
8373 
8374 			type = array_type_expr.ResolveAsType (ec);
8375 			if (array_type_expr == null)
8376 				return false;
8377 
8378 			var ac = type as ArrayContainer;
8379 			if (ac == null) {
8380 				ec.Report.Error (622, loc, "Can only use array initializer expressions to assign to array types. Try using a new expression instead");
8381 				return false;
8382 			}
8383 
8384 			array_element_type = ac.Element;
8385 			dimensions = ac.Rank;
8386 
8387 			return true;
8388 		}
8389 
DoResolve(ResolveContext ec)8390 		protected override Expression DoResolve (ResolveContext ec)
8391 		{
8392 			if (type != null)
8393 				return this;
8394 
8395 			if (!ResolveArrayType (ec))
8396 				return null;
8397 
8398 			//
8399 			// validate the initializers and fill in any missing bits
8400 			//
8401 			if (!ResolveInitializers (ec))
8402 				return null;
8403 
8404 			eclass = ExprClass.Value;
8405 			return this;
8406 		}
8407 
MakeByteBlob()8408 		byte [] MakeByteBlob ()
8409 		{
8410 			int factor;
8411 			byte [] data;
8412 			byte [] element;
8413 			int count = array_data.Count;
8414 
8415 			TypeSpec element_type = array_element_type;
8416 			if (element_type.IsEnum)
8417 				element_type = EnumSpec.GetUnderlyingType (element_type);
8418 
8419 			factor = BuiltinTypeSpec.GetSize (element_type);
8420 			if (factor == 0)
8421 				throw new Exception ("unrecognized type in MakeByteBlob: " + element_type);
8422 
8423 			data = new byte [(count * factor + 3) & ~3];
8424 			int idx = 0;
8425 
8426 			for (int i = 0; i < count; ++i) {
8427 				var c = array_data[i] as Constant;
8428 				if (c == null) {
8429 					idx += factor;
8430 					continue;
8431 				}
8432 
8433 				object v = c.GetValue ();
8434 
8435 				switch (element_type.BuiltinType) {
8436 				case BuiltinTypeSpec.Type.Long:
8437 					long lval = (long) v;
8438 
8439 					for (int j = 0; j < factor; ++j) {
8440 						data[idx + j] = (byte) (lval & 0xFF);
8441 						lval = (lval >> 8);
8442 					}
8443 					break;
8444 				case BuiltinTypeSpec.Type.ULong:
8445 					ulong ulval = (ulong) v;
8446 
8447 					for (int j = 0; j < factor; ++j) {
8448 						data[idx + j] = (byte) (ulval & 0xFF);
8449 						ulval = (ulval >> 8);
8450 					}
8451 					break;
8452 				case BuiltinTypeSpec.Type.Float:
8453 					var fval = SingleConverter.SingleToInt32Bits((float) v);
8454 
8455 					data[idx] = (byte) (fval & 0xff);
8456 					data[idx + 1] = (byte) ((fval >> 8) & 0xff);
8457 					data[idx + 2] = (byte) ((fval >> 16) & 0xff);
8458 					data[idx + 3] = (byte) (fval >> 24);
8459 					break;
8460 				case BuiltinTypeSpec.Type.Double:
8461 					element = BitConverter.GetBytes ((double) v);
8462 
8463 					for (int j = 0; j < factor; ++j)
8464 						data[idx + j] = element[j];
8465 
8466 					// FIXME: Handle the ARM float format.
8467 					if (!BitConverter.IsLittleEndian)
8468 						System.Array.Reverse (data, idx, 8);
8469 					break;
8470 				case BuiltinTypeSpec.Type.Char:
8471 					int chval = (int) ((char) v);
8472 
8473 					data[idx] = (byte) (chval & 0xff);
8474 					data[idx + 1] = (byte) (chval >> 8);
8475 					break;
8476 				case BuiltinTypeSpec.Type.Short:
8477 					int sval = (int) ((short) v);
8478 
8479 					data[idx] = (byte) (sval & 0xff);
8480 					data[idx + 1] = (byte) (sval >> 8);
8481 					break;
8482 				case BuiltinTypeSpec.Type.UShort:
8483 					int usval = (int) ((ushort) v);
8484 
8485 					data[idx] = (byte) (usval & 0xff);
8486 					data[idx + 1] = (byte) (usval >> 8);
8487 					break;
8488 				case BuiltinTypeSpec.Type.Int:
8489 					int val = (int) v;
8490 
8491 					data[idx] = (byte) (val & 0xff);
8492 					data[idx + 1] = (byte) ((val >> 8) & 0xff);
8493 					data[idx + 2] = (byte) ((val >> 16) & 0xff);
8494 					data[idx + 3] = (byte) (val >> 24);
8495 					break;
8496 				case BuiltinTypeSpec.Type.UInt:
8497 					uint uval = (uint) v;
8498 
8499 					data[idx] = (byte) (uval & 0xff);
8500 					data[idx + 1] = (byte) ((uval >> 8) & 0xff);
8501 					data[idx + 2] = (byte) ((uval >> 16) & 0xff);
8502 					data[idx + 3] = (byte) (uval >> 24);
8503 					break;
8504 				case BuiltinTypeSpec.Type.SByte:
8505 					data[idx] = (byte) (sbyte) v;
8506 					break;
8507 				case BuiltinTypeSpec.Type.Byte:
8508 					data[idx] = (byte) v;
8509 					break;
8510 				case BuiltinTypeSpec.Type.Bool:
8511 					data[idx] = (byte) ((bool) v ? 1 : 0);
8512 					break;
8513 				case BuiltinTypeSpec.Type.Decimal:
8514 					int[] bits = Decimal.GetBits ((decimal) v);
8515 					int p = idx;
8516 
8517 					// FIXME: For some reason, this doesn't work on the MS runtime.
8518 					int[] nbits = new int[4];
8519 					nbits[0] = bits[3];
8520 					nbits[1] = bits[2];
8521 					nbits[2] = bits[0];
8522 					nbits[3] = bits[1];
8523 
8524 					for (int j = 0; j < 4; j++) {
8525 						data[p++] = (byte) (nbits[j] & 0xff);
8526 						data[p++] = (byte) ((nbits[j] >> 8) & 0xff);
8527 						data[p++] = (byte) ((nbits[j] >> 16) & 0xff);
8528 						data[p++] = (byte) (nbits[j] >> 24);
8529 					}
8530 					break;
8531 				default:
8532 					throw new Exception ("Unrecognized type in MakeByteBlob: " + element_type);
8533 				}
8534 
8535 				idx += factor;
8536 			}
8537 
8538 			return data;
8539 		}
8540 
MakeExpression(BuilderContext ctx)8541 		public override SLE.Expression MakeExpression (BuilderContext ctx)
8542 		{
8543 #if STATIC
8544 			return base.MakeExpression (ctx);
8545 #else
8546 			var initializers = new SLE.Expression [array_data.Count];
8547 			for (var i = 0; i < initializers.Length; i++) {
8548 				if (array_data [i] == null)
8549 					initializers [i] = SLE.Expression.Default (array_element_type.GetMetaInfo ());
8550 				else
8551 					initializers [i] = array_data [i].MakeExpression (ctx);
8552 			}
8553 
8554 			return SLE.Expression.NewArrayInit (array_element_type.GetMetaInfo (), initializers);
8555 #endif
8556 		}
8557 #if STATIC
8558 		//
8559 		// Emits the initializers for the array
8560 		//
EmitStaticInitializers(EmitContext ec, FieldExpr stackArray)8561 		void EmitStaticInitializers (EmitContext ec, FieldExpr stackArray)
8562 		{
8563 			var m = ec.Module.PredefinedMembers.RuntimeHelpersInitializeArray.Resolve (loc);
8564 			if (m == null)
8565 				return;
8566 
8567 			//
8568 			// First, the static data
8569 			//
8570 			byte [] data = MakeByteBlob ();
8571 			var fb = ec.CurrentTypeDefinition.Module.MakeStaticData (data, loc);
8572 
8573 			if (stackArray == null) {
8574 				ec.Emit (OpCodes.Dup);
8575 			} else {
8576 				stackArray.Emit (ec);
8577 			}
8578 
8579 			ec.Emit (OpCodes.Ldtoken, fb);
8580 			ec.Emit (OpCodes.Call, m);
8581 		}
8582 #endif
8583 
8584 		//
8585 		// Emits pieces of the array that can not be computed at compile
8586 		// time (variables and string locations).
8587 		//
8588 		// This always expect the top value on the stack to be the array
8589 		//
EmitDynamicInitializers(EmitContext ec, bool emitConstants, StackFieldExpr stackArray)8590 		void EmitDynamicInitializers (EmitContext ec, bool emitConstants, StackFieldExpr stackArray)
8591 		{
8592 			int dims = bounds.Count;
8593 			var current_pos = new int [dims];
8594 
8595 			for (int i = 0; i < array_data.Count; i++){
8596 
8597 				Expression e = array_data [i];
8598 				var c = e as Constant;
8599 
8600 				// Constant can be initialized via StaticInitializer
8601 				if (c == null || (c != null && emitConstants && !c.IsDefaultInitializer (array_element_type))) {
8602 
8603 					var etype = e.Type;
8604 
8605 					if (stackArray != null) {
8606 						if (e.ContainsEmitWithAwait ()) {
8607 							e = e.EmitToField (ec);
8608 						}
8609 
8610 						stackArray.EmitLoad (ec);
8611 					} else {
8612 						ec.Emit (OpCodes.Dup);
8613 					}
8614 
8615 					for (int idx = 0; idx < dims; idx++)
8616 						ec.EmitInt (current_pos [idx]);
8617 
8618 					//
8619 					// If we are dealing with a struct, get the
8620 					// address of it, so we can store it.
8621 					//
8622 					if (dims == 1 && etype.IsStruct && !BuiltinTypeSpec.IsPrimitiveType (etype))
8623 						ec.Emit (OpCodes.Ldelema, etype);
8624 
8625 					e.Emit (ec);
8626 
8627 					ec.EmitArrayStore ((ArrayContainer) type);
8628 				}
8629 
8630 				//
8631 				// Advance counter
8632 				//
8633 				for (int j = dims - 1; j >= 0; j--){
8634 					current_pos [j]++;
8635 					if (current_pos [j] < bounds [j])
8636 						break;
8637 					current_pos [j] = 0;
8638 				}
8639 			}
8640 
8641 			if (stackArray != null)
8642 				stackArray.PrepareCleanup (ec);
8643 		}
8644 
Emit(EmitContext ec)8645 		public override void Emit (EmitContext ec)
8646 		{
8647 			if (!NoEmptyInterpolation && EmitOptimizedEmpty (ec))
8648 				return;
8649 
8650 			var await_field = EmitToFieldSource (ec);
8651 			if (await_field != null)
8652 				await_field.Emit (ec);
8653 		}
8654 
EmitOptimizedEmpty(EmitContext ec)8655 		bool EmitOptimizedEmpty (EmitContext ec)
8656 		{
8657 			if (arguments.Count != 1 || dimensions != 1)
8658 				return false;
8659 
8660 			var c = arguments [0] as Constant;
8661 			if (c == null || !c.IsZeroInteger)
8662 				return false;
8663 
8664 			var m = ec.Module.PredefinedMembers.ArrayEmpty.Get ();
8665 			if (m == null || ec.CurrentType.MemberDefinition.DeclaringAssembly == m.DeclaringType.MemberDefinition.DeclaringAssembly)
8666 				return false;
8667 
8668 			m = m.MakeGenericMethod (ec.MemberContext, array_element_type);
8669 			ec.Emit (OpCodes.Call, m);
8670 			return true;
8671 		}
8672 
EmitToFieldSource(EmitContext ec)8673 		protected sealed override FieldExpr EmitToFieldSource (EmitContext ec)
8674 		{
8675 			if (first_emit != null) {
8676 				first_emit.Emit (ec);
8677 				first_emit_temp.Store (ec);
8678 			}
8679 
8680 			StackFieldExpr await_stack_field;
8681 			if (ec.HasSet (BuilderContext.Options.AsyncBody) && InitializersContainAwait ()) {
8682 				await_stack_field = ec.GetTemporaryField (type);
8683 				ec.EmitThis ();
8684 			} else {
8685 				await_stack_field = null;
8686 			}
8687 
8688 			EmitExpressionsList (ec, arguments);
8689 
8690 			ec.EmitArrayNew ((ArrayContainer) type);
8691 
8692 			if (initializers == null)
8693 				return await_stack_field;
8694 
8695 			if (await_stack_field != null)
8696 				await_stack_field.EmitAssignFromStack (ec);
8697 
8698 #if STATIC
8699 			//
8700 			// Emit static initializer for arrays which contain more than 2 items and
8701 			// the static initializer will initialize at least 25% of array values or there
8702 			// is more than 10 items to be initialized
8703 			//
8704 			// NOTE: const_initializers_count does not contain default constant values.
8705 			//
8706 			if (const_initializers_count > 2 && (array_data.Count > 10 || const_initializers_count * 4 > (array_data.Count)) &&
8707 				(BuiltinTypeSpec.IsPrimitiveType (array_element_type) || array_element_type.IsEnum)) {
8708 				EmitStaticInitializers (ec, await_stack_field);
8709 
8710 				if (!only_constant_initializers)
8711 					EmitDynamicInitializers (ec, false, await_stack_field);
8712 			} else
8713 #endif
8714 			{
8715 				EmitDynamicInitializers (ec, true, await_stack_field);
8716 			}
8717 
8718 			if (first_emit_temp != null)
8719 				first_emit_temp.Release (ec);
8720 
8721 			return await_stack_field;
8722 		}
8723 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)8724 		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
8725 		{
8726 			// no multi dimensional or jagged arrays
8727 			if (arguments.Count != 1 || array_element_type.IsArray) {
8728 				base.EncodeAttributeValue (rc, enc, targetType, parameterType);
8729 				return;
8730 			}
8731 
8732 			// No array covariance, except for array -> object
8733 			if (type != targetType) {
8734 				if (targetType.BuiltinType != BuiltinTypeSpec.Type.Object) {
8735 					base.EncodeAttributeValue (rc, enc, targetType, parameterType);
8736 					return;
8737 				}
8738 
8739 				if (enc.Encode (type) == AttributeEncoder.EncodedTypeProperties.DynamicType) {
8740 					Attribute.Error_AttributeArgumentIsDynamic (rc, loc);
8741 					return;
8742 				}
8743 			}
8744 
8745 			// Single dimensional array of 0 size
8746 			if (array_data == null) {
8747 				IntConstant ic = arguments[0] as IntConstant;
8748 				if (ic == null || !ic.IsDefaultValue) {
8749 					base.EncodeAttributeValue (rc, enc, targetType, parameterType);
8750 				} else {
8751 					enc.Encode (0);
8752 				}
8753 
8754 				return;
8755 			}
8756 
8757 			enc.Encode (array_data.Count);
8758 			foreach (var element in array_data) {
8759 				element.EncodeAttributeValue (rc, enc, array_element_type, parameterType);
8760 			}
8761 		}
8762 
CloneTo(CloneContext clonectx, Expression t)8763 		protected override void CloneTo (CloneContext clonectx, Expression t)
8764 		{
8765 			ArrayCreation target = (ArrayCreation) t;
8766 
8767 			if (requested_base_type != null)
8768 				target.requested_base_type = (FullNamedExpression)requested_base_type.Clone (clonectx);
8769 
8770 			if (arguments != null){
8771 				target.arguments = new List<Expression> (arguments.Count);
8772 				foreach (Expression e in arguments)
8773 					target.arguments.Add (e.Clone (clonectx));
8774 			}
8775 
8776 			if (initializers != null)
8777 				target.initializers = (ArrayInitializer) initializers.Clone (clonectx);
8778 		}
8779 
Accept(StructuralVisitor visitor)8780 		public override object Accept (StructuralVisitor visitor)
8781 		{
8782 			return visitor.Visit (this);
8783 		}
8784 	}
8785 
8786 	//
8787 	// Represents an implicitly typed array epxression
8788 	//
8789 	class ImplicitlyTypedArrayCreation : ArrayCreation
8790 	{
8791 		TypeInferenceContext best_type_inference;
8792 
ImplicitlyTypedArrayCreation(ComposedTypeSpecifier rank, ArrayInitializer initializers, Location loc)8793 		public ImplicitlyTypedArrayCreation (ComposedTypeSpecifier rank, ArrayInitializer initializers, Location loc)
8794 			: base (null, rank, initializers, loc)
8795 		{
8796 		}
8797 
ImplicitlyTypedArrayCreation(ArrayInitializer initializers, Location loc)8798 		public ImplicitlyTypedArrayCreation (ArrayInitializer initializers, Location loc)
8799 			: base (null, initializers, loc)
8800 		{
8801 		}
8802 
DoResolve(ResolveContext ec)8803 		protected override Expression DoResolve (ResolveContext ec)
8804 		{
8805 			if (type != null)
8806 				return this;
8807 
8808 			dimensions = rank.Dimension;
8809 
8810 			best_type_inference = new TypeInferenceContext ();
8811 
8812 			if (!ResolveInitializers (ec))
8813 				return null;
8814 
8815 			best_type_inference.FixAllTypes (ec);
8816 			array_element_type = best_type_inference.InferredTypeArguments[0];
8817 			best_type_inference = null;
8818 
8819 			if (array_element_type == null || InternalType.HasNoType (array_element_type) || arguments.Count != rank.Dimension) {
8820 				ec.Report.Error (826, loc,
8821 					"The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
8822 				return null;
8823 			}
8824 
8825 			//
8826 			// At this point we found common base type for all initializer elements
8827 			// but we have to be sure that all static initializer elements are of
8828 			// same type
8829 			//
8830 			UnifyInitializerElement (ec);
8831 
8832 			type = ArrayContainer.MakeType (ec.Module, array_element_type, dimensions);
8833 			eclass = ExprClass.Value;
8834 			return this;
8835 		}
8836 
8837 		//
8838 		// Converts static initializer only
8839 		//
UnifyInitializerElement(ResolveContext ec)8840 		void UnifyInitializerElement (ResolveContext ec)
8841 		{
8842 			for (int i = 0; i < array_data.Count; ++i) {
8843 				Expression e = array_data[i];
8844 				if (e != null)
8845 					array_data [i] = Convert.ImplicitConversion (ec, e, array_element_type, Location.Null);
8846 			}
8847 		}
8848 
ResolveArrayElement(ResolveContext ec, Expression element)8849 		protected override Expression ResolveArrayElement (ResolveContext ec, Expression element)
8850 		{
8851 			element = element.Resolve (ec);
8852 			if (element != null)
8853 				best_type_inference.AddCommonTypeBound (element.Type);
8854 
8855 			return element;
8856 		}
8857 	}
8858 
8859 	sealed class CompilerGeneratedThis : This
8860 	{
CompilerGeneratedThis(TypeSpec type, Location loc)8861 		public CompilerGeneratedThis (TypeSpec type, Location loc)
8862 			: base (loc)
8863 		{
8864 			this.type = type;
8865 		}
8866 
DoResolve(ResolveContext rc)8867 		protected override Expression DoResolve (ResolveContext rc)
8868 		{
8869 			eclass = ExprClass.Variable;
8870 
8871 			var block = rc.CurrentBlock;
8872 			if (block != null) {
8873 				var top = block.ParametersBlock.TopBlock;
8874 				if (top.ThisVariable != null)
8875 					variable_info = top.ThisVariable.VariableInfo;
8876 
8877 			}
8878 
8879 			return this;
8880 		}
8881 
DoResolveLValue(ResolveContext rc, Expression right_side)8882 		public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
8883 		{
8884 			return DoResolve (rc);
8885 		}
8886 
GetHoistedVariable(AnonymousExpression ae)8887 		public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
8888 		{
8889 			return null;
8890 		}
8891 	}
8892 
8893 	/// <summary>
8894 	///   Represents the `this' construct
8895 	/// </summary>
8896 
8897 	public class This : VariableReference
8898 	{
8899 		sealed class ThisVariable : ILocalVariable
8900 		{
8901 			public static readonly ILocalVariable Instance = new ThisVariable ();
8902 
Emit(EmitContext ec)8903 			public void Emit (EmitContext ec)
8904 			{
8905 				ec.EmitThis ();
8906 			}
8907 
EmitAssign(EmitContext ec)8908 			public void EmitAssign (EmitContext ec)
8909 			{
8910 				throw new InvalidOperationException ();
8911 			}
8912 
EmitAddressOf(EmitContext ec)8913 			public void EmitAddressOf (EmitContext ec)
8914 			{
8915 				ec.EmitThis ();
8916 			}
8917 		}
8918 
8919 		protected VariableInfo variable_info;
8920 
This(Location loc)8921 		public This (Location loc)
8922 		{
8923 			this.loc = loc;
8924 		}
8925 
8926 		#region Properties
8927 
8928 		public override string Name {
8929 			get { return "this"; }
8930 		}
8931 
8932 		public override bool IsLockedByStatement {
8933 			get {
8934 				return false;
8935 			}
8936 			set {
8937 			}
8938 		}
8939 
8940 		public override bool IsRef {
8941 			get { return type.IsStruct; }
8942 		}
8943 
8944 		public override bool IsSideEffectFree {
8945 			get {
8946 				return true;
8947 			}
8948 		}
8949 
8950 		protected override ILocalVariable Variable {
8951 			get { return ThisVariable.Instance; }
8952 		}
8953 
8954 		public override VariableInfo VariableInfo {
8955 			get { return variable_info; }
8956 		}
8957 
8958 		public override bool IsFixed {
8959 			get { return false; }
8960 		}
8961 
8962 		#endregion
8963 
CheckStructThisDefiniteAssignment(FlowAnalysisContext fc)8964 		void CheckStructThisDefiniteAssignment (FlowAnalysisContext fc)
8965 		{
8966 			//
8967 			// It's null for all cases when we don't need to check `this'
8968 			// definitive assignment
8969 			//
8970 			if (variable_info == null)
8971 				return;
8972 
8973 			if (fc.IsDefinitelyAssigned (variable_info))
8974 				return;
8975 
8976 			fc.Report.Error (188, loc, "The `this' object cannot be used before all of its fields are assigned to");
8977 		}
8978 
Error_ThisNotAvailable(ResolveContext ec)8979 		protected virtual void Error_ThisNotAvailable (ResolveContext ec)
8980 		{
8981 			if (ec.IsStatic && !ec.HasSet (ResolveContext.Options.ConstantScope)) {
8982 				ec.Report.Error (26, loc, "Keyword `this' is not valid in a static property, static method, or static field initializer");
8983 			} else if (ec.CurrentAnonymousMethod != null) {
8984 				ec.Report.Error (1673, loc,
8985 					"Anonymous methods inside structs cannot access instance members of `this'. " +
8986 					"Consider copying `this' to a local variable outside the anonymous method and using the local instead");
8987 			} else {
8988 				ec.Report.Error (27, loc, "Keyword `this' is not available in the current context");
8989 			}
8990 		}
8991 
FlowAnalysis(FlowAnalysisContext fc)8992 		public override void FlowAnalysis (FlowAnalysisContext fc)
8993 		{
8994 			CheckStructThisDefiniteAssignment (fc);
8995 		}
8996 
GetHoistedVariable(AnonymousExpression ae)8997 		public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
8998 		{
8999 			if (ae == null)
9000 				return null;
9001 
9002 			AnonymousMethodStorey storey = ae.Storey;
9003 			return storey != null ? storey.HoistedThis : null;
9004 		}
9005 
IsThisAvailable(ResolveContext ec, bool ignoreAnonymous)9006 		public static bool IsThisAvailable (ResolveContext ec, bool ignoreAnonymous)
9007 		{
9008 			if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer | ResolveContext.Options.ConstantScope))
9009 				return false;
9010 
9011 			if (ignoreAnonymous || ec.CurrentAnonymousMethod == null)
9012 				return true;
9013 
9014 			if (ec.CurrentType.IsStruct && !(ec.CurrentAnonymousMethod is StateMachineInitializer))
9015 				return false;
9016 
9017 			return true;
9018 		}
9019 
ResolveBase(ResolveContext ec)9020 		public virtual void ResolveBase (ResolveContext ec)
9021 		{
9022 			eclass = ExprClass.Variable;
9023 			type = ec.CurrentType;
9024 
9025 			if (!IsThisAvailable (ec, false)) {
9026 				Error_ThisNotAvailable (ec);
9027 				return;
9028 			}
9029 
9030 			var block = ec.CurrentBlock;
9031 			if (block != null) {
9032 				var top = block.ParametersBlock.TopBlock;
9033 				if (top.ThisVariable != null)
9034 					variable_info = top.ThisVariable.VariableInfo;
9035 
9036 				AnonymousExpression am = ec.CurrentAnonymousMethod;
9037 				if (am != null && ec.IsVariableCapturingRequired && !block.Explicit.HasCapturedThis) {
9038 					//
9039 					// Hoisted this is almost like hoisted variable but not exactly. When
9040 					// there is no variable hoisted we can simply emit an instance method
9041 					// without lifting this into a storey. Unfotunatelly this complicates
9042 					// things in other cases because we don't know where this will be hoisted
9043 					// until top-level block is fully resolved
9044 					//
9045 					top.AddThisReferenceFromChildrenBlock (block.Explicit);
9046 					am.SetHasThisAccess ();
9047 				}
9048 			}
9049 		}
9050 
DoResolve(ResolveContext ec)9051 		protected override Expression DoResolve (ResolveContext ec)
9052 		{
9053 			ResolveBase (ec);
9054 			return this;
9055 		}
9056 
DoResolveLValue(ResolveContext ec, Expression right_side)9057 		public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
9058 		{
9059 			if (eclass == ExprClass.Unresolved)
9060 				ResolveBase (ec);
9061 
9062 			if (type.IsClass || (type.IsReadOnly && !ec.HasSet (ResolveContext.Options.ConstructorScope))) {
9063 				if (right_side == EmptyExpression.UnaryAddress)
9064 					ec.Report.Error (459, loc, "Cannot take the address of `this' because it is read-only");
9065 				else if (right_side == EmptyExpression.OutAccess)
9066 					ec.Report.Error (1605, loc, "Cannot pass `this' as a ref or out argument because it is read-only");
9067 				else
9068 					ec.Report.Error (1604, loc, "Cannot assign to `this' because it is read-only");
9069 			}
9070 
9071 			return this;
9072 		}
9073 
GetHashCode()9074 		public override int GetHashCode()
9075 		{
9076 			throw new NotImplementedException ();
9077 		}
9078 
Equals(object obj)9079 		public override bool Equals (object obj)
9080 		{
9081 			This t = obj as This;
9082 			if (t == null)
9083 				return false;
9084 
9085 			return true;
9086 		}
9087 
CloneTo(CloneContext clonectx, Expression t)9088 		protected override void CloneTo (CloneContext clonectx, Expression t)
9089 		{
9090 			// Nothing
9091 		}
9092 
SetHasAddressTaken()9093 		public override void SetHasAddressTaken ()
9094 		{
9095 			// Nothing
9096 		}
9097 
Accept(StructuralVisitor visitor)9098 		public override object Accept (StructuralVisitor visitor)
9099 		{
9100 			return visitor.Visit (this);
9101 		}
9102 	}
9103 
9104 	/// <summary>
9105 	///   Represents the `__arglist' construct
9106 	/// </summary>
9107 	public class ArglistAccess : Expression
9108 	{
ArglistAccess(Location loc)9109 		public ArglistAccess (Location loc)
9110 		{
9111 			this.loc = loc;
9112 		}
9113 
CloneTo(CloneContext clonectx, Expression target)9114 		protected override void CloneTo (CloneContext clonectx, Expression target)
9115 		{
9116 			// nothing.
9117 		}
9118 
ContainsEmitWithAwait()9119 		public override bool ContainsEmitWithAwait ()
9120 		{
9121 			return false;
9122 		}
9123 
CreateExpressionTree(ResolveContext ec)9124 		public override Expression CreateExpressionTree (ResolveContext ec)
9125 		{
9126 			throw new NotSupportedException ("ET");
9127 		}
9128 
DoResolve(ResolveContext ec)9129 		protected override Expression DoResolve (ResolveContext ec)
9130 		{
9131 			eclass = ExprClass.Variable;
9132 			type = ec.Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
9133 
9134 			if (ec.HasSet (ResolveContext.Options.FieldInitializerScope) || !ec.CurrentBlock.ParametersBlock.Parameters.HasArglist) {
9135 				ec.Report.Error (190, loc,
9136 					"The __arglist construct is valid only within a variable argument method");
9137 			}
9138 
9139 			return this;
9140 		}
9141 
Emit(EmitContext ec)9142 		public override void Emit (EmitContext ec)
9143 		{
9144 			ec.Emit (OpCodes.Arglist);
9145 		}
9146 
Accept(StructuralVisitor visitor)9147 		public override object Accept (StructuralVisitor visitor)
9148 		{
9149 			return visitor.Visit (this);
9150 		}
9151 	}
9152 
9153 	/// <summary>
9154 	///   Represents the `__arglist (....)' construct
9155 	/// </summary>
9156 	public class Arglist : Expression
9157 	{
9158 		Arguments arguments;
9159 
Arglist(Location loc)9160 		public Arglist (Location loc)
9161 			: this (null, loc)
9162 		{
9163 		}
9164 
Arglist(Arguments args, Location l)9165 		public Arglist (Arguments args, Location l)
9166 		{
9167 			arguments = args;
9168 			loc = l;
9169 		}
9170 
9171 		public Arguments Arguments {
9172 			get {
9173 				return arguments;
9174 			}
9175 		}
9176 
9177 		public MetaType[] ArgumentTypes {
9178 		    get {
9179 				if (arguments == null)
9180 					return MetaType.EmptyTypes;
9181 
9182 				var retval = new MetaType[arguments.Count];
9183 				for (int i = 0; i < retval.Length; i++)
9184 					retval[i] = arguments[i].Expr.Type.GetMetaInfo ();
9185 
9186 		        return retval;
9187 		    }
9188 		}
9189 
ContainsEmitWithAwait()9190 		public override bool ContainsEmitWithAwait ()
9191 		{
9192 			throw new NotImplementedException ();
9193 		}
9194 
CreateExpressionTree(ResolveContext ec)9195 		public override Expression CreateExpressionTree (ResolveContext ec)
9196 		{
9197 			ec.Report.Error (1952, loc, "An expression tree cannot contain a method with variable arguments");
9198 			return null;
9199 		}
9200 
DoResolve(ResolveContext ec)9201 		protected override Expression DoResolve (ResolveContext ec)
9202 		{
9203 			eclass = ExprClass.Variable;
9204 			type = InternalType.Arglist;
9205 			if (arguments != null) {
9206 				bool dynamic;	// Can be ignored as there is always only 1 overload
9207 				arguments.Resolve (ec, out dynamic);
9208 			}
9209 
9210 			return this;
9211 		}
9212 
Emit(EmitContext ec)9213 		public override void Emit (EmitContext ec)
9214 		{
9215 			if (arguments != null)
9216 				arguments.Emit (ec);
9217 		}
9218 
CloneTo(CloneContext clonectx, Expression t)9219 		protected override void CloneTo (CloneContext clonectx, Expression t)
9220 		{
9221 			Arglist target = (Arglist) t;
9222 
9223 			if (arguments != null)
9224 				target.arguments = arguments.Clone (clonectx);
9225 		}
9226 
Accept(StructuralVisitor visitor)9227 		public override object Accept (StructuralVisitor visitor)
9228 		{
9229 			return visitor.Visit (this);
9230 		}
9231 	}
9232 
9233 	public class RefValueExpr : ShimExpression, IAssignMethod, IMemoryLocation
9234 	{
9235 		FullNamedExpression texpr;
9236 
RefValueExpr(Expression expr, FullNamedExpression texpr, Location loc)9237 		public RefValueExpr (Expression expr, FullNamedExpression texpr, Location loc)
9238 			: base (expr)
9239 		{
9240 			this.texpr = texpr;
9241 			this.loc = loc;
9242 		}
9243 
9244 		public FullNamedExpression TypeExpression {
9245 			get {
9246 				return texpr;
9247 			}
9248 		}
9249 
ContainsEmitWithAwait()9250 		public override bool ContainsEmitWithAwait ()
9251 		{
9252 			return false;
9253 		}
9254 
AddressOf(EmitContext ec, AddressOp mode)9255 		public void AddressOf (EmitContext ec, AddressOp mode)
9256 		{
9257 			expr.Emit (ec);
9258 			ec.Emit (OpCodes.Refanyval, type);
9259 		}
9260 
DoResolve(ResolveContext rc)9261 		protected override Expression DoResolve (ResolveContext rc)
9262 		{
9263 			expr = expr.Resolve (rc);
9264 			type = texpr.ResolveAsType (rc);
9265 			if (expr == null || type == null)
9266 				return null;
9267 
9268 			expr = Convert.ImplicitConversionRequired (rc, expr, rc.Module.PredefinedTypes.TypedReference.Resolve (), loc);
9269 			eclass = ExprClass.Variable;
9270 			return this;
9271 		}
9272 
DoResolveLValue(ResolveContext rc, Expression right_side)9273 		public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
9274 		{
9275 			return DoResolve (rc);
9276 		}
9277 
Emit(EmitContext ec)9278 		public override void Emit (EmitContext ec)
9279 		{
9280 			expr.Emit (ec);
9281 			ec.Emit (OpCodes.Refanyval, type);
9282 			ec.EmitLoadFromPtr (type);
9283 		}
9284 
Emit(EmitContext ec, bool leave_copy)9285 		public void Emit (EmitContext ec, bool leave_copy)
9286 		{
9287 			throw new NotImplementedException ();
9288 		}
9289 
EmitAssign(EmitContext ec, Expression source, bool leave_copy, bool isCompound)9290 		public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
9291 		{
9292 			expr.Emit (ec);
9293 			ec.Emit (OpCodes.Refanyval, type);
9294 			source.Emit (ec);
9295 
9296 			LocalTemporary temporary = null;
9297 			if (leave_copy) {
9298 				ec.Emit (OpCodes.Dup);
9299 				temporary = new LocalTemporary (source.Type);
9300 				temporary.Store (ec);
9301 			}
9302 
9303 			ec.EmitStoreFromPtr (type);
9304 
9305 			if (temporary != null) {
9306 				temporary.Emit (ec);
9307 				temporary.Release (ec);
9308 			}
9309 		}
9310 
Accept(StructuralVisitor visitor)9311 		public override object Accept (StructuralVisitor visitor)
9312 		{
9313 			return visitor.Visit (this);
9314 		}
9315 	}
9316 
9317 	public class RefTypeExpr : ShimExpression
9318 	{
RefTypeExpr(Expression expr, Location loc)9319 		public RefTypeExpr (Expression expr, Location loc)
9320 			: base (expr)
9321 		{
9322 			this.loc = loc;
9323 		}
9324 
DoResolve(ResolveContext rc)9325 		protected override Expression DoResolve (ResolveContext rc)
9326 		{
9327 			expr = expr.Resolve (rc);
9328 			if (expr == null)
9329 				return null;
9330 
9331 			expr = Convert.ImplicitConversionRequired (rc, expr, rc.Module.PredefinedTypes.TypedReference.Resolve (), loc);
9332 			if (expr == null)
9333 				return null;
9334 
9335 			type = rc.BuiltinTypes.Type;
9336 			eclass = ExprClass.Value;
9337 			return this;
9338 		}
9339 
Emit(EmitContext ec)9340 		public override void Emit (EmitContext ec)
9341 		{
9342 			expr.Emit (ec);
9343 			ec.Emit (OpCodes.Refanytype);
9344 			var m = ec.Module.PredefinedMembers.TypeGetTypeFromHandle.Resolve (loc);
9345 			if (m != null)
9346 				ec.Emit (OpCodes.Call, m);
9347 		}
9348 
Accept(StructuralVisitor visitor)9349 		public override object Accept (StructuralVisitor visitor)
9350 		{
9351 			return visitor.Visit (this);
9352 		}
9353 	}
9354 
9355 	public class MakeRefExpr : ShimExpression
9356 	{
MakeRefExpr(Expression expr, Location loc)9357 		public MakeRefExpr (Expression expr, Location loc)
9358 			: base (expr)
9359 		{
9360 			this.loc = loc;
9361 		}
9362 
ContainsEmitWithAwait()9363 		public override bool ContainsEmitWithAwait ()
9364 		{
9365 			throw new NotImplementedException ();
9366 		}
9367 
DoResolve(ResolveContext rc)9368 		protected override Expression DoResolve (ResolveContext rc)
9369 		{
9370 			expr = expr.ResolveLValue (rc, EmptyExpression.LValueMemberAccess);
9371 			type = rc.Module.PredefinedTypes.TypedReference.Resolve ();
9372 			eclass = ExprClass.Value;
9373 			return this;
9374 		}
9375 
Emit(EmitContext ec)9376 		public override void Emit (EmitContext ec)
9377 		{
9378 			((IMemoryLocation) expr).AddressOf (ec, AddressOp.Load);
9379 			ec.Emit (OpCodes.Mkrefany, expr.Type);
9380 		}
9381 
Accept(StructuralVisitor visitor)9382 		public override object Accept (StructuralVisitor visitor)
9383 		{
9384 			return visitor.Visit (this);
9385 		}
9386 	}
9387 
9388 	/// <summary>
9389 	///   Implements the typeof operator
9390 	/// </summary>
9391 	public class TypeOf : Expression {
9392 		FullNamedExpression QueriedType;
9393 		TypeSpec typearg;
9394 
TypeOf(FullNamedExpression queried_type, Location l)9395 		public TypeOf (FullNamedExpression queried_type, Location l)
9396 		{
9397 			QueriedType = queried_type;
9398 			loc = l;
9399 		}
9400 
9401 		//
9402 		// Use this constructor for any compiler generated typeof expression
9403 		//
TypeOf(TypeSpec type, Location loc)9404 		public TypeOf (TypeSpec type, Location loc)
9405 		{
9406 			this.typearg = type;
9407 			this.loc = loc;
9408 		}
9409 
9410 		#region Properties
9411 
9412 		public override bool IsSideEffectFree {
9413 			get {
9414 				return true;
9415 			}
9416 		}
9417 
9418 		public TypeSpec TypeArgument {
9419 			get {
9420 				return typearg;
9421 			}
9422 		}
9423 
9424 		public FullNamedExpression TypeExpression {
9425 			get {
9426 				return QueriedType;
9427 			}
9428 		}
9429 
9430 		#endregion
9431 
9432 
CloneTo(CloneContext clonectx, Expression t)9433 		protected override void CloneTo (CloneContext clonectx, Expression t)
9434 		{
9435 			TypeOf target = (TypeOf) t;
9436 			if (QueriedType != null)
9437 				target.QueriedType = (FullNamedExpression) QueriedType.Clone (clonectx);
9438 		}
9439 
ContainsEmitWithAwait()9440 		public override bool ContainsEmitWithAwait ()
9441 		{
9442 			return false;
9443 		}
9444 
CreateExpressionTree(ResolveContext ec)9445 		public override Expression CreateExpressionTree (ResolveContext ec)
9446 		{
9447 			Arguments args = new Arguments (2);
9448 			args.Add (new Argument (this));
9449 			args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
9450 			return CreateExpressionFactoryCall (ec, "Constant", args);
9451 		}
9452 
DoResolve(ResolveContext ec)9453 		protected override Expression DoResolve (ResolveContext ec)
9454 		{
9455 			if (eclass != ExprClass.Unresolved)
9456 				return this;
9457 
9458 			if (typearg == null) {
9459 				//
9460 				// Pointer types are allowed without explicit unsafe, they are just tokens
9461 				//
9462 				using (ec.Set (ResolveContext.Options.UnsafeScope)) {
9463 					typearg = QueriedType.ResolveAsType (ec, true);
9464 				}
9465 
9466 				if (typearg == null)
9467 					return null;
9468 
9469 				if (typearg.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
9470 					ec.Report.Error (1962, QueriedType.Location,
9471 						"The typeof operator cannot be used on the dynamic type");
9472 				}
9473 			}
9474 
9475 			type = ec.BuiltinTypes.Type;
9476 
9477 			// Even though what is returned is a type object, it's treated as a value by the compiler.
9478 			// In particular, 'typeof (Foo).X' is something totally different from 'Foo.X'.
9479 			eclass = ExprClass.Value;
9480 			return this;
9481 		}
9482 
ContainsDynamicType(TypeSpec type)9483 		static bool ContainsDynamicType (TypeSpec type)
9484 		{
9485 			if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
9486 				return true;
9487 
9488 			var element_container = type as ElementTypeSpec;
9489 			if (element_container != null)
9490 				return ContainsDynamicType (element_container.Element);
9491 
9492 			foreach (var t in type.TypeArguments) {
9493 				if (ContainsDynamicType (t)) {
9494 					return true;
9495 				}
9496 			}
9497 
9498 			return false;
9499 		}
9500 
EncodeAttributeValue(IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)9501 		public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType)
9502 		{
9503 			// Target type is not System.Type therefore must be object
9504 			// and we need to use different encoding sequence
9505 			if (targetType != type)
9506 				enc.Encode (type);
9507 
9508 			if (typearg is InflatedTypeSpec) {
9509 				var gt = typearg;
9510 				do {
9511 					if (InflatedTypeSpec.ContainsTypeParameter (gt)) {
9512 						rc.Module.Compiler.Report.Error (416, loc, "`{0}': an attribute argument cannot use type parameters",
9513 							typearg.GetSignatureForError ());
9514 						return;
9515 					}
9516 
9517 					gt = gt.DeclaringType;
9518 				} while (gt != null);
9519 			}
9520 
9521 			if (ContainsDynamicType (typearg)) {
9522 				Attribute.Error_AttributeArgumentIsDynamic (rc, loc);
9523 				return;
9524 			}
9525 
9526 			enc.EncodeTypeName (typearg);
9527 		}
9528 
Emit(EmitContext ec)9529 		public override void Emit (EmitContext ec)
9530 		{
9531 			ec.Emit (OpCodes.Ldtoken, typearg);
9532 			var m = ec.Module.PredefinedMembers.TypeGetTypeFromHandle.Resolve (loc);
9533 			if (m != null)
9534 				ec.Emit (OpCodes.Call, m);
9535 		}
9536 
Accept(StructuralVisitor visitor)9537 		public override object Accept (StructuralVisitor visitor)
9538 		{
9539 			return visitor.Visit (this);
9540 		}
9541 	}
9542 
9543 	sealed class TypeOfMethod : TypeOfMember<MethodSpec>
9544 	{
TypeOfMethod(MethodSpec method, Location loc)9545 		public TypeOfMethod (MethodSpec method, Location loc)
9546 			: base (method, loc)
9547 		{
9548 		}
9549 
DoResolve(ResolveContext ec)9550 		protected override Expression DoResolve (ResolveContext ec)
9551 		{
9552 			if (member.IsConstructor) {
9553 				type = ec.Module.PredefinedTypes.ConstructorInfo.Resolve ();
9554 			} else {
9555 				type = ec.Module.PredefinedTypes.MethodInfo.Resolve ();
9556 			}
9557 
9558 			if (type == null)
9559 				return null;
9560 
9561 			return base.DoResolve (ec);
9562 		}
9563 
Emit(EmitContext ec)9564 		public override void Emit (EmitContext ec)
9565 		{
9566 			ec.Emit (OpCodes.Ldtoken, member);
9567 
9568 			base.Emit (ec);
9569 			ec.Emit (OpCodes.Castclass, type);
9570 		}
9571 
GetTypeFromHandle(EmitContext ec)9572 		protected override PredefinedMember<MethodSpec> GetTypeFromHandle (EmitContext ec)
9573 		{
9574 			return ec.Module.PredefinedMembers.MethodInfoGetMethodFromHandle;
9575 		}
9576 
GetTypeFromHandleGeneric(EmitContext ec)9577 		protected override PredefinedMember<MethodSpec> GetTypeFromHandleGeneric (EmitContext ec)
9578 		{
9579 			return ec.Module.PredefinedMembers.MethodInfoGetMethodFromHandle2;
9580 		}
9581 	}
9582 
9583 	abstract class TypeOfMember<T> : Expression where T : MemberSpec
9584 	{
9585 		protected readonly T member;
9586 
TypeOfMember(T member, Location loc)9587 		protected TypeOfMember (T member, Location loc)
9588 		{
9589 			this.member = member;
9590 			this.loc = loc;
9591 		}
9592 
9593 		public override bool IsSideEffectFree {
9594 			get {
9595 				return true;
9596 			}
9597 		}
9598 
ContainsEmitWithAwait()9599 		public override bool ContainsEmitWithAwait ()
9600 		{
9601 			return false;
9602 		}
9603 
CreateExpressionTree(ResolveContext ec)9604 		public override Expression CreateExpressionTree (ResolveContext ec)
9605 		{
9606 			Arguments args = new Arguments (2);
9607 			args.Add (new Argument (this));
9608 			args.Add (new Argument (new TypeOf (type, loc)));
9609 			return CreateExpressionFactoryCall (ec, "Constant", args);
9610 		}
9611 
DoResolve(ResolveContext ec)9612 		protected override Expression DoResolve (ResolveContext ec)
9613 		{
9614 			eclass = ExprClass.Value;
9615 			return this;
9616 		}
9617 
Emit(EmitContext ec)9618 		public override void Emit (EmitContext ec)
9619 		{
9620 			bool is_generic = member.DeclaringType.IsGenericOrParentIsGeneric;
9621 			PredefinedMember<MethodSpec> p;
9622 			if (is_generic) {
9623 				p = GetTypeFromHandleGeneric (ec);
9624 				ec.Emit (OpCodes.Ldtoken, member.DeclaringType);
9625 			} else {
9626 				p = GetTypeFromHandle (ec);
9627 			}
9628 
9629 			var mi = p.Resolve (loc);
9630 			if (mi != null)
9631 				ec.Emit (OpCodes.Call, mi);
9632 		}
9633 
GetTypeFromHandle(EmitContext ec)9634 		protected abstract PredefinedMember<MethodSpec> GetTypeFromHandle (EmitContext ec);
GetTypeFromHandleGeneric(EmitContext ec)9635 		protected abstract PredefinedMember<MethodSpec> GetTypeFromHandleGeneric (EmitContext ec);
9636 	}
9637 
9638 	sealed class TypeOfField : TypeOfMember<FieldSpec>
9639 	{
TypeOfField(FieldSpec field, Location loc)9640 		public TypeOfField (FieldSpec field, Location loc)
9641 			: base (field, loc)
9642 		{
9643 		}
9644 
DoResolve(ResolveContext ec)9645 		protected override Expression DoResolve (ResolveContext ec)
9646 		{
9647 			type = ec.Module.PredefinedTypes.FieldInfo.Resolve ();
9648 			if (type == null)
9649 				return null;
9650 
9651 			return base.DoResolve (ec);
9652 		}
9653 
Emit(EmitContext ec)9654 		public override void Emit (EmitContext ec)
9655 		{
9656 			ec.Emit (OpCodes.Ldtoken, member);
9657 			base.Emit (ec);
9658 		}
9659 
GetTypeFromHandle(EmitContext ec)9660 		protected override PredefinedMember<MethodSpec> GetTypeFromHandle (EmitContext ec)
9661 		{
9662 			return ec.Module.PredefinedMembers.FieldInfoGetFieldFromHandle;
9663 		}
9664 
GetTypeFromHandleGeneric(EmitContext ec)9665 		protected override PredefinedMember<MethodSpec> GetTypeFromHandleGeneric (EmitContext ec)
9666 		{
9667 			return ec.Module.PredefinedMembers.FieldInfoGetFieldFromHandle2;
9668 		}
9669 	}
9670 
9671 	/// <summary>
9672 	///   Implements the sizeof expression
9673 	/// </summary>
9674 	public class SizeOf : Expression {
9675 		readonly Expression texpr;
9676 		TypeSpec type_queried;
9677 
SizeOf(Expression queried_type, Location l)9678 		public SizeOf (Expression queried_type, Location l)
9679 		{
9680 			this.texpr = queried_type;
9681 			loc = l;
9682 		}
9683 
9684 		public override bool IsSideEffectFree {
9685 			get {
9686 				return true;
9687 			}
9688 		}
9689 
9690 		public Expression TypeExpression {
9691 			get {
9692 				return texpr;
9693 			}
9694 		}
9695 
ContainsEmitWithAwait()9696 		public override bool ContainsEmitWithAwait ()
9697 		{
9698 			return false;
9699 		}
9700 
CreateExpressionTree(ResolveContext ec)9701 		public override Expression CreateExpressionTree (ResolveContext ec)
9702 		{
9703 			Error_PointerInsideExpressionTree (ec);
9704 			return null;
9705 		}
9706 
DoResolve(ResolveContext ec)9707 		protected override Expression DoResolve (ResolveContext ec)
9708 		{
9709 			type_queried = texpr.ResolveAsType (ec);
9710 			if (type_queried == null)
9711 				return null;
9712 
9713 			if (type_queried.IsEnum)
9714 				type_queried = EnumSpec.GetUnderlyingType (type_queried);
9715 
9716 			int size_of = BuiltinTypeSpec.GetSize (type_queried);
9717 			if (size_of > 0) {
9718 				return new IntConstant (ec.BuiltinTypes, size_of, loc);
9719 			}
9720 
9721 			if (!TypeManager.VerifyUnmanaged (ec.Module, type_queried, loc)){
9722 				return null;
9723 			}
9724 
9725 			if (!ec.IsUnsafe) {
9726 				ec.Report.Error (233, loc,
9727 					"`{0}' does not have a predefined size, therefore sizeof can only be used in an unsafe context (consider using System.Runtime.InteropServices.Marshal.SizeOf)",
9728 					type_queried.GetSignatureForError ());
9729 			}
9730 
9731 			type = ec.BuiltinTypes.Int;
9732 			eclass = ExprClass.Value;
9733 			return this;
9734 		}
9735 
Emit(EmitContext ec)9736 		public override void Emit (EmitContext ec)
9737 		{
9738 			ec.Emit (OpCodes.Sizeof, type_queried);
9739 		}
9740 
CloneTo(CloneContext clonectx, Expression t)9741 		protected override void CloneTo (CloneContext clonectx, Expression t)
9742 		{
9743 		}
9744 
Accept(StructuralVisitor visitor)9745 		public override object Accept (StructuralVisitor visitor)
9746 		{
9747 			return visitor.Visit (this);
9748 		}
9749 	}
9750 
9751 	/// <summary>
9752 	///   Implements the qualified-alias-member (::) expression.
9753 	/// </summary>
9754 	public class QualifiedAliasMember : MemberAccess
9755 	{
9756 		readonly string alias;
9757 		public static readonly string GlobalAlias = "global";
9758 
QualifiedAliasMember(string alias, string identifier, Location l)9759 		public QualifiedAliasMember (string alias, string identifier, Location l)
9760 			: base (null, identifier, l)
9761 		{
9762 			this.alias = alias;
9763 		}
9764 
QualifiedAliasMember(string alias, string identifier, TypeArguments targs, Location l)9765 		public QualifiedAliasMember (string alias, string identifier, TypeArguments targs, Location l)
9766 			: base (null, identifier, targs, l)
9767 		{
9768 			this.alias = alias;
9769 		}
9770 
QualifiedAliasMember(string alias, string identifier, int arity, Location l)9771 		public QualifiedAliasMember (string alias, string identifier, int arity, Location l)
9772 			: base (null, identifier, arity, l)
9773 		{
9774 			this.alias = alias;
9775 		}
9776 
9777 		public string Alias {
9778 			get {
9779 				return alias;
9780 			}
9781 		}
9782 
CreateExpressionFromAlias(IMemberContext mc)9783 		public FullNamedExpression CreateExpressionFromAlias (IMemberContext mc)
9784 		{
9785 			if (alias == GlobalAlias)
9786 				return new NamespaceExpression (mc.Module.GlobalRootNamespace, loc);
9787 
9788 			int errors = mc.Module.Compiler.Report.Errors;
9789 			var expr = mc.LookupNamespaceAlias (alias);
9790 			if (expr == null) {
9791 				if (errors == mc.Module.Compiler.Report.Errors)
9792 					mc.Module.Compiler.Report.Error (432, loc, "Alias `{0}' not found", alias);
9793 
9794 				return null;
9795 			}
9796 
9797 			return expr;
9798 		}
9799 
ResolveAsTypeOrNamespace(IMemberContext mc, bool allowUnboundTypeArguments)9800 		public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc, bool allowUnboundTypeArguments)
9801 		{
9802 			expr = CreateExpressionFromAlias (mc);
9803 			if (expr == null)
9804 				return null;
9805 
9806 			return base.ResolveAsTypeOrNamespace (mc, allowUnboundTypeArguments);
9807 		}
9808 
DoResolve(ResolveContext rc)9809 		protected override Expression DoResolve (ResolveContext rc)
9810 		{
9811 			return ResolveAsTypeOrNamespace (rc, false);
9812 		}
9813 
GetSignatureForError()9814 		public override string GetSignatureForError ()
9815 		{
9816 			string name = Name;
9817 			if (targs != null) {
9818 				name = Name + "<" + targs.GetSignatureForError () + ">";
9819 			}
9820 
9821 			return alias + "::" + name;
9822 		}
9823 
HasConditionalAccess()9824 		public override bool HasConditionalAccess ()
9825 		{
9826 			return false;
9827 		}
9828 
LookupNameExpression(ResolveContext rc, MemberLookupRestrictions restrictions)9829 		public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions)
9830 		{
9831 			if ((restrictions & MemberLookupRestrictions.InvocableOnly) != 0) {
9832 				rc.Module.Compiler.Report.Error (687, loc,
9833 					"The namespace alias qualifier `::' cannot be used to invoke a method. Consider using `.' instead",
9834 					GetSignatureForError ());
9835 
9836 				return null;
9837 			}
9838 
9839 			return DoResolve (rc);
9840 		}
9841 
CloneTo(CloneContext clonectx, Expression t)9842 		protected override void CloneTo (CloneContext clonectx, Expression t)
9843 		{
9844 			// Nothing
9845 		}
9846 
Accept(StructuralVisitor visitor)9847 		public override object Accept (StructuralVisitor visitor)
9848 		{
9849 			return visitor.Visit (this);
9850 		}
9851 	}
9852 
9853 	/// <summary>
9854 	///   Implements the member access expression
9855 	/// </summary>
9856 	public class MemberAccess : ATypeNameExpression
9857 	{
9858 		protected Expression expr;
9859 
MemberAccess(Expression expr, string id)9860 		public MemberAccess (Expression expr, string id)
9861 			: base (id, expr.Location)
9862 		{
9863 			this.expr = expr;
9864 		}
9865 
MemberAccess(Expression expr, string identifier, Location loc)9866 		public MemberAccess (Expression expr, string identifier, Location loc)
9867 			: base (identifier, loc)
9868 		{
9869 			this.expr = expr;
9870 		}
9871 
MemberAccess(Expression expr, string identifier, TypeArguments args, Location loc)9872 		public MemberAccess (Expression expr, string identifier, TypeArguments args, Location loc)
9873 			: base (identifier, args, loc)
9874 		{
9875 			this.expr = expr;
9876 		}
9877 
MemberAccess(Expression expr, string identifier, int arity, Location loc)9878 		public MemberAccess (Expression expr, string identifier, int arity, Location loc)
9879 			: base (identifier, arity, loc)
9880 		{
9881 			this.expr = expr;
9882 		}
9883 
9884 		public Expression LeftExpression {
9885 			get {
9886 				return expr;
9887 			}
9888 		}
9889 
9890 		public override Location StartLocation {
9891 			get {
9892 				return expr == null ? loc : expr.StartLocation;
9893 			}
9894 		}
9895 
DoResolve(ResolveContext rc)9896 		protected override Expression DoResolve (ResolveContext rc)
9897 		{
9898 			var e = LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.DontSetConditionalAccess);
9899 			if (e != null)
9900 				e = e.Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.Type | ResolveFlags.MethodGroup);
9901 
9902 			return e;
9903 		}
9904 
DoResolveLValue(ResolveContext rc, Expression rhs)9905 		public override Expression DoResolveLValue (ResolveContext rc, Expression rhs)
9906 		{
9907 			var e = LookupNameExpression (rc, MemberLookupRestrictions.None);
9908 
9909 			if (e is TypeExpr) {
9910 				e.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
9911 				return null;
9912 			}
9913 
9914 			if (e != null)
9915 				e = e.ResolveLValue (rc, rhs);
9916 
9917 			return e;
9918 		}
9919 
Error_OperatorCannotBeApplied(ResolveContext rc, TypeSpec type)9920 		protected virtual void Error_OperatorCannotBeApplied (ResolveContext rc, TypeSpec type)
9921 		{
9922 			if (type == InternalType.NullLiteral && rc.IsRuntimeBinder)
9923 				rc.Report.Error (Report.RuntimeErrorId, loc, "Cannot perform member binding on `null' value");
9924 			else
9925 				expr.Error_OperatorCannotBeApplied (rc, loc, ".", type);
9926 		}
9927 
HasConditionalAccess()9928 		public override bool HasConditionalAccess ()
9929 		{
9930 			return LeftExpression.HasConditionalAccess ();
9931 		}
9932 
IsValidDotExpression(TypeSpec type)9933 		public static bool IsValidDotExpression (TypeSpec type)
9934 		{
9935 			const MemberKind dot_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.Delegate | MemberKind.Enum |
9936 				MemberKind.Interface | MemberKind.TypeParameter | MemberKind.ArrayType  | MemberKind.ByRef;
9937 
9938 			return (type.Kind & dot_kinds) != 0 || type.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
9939 		}
9940 
LookupNameExpression(ResolveContext rc, MemberLookupRestrictions restrictions)9941 		public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions)
9942 		{
9943 			var sn = expr as SimpleName;
9944 			const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type;
9945 
9946 			if (sn != null) {
9947 				expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
9948 
9949 				//
9950 				// Resolve expression which does have type set as we need expression type
9951 				// with disable flow analysis as we don't know whether left side expression
9952 				// is used as variable or type
9953 				//
9954 				if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess || expr is EventExpr) {
9955 					expr = expr.Resolve (rc);
9956 				} else if (expr is TypeParameterExpr) {
9957 					expr.Error_UnexpectedKind (rc, flags, sn.Location);
9958 					expr = null;
9959 				}
9960 			} else {
9961 				if ((restrictions & MemberLookupRestrictions.DontSetConditionalAccess) != 0) {
9962 					using (rc.Set (ResolveContext.Options.DontSetConditionalAccessReceiver)) {
9963 						expr = expr.Resolve (rc, flags);
9964 					}
9965 				} else {
9966 					expr = expr.Resolve (rc, flags);
9967 				}
9968 			}
9969 
9970 			if (expr == null)
9971 				return null;
9972 
9973 			var ns = expr as NamespaceExpression;
9974 			if (ns != null) {
9975 				var retval = ns.LookupTypeOrNamespace (rc, Name, Arity, LookupMode.Normal, loc);
9976 
9977 				if (retval == null) {
9978 					ns.Error_NamespaceDoesNotExist (rc, Name, Arity, loc);
9979 					return null;
9980 				}
9981 
9982 				if (Arity > 0) {
9983 					if (HasTypeArguments)
9984 						return new GenericTypeExpr (retval.Type, targs, loc);
9985 
9986 					targs.Resolve (rc, false);
9987 				}
9988 
9989 				return retval;
9990 			}
9991 
9992 			var cma = this as ConditionalMemberAccess;
9993 
9994 			MemberExpr me;
9995 			TypeSpec expr_type = expr.Type;
9996 			if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
9997 				me = expr as MemberExpr;
9998 				if (me != null)
9999 					me.ResolveInstanceExpression (rc, null);
10000 
10001 				Arguments args = new Arguments (1);
10002 				args.Add (new Argument (expr));
10003 
10004 				if (cma != null)
10005 					return new DynamicConditionalMemberBinder (Name, args, loc);
10006 
10007 				return new DynamicMemberBinder (Name, args, loc);
10008 			}
10009 
10010 			if (cma != null) {
10011 				if (!IsNullPropagatingValid (expr.Type)) {
10012 					expr.Error_OperatorCannotBeApplied (rc, loc, "?", expr.Type);
10013 					return null;
10014 				}
10015 
10016 				if (expr_type.IsNullableType) {
10017 					expr = Nullable.Unwrap.Create (expr.Resolve (rc), true);
10018 					expr_type = expr.Type;
10019 				}
10020 			}
10021 
10022 			if (!IsValidDotExpression (expr_type)) {
10023 				Error_OperatorCannotBeApplied (rc, expr_type);
10024 				return null;
10025 			}
10026 
10027 			var lookup_arity = Arity;
10028 			bool errorMode = false;
10029 			Expression member_lookup;
10030 			while (true) {
10031 				member_lookup = MemberLookup (rc, errorMode, expr_type, Name, lookup_arity, restrictions, loc);
10032 				if (member_lookup == null) {
10033 					//
10034 					// Try to look for extension method when member lookup failed
10035 					//
10036 					if (MethodGroupExpr.IsExtensionMethodArgument (expr)) {
10037 						var methods = rc.LookupExtensionMethod (Name, lookup_arity);
10038 						if (methods != null) {
10039 							var emg = new ExtensionMethodGroupExpr (methods, expr, loc);
10040 							if (HasTypeArguments) {
10041 								if (!targs.Resolve (rc, false))
10042 									return null;
10043 
10044 								emg.SetTypeArguments (rc, targs);
10045 							}
10046 
10047 							if (cma != null)
10048 								emg.ConditionalAccess = true;
10049 
10050 							// TODO: it should really skip the checks bellow
10051 							return emg.Resolve (rc);
10052 						}
10053 					}
10054 				}
10055 
10056 				if (errorMode) {
10057 					if (member_lookup == null) {
10058 						var dep = expr_type.GetMissingDependencies ();
10059 						if (dep != null) {
10060 							ImportedTypeDefinition.Error_MissingDependency (rc, dep, loc);
10061 						} else if (expr is TypeExpr) {
10062 							base.Error_TypeDoesNotContainDefinition (rc, expr_type, Name);
10063 						} else {
10064 							Error_TypeDoesNotContainDefinition (rc, expr_type, Name);
10065 						}
10066 
10067 						return null;
10068 					}
10069 
10070 					if (member_lookup is MethodGroupExpr || member_lookup is PropertyExpr) {
10071 						// Leave it to overload resolution to report correct error
10072 					} else if (!(member_lookup is TypeExpr)) {
10073 						// TODO: rc.SymbolRelatedToPreviousError
10074 						ErrorIsInaccesible (rc, member_lookup.GetSignatureForError (), loc);
10075 					}
10076 					break;
10077 				}
10078 
10079 				if (member_lookup != null)
10080 					break;
10081 
10082 				lookup_arity = 0;
10083 				restrictions &= ~MemberLookupRestrictions.InvocableOnly;
10084 				errorMode = true;
10085 			}
10086 
10087 			TypeExpr texpr = member_lookup as TypeExpr;
10088 			if (texpr != null) {
10089 				if (!(expr is TypeExpr) && (sn == null || expr.ProbeIdenticalTypeName (rc, expr, sn) == expr)) {
10090 					rc.Report.Error (572, loc, "`{0}': cannot reference a type through an expression. Consider using `{1}' instead",
10091 						Name, texpr.GetSignatureForError ());
10092 				}
10093 
10094 				if (!texpr.Type.IsAccessible (rc)) {
10095 					rc.Report.SymbolRelatedToPreviousError (member_lookup.Type);
10096 					ErrorIsInaccesible (rc, member_lookup.Type.GetSignatureForError (), loc);
10097 					return null;
10098 				}
10099 
10100 				if (HasTypeArguments) {
10101 					return new GenericTypeExpr (member_lookup.Type, targs, loc);
10102 				}
10103 
10104 				return member_lookup;
10105 			}
10106 
10107 			me = member_lookup as MemberExpr;
10108 
10109 			if (sn != null && me.IsStatic && (expr = me.ProbeIdenticalTypeName (rc, expr, sn)) != expr) {
10110 				sn = null;
10111 			}
10112 
10113 			if (cma != null) {
10114 				me.ConditionalAccess = true;
10115 			}
10116 
10117 			me = me.ResolveMemberAccess (rc, expr, sn);
10118 
10119 			if (Arity > 0) {
10120 				if (!targs.Resolve (rc, false))
10121 					return null;
10122 
10123 				me.SetTypeArguments (rc, targs);
10124 			}
10125 
10126 			return me;
10127 		}
10128 
ResolveAsTypeOrNamespace(IMemberContext rc, bool allowUnboundTypeArguments)10129 		public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext rc, bool allowUnboundTypeArguments)
10130 		{
10131 			FullNamedExpression fexpr = expr as FullNamedExpression;
10132 			if (fexpr == null) {
10133 				expr.ResolveAsType (rc);
10134 				return null;
10135 			}
10136 
10137 			FullNamedExpression expr_resolved = fexpr.ResolveAsTypeOrNamespace (rc, allowUnboundTypeArguments);
10138 
10139 			if (expr_resolved == null)
10140 				return null;
10141 
10142 			var ns = expr_resolved as NamespaceExpression;
10143 			if (ns != null) {
10144 				FullNamedExpression retval = ns.LookupTypeOrNamespace (rc, Name, Arity, LookupMode.Normal, loc);
10145 
10146 				if (retval == null) {
10147 					ns.Error_NamespaceDoesNotExist (rc, Name, Arity, loc);
10148 				} else if (Arity > 0) {
10149 					if (HasTypeArguments) {
10150 						retval = new GenericTypeExpr (retval.Type, targs, loc);
10151 						if (retval.ResolveAsType (rc) == null)
10152 							return null;
10153 					} else {
10154 						targs.Resolve (rc, allowUnboundTypeArguments);
10155 
10156 						retval = new GenericOpenTypeExpr (retval.Type, loc);
10157 					}
10158 				}
10159 
10160 				return retval;
10161 			}
10162 
10163 			var tnew_expr = expr_resolved.ResolveAsType (rc);
10164 			if (tnew_expr == null)
10165 				return null;
10166 
10167 			TypeSpec expr_type = tnew_expr;
10168 			if (TypeManager.IsGenericParameter (expr_type)) {
10169 				rc.Module.Compiler.Report.Error (704, loc, "A nested type cannot be specified through a type parameter `{0}'",
10170 					tnew_expr.GetSignatureForError ());
10171 				return null;
10172 			}
10173 
10174 			var qam = this as QualifiedAliasMember;
10175 			if (qam != null) {
10176 				rc.Module.Compiler.Report.Error (431, loc,
10177 					"Alias `{0}' cannot be used with `::' since it denotes a type. Consider replacing `::' with `.'",
10178 					qam.Alias);
10179 
10180 			}
10181 
10182 			TypeSpec nested = null;
10183 			while (expr_type != null) {
10184 				nested = MemberCache.FindNestedType (expr_type, Name, Arity, false);
10185 				if (nested == null) {
10186 					if (expr_type == tnew_expr) {
10187 						Error_IdentifierNotFound (rc, expr_type);
10188 						return null;
10189 					}
10190 
10191 					expr_type = tnew_expr;
10192 					nested = MemberCache.FindNestedType (expr_type, Name, Arity, false);
10193 					ErrorIsInaccesible (rc, nested.GetSignatureForError (), loc);
10194 					break;
10195 				}
10196 
10197 				if (nested.IsAccessible (rc))
10198 					break;
10199 
10200 				//
10201 				// Keep looking after inaccessible candidate but only if
10202 				// we are not in same context as the definition itself
10203  				//
10204 				if (expr_type.MemberDefinition == rc.CurrentMemberDefinition)
10205 					break;
10206 
10207 				expr_type = expr_type.BaseType;
10208 			}
10209 
10210 			TypeExpr texpr;
10211 			if (Arity > 0) {
10212 				if (HasTypeArguments) {
10213 					texpr = new GenericTypeExpr (nested, targs, loc);
10214 				} else {
10215 					targs.Resolve (rc, allowUnboundTypeArguments && !(expr_resolved is GenericTypeExpr));
10216 
10217 					texpr = new GenericOpenTypeExpr (nested, loc);
10218 				}
10219 			} else if (expr_resolved is GenericOpenTypeExpr) {
10220 				texpr = new GenericOpenTypeExpr (nested, loc);
10221 			} else {
10222 				texpr = new TypeExpression (nested, loc);
10223 			}
10224 
10225 			if (texpr.ResolveAsType (rc) == null)
10226 				return null;
10227 
10228 			return texpr;
10229 		}
10230 
Error_IdentifierNotFound(IMemberContext rc, TypeSpec expr_type)10231 		public void Error_IdentifierNotFound (IMemberContext rc, TypeSpec expr_type)
10232 		{
10233 			var nested = MemberCache.FindNestedType (expr_type, Name, -System.Math.Max (1, Arity), false);
10234 
10235 			if (nested != null) {
10236 				Error_TypeArgumentsCannotBeUsed (rc, nested, expr.Location);
10237 				return;
10238 			}
10239 
10240 			var any_other_member = MemberLookup (rc, false, expr_type, Name, 0, MemberLookupRestrictions.None, loc);
10241 			if (any_other_member != null) {
10242 				Error_UnexpectedKind (rc, any_other_member, "type", any_other_member.ExprClassName, loc);
10243 				return;
10244 			}
10245 
10246 			rc.Module.Compiler.Report.Error (426, loc, "The nested type `{0}' does not exist in the type `{1}'",
10247 				Name, expr_type.GetSignatureForError ());
10248 		}
10249 
Error_InvalidExpressionStatement(Report report, Location loc)10250 		protected override void Error_InvalidExpressionStatement (Report report, Location loc)
10251 		{
10252 			base.Error_InvalidExpressionStatement (report, LeftExpression.Location);
10253 		}
10254 
Error_TypeDoesNotContainDefinition(ResolveContext ec, TypeSpec type, string name)10255 		public override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name)
10256 		{
10257 			if (ec.Module.Compiler.Settings.Version > LanguageVersion.ISO_2 && !ec.IsRuntimeBinder && MethodGroupExpr.IsExtensionMethodArgument (expr)) {
10258 				ec.Report.SymbolRelatedToPreviousError (type);
10259 
10260 				var cand = ec.Module.GlobalRootNamespace.FindExtensionMethodNamespaces (ec, name, Arity);
10261 				string missing;
10262 				// a using directive or an assembly reference
10263 				if (cand != null) {
10264 					missing = "`" + string.Join ("' or `", cand.ToArray ()) + "' using directive";
10265 				} else {
10266 					missing = "an assembly reference";
10267 				}
10268 
10269 				ec.Report.Error (1061, loc,
10270 					"Type `{0}' does not contain a definition for `{1}' and no extension method `{1}' of type `{0}' could be found. Are you missing {2}?",
10271 					type.GetSignatureForError (), name, missing);
10272 				return;
10273 			}
10274 
10275 			base.Error_TypeDoesNotContainDefinition (ec, type, name);
10276 		}
10277 
GetSignatureForError()10278 		public override string GetSignatureForError ()
10279 		{
10280 			return expr.GetSignatureForError () + "." + base.GetSignatureForError ();
10281 		}
10282 
CloneTo(CloneContext clonectx, Expression t)10283 		protected override void CloneTo (CloneContext clonectx, Expression t)
10284 		{
10285 			MemberAccess target = (MemberAccess) t;
10286 
10287 			target.expr = expr.Clone (clonectx);
10288 		}
10289 
Accept(StructuralVisitor visitor)10290 		public override object Accept (StructuralVisitor visitor)
10291 		{
10292 			return visitor.Visit (this);
10293 		}
10294 	}
10295 
10296 	public class ConditionalMemberAccess : MemberAccess
10297 	{
ConditionalMemberAccess(Expression expr, string identifier, TypeArguments args, Location loc)10298 		public ConditionalMemberAccess (Expression expr, string identifier, TypeArguments args, Location loc)
10299 			: base (expr, identifier, args, loc)
10300 		{
10301 		}
10302 
HasConditionalAccess()10303 		public override bool HasConditionalAccess ()
10304 		{
10305 			return true;
10306 		}
10307 	}
10308 
10309 	/// <summary>
10310 	///   Implements checked expressions
10311 	/// </summary>
10312 	public class CheckedExpr : Expression {
10313 
10314 		public Expression Expr;
10315 
CheckedExpr(Expression e, Location l)10316 		public CheckedExpr (Expression e, Location l)
10317 		{
10318 			Expr = e;
10319 			loc = l;
10320 		}
10321 
ContainsEmitWithAwait()10322 		public override bool ContainsEmitWithAwait ()
10323 		{
10324 			return Expr.ContainsEmitWithAwait ();
10325 		}
10326 
CreateExpressionTree(ResolveContext ec)10327 		public override Expression CreateExpressionTree (ResolveContext ec)
10328 		{
10329 			using (ec.With (ResolveContext.Options.AllCheckStateFlags, true))
10330 				return Expr.CreateExpressionTree (ec);
10331 		}
10332 
DoResolve(ResolveContext ec)10333 		protected override Expression DoResolve (ResolveContext ec)
10334 		{
10335 			using (ec.With (ResolveContext.Options.AllCheckStateFlags, true))
10336 				Expr = Expr.Resolve (ec);
10337 
10338 			if (Expr == null)
10339 				return null;
10340 
10341 			if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression || Expr is DefaultValueExpression)
10342 				return Expr;
10343 
10344 			eclass = Expr.eclass;
10345 			type = Expr.Type;
10346 			return this;
10347 		}
10348 
Emit(EmitContext ec)10349 		public override void Emit (EmitContext ec)
10350 		{
10351 			using (ec.With (EmitContext.Options.CheckedScope, true))
10352 				Expr.Emit (ec);
10353 		}
10354 
EmitBranchable(EmitContext ec, Label target, bool on_true)10355 		public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
10356 		{
10357 			using (ec.With (EmitContext.Options.CheckedScope, true))
10358 				Expr.EmitBranchable (ec, target, on_true);
10359 		}
10360 
FlowAnalysis(FlowAnalysisContext fc)10361 		public override void FlowAnalysis (FlowAnalysisContext fc)
10362 		{
10363 			Expr.FlowAnalysis (fc);
10364 		}
10365 
MakeExpression(BuilderContext ctx)10366 		public override SLE.Expression MakeExpression (BuilderContext ctx)
10367 		{
10368 			using (ctx.With (BuilderContext.Options.CheckedScope, true)) {
10369 				return Expr.MakeExpression (ctx);
10370 			}
10371 		}
10372 
CloneTo(CloneContext clonectx, Expression t)10373 		protected override void CloneTo (CloneContext clonectx, Expression t)
10374 		{
10375 			CheckedExpr target = (CheckedExpr) t;
10376 
10377 			target.Expr = Expr.Clone (clonectx);
10378 		}
10379 
Accept(StructuralVisitor visitor)10380 		public override object Accept (StructuralVisitor visitor)
10381 		{
10382 			return visitor.Visit (this);
10383 		}
10384 	}
10385 
10386 	/// <summary>
10387 	///   Implements the unchecked expression
10388 	/// </summary>
10389 	public class UnCheckedExpr : Expression {
10390 
10391 		public Expression Expr;
10392 
UnCheckedExpr(Expression e, Location l)10393 		public UnCheckedExpr (Expression e, Location l)
10394 		{
10395 			Expr = e;
10396 			loc = l;
10397 		}
10398 
ContainsEmitWithAwait()10399 		public override bool ContainsEmitWithAwait ()
10400 		{
10401 			return Expr.ContainsEmitWithAwait ();
10402 		}
10403 
CreateExpressionTree(ResolveContext ec)10404 		public override Expression CreateExpressionTree (ResolveContext ec)
10405 		{
10406 			using (ec.With (ResolveContext.Options.AllCheckStateFlags, false))
10407 				return Expr.CreateExpressionTree (ec);
10408 		}
10409 
DoResolve(ResolveContext ec)10410 		protected override Expression DoResolve (ResolveContext ec)
10411 		{
10412 			using (ec.With (ResolveContext.Options.AllCheckStateFlags, false))
10413 				Expr = Expr.Resolve (ec);
10414 
10415 			if (Expr == null)
10416 				return null;
10417 
10418 			if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression || Expr is DefaultValueExpression)
10419 				return Expr;
10420 
10421 			eclass = Expr.eclass;
10422 			type = Expr.Type;
10423 			return this;
10424 		}
10425 
Emit(EmitContext ec)10426 		public override void Emit (EmitContext ec)
10427 		{
10428 			using (ec.With (EmitContext.Options.CheckedScope, false))
10429 				Expr.Emit (ec);
10430 		}
10431 
EmitBranchable(EmitContext ec, Label target, bool on_true)10432 		public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
10433 		{
10434 			using (ec.With (EmitContext.Options.CheckedScope, false))
10435 				Expr.EmitBranchable (ec, target, on_true);
10436 		}
10437 
FlowAnalysis(FlowAnalysisContext fc)10438 		public override void FlowAnalysis (FlowAnalysisContext fc)
10439 		{
10440 			Expr.FlowAnalysis (fc);
10441 		}
10442 
CloneTo(CloneContext clonectx, Expression t)10443 		protected override void CloneTo (CloneContext clonectx, Expression t)
10444 		{
10445 			UnCheckedExpr target = (UnCheckedExpr) t;
10446 
10447 			target.Expr = Expr.Clone (clonectx);
10448 		}
10449 
Accept(StructuralVisitor visitor)10450 		public override object Accept (StructuralVisitor visitor)
10451 		{
10452 			return visitor.Visit (this);
10453 		}
10454 	}
10455 
10456 	/// <summary>
10457 	///   An Element Access expression.
10458 	///
10459 	///   During semantic analysis these are transformed into
10460 	///   IndexerAccess, ArrayAccess or a PointerArithmetic.
10461 	/// </summary>
10462 	public class ElementAccess : Expression
10463 	{
10464 		public Arguments Arguments;
10465 		public Expression Expr;
10466 		bool conditional_access_receiver;
10467 
ElementAccess(Expression e, Arguments args, Location loc)10468 		public ElementAccess (Expression e, Arguments args, Location loc)
10469 		{
10470 			Expr = e;
10471 			this.loc = loc;
10472 			this.Arguments = args;
10473 		}
10474 
10475 		public bool ConditionalAccess { get; set; }
10476 
10477 		public override Location StartLocation {
10478 			get {
10479 				return Expr.StartLocation;
10480 			}
10481 		}
10482 
ContainsEmitWithAwait()10483 		public override bool ContainsEmitWithAwait ()
10484 		{
10485 			return Expr.ContainsEmitWithAwait () || Arguments.ContainsEmitWithAwait ();
10486 		}
10487 
10488 		//
10489 		// We perform some simple tests, and then to "split" the emit and store
10490 		// code we create an instance of a different class, and return that.
10491 		//
CreateAccessExpression(ResolveContext ec, bool conditionalAccessReceiver)10492 		Expression CreateAccessExpression (ResolveContext ec, bool conditionalAccessReceiver)
10493 		{
10494 			if (conditionalAccessReceiver)
10495 				ec.Set (ResolveContext.Options.DontSetConditionalAccessReceiver);
10496 
10497 			Expr = Expr.Resolve (ec);
10498 
10499 			if (conditionalAccessReceiver)
10500 				ec.With (ResolveContext.Options.DontSetConditionalAccessReceiver, false);
10501 
10502 			if (Expr == null)
10503 				return null;
10504 
10505 			type = Expr.Type;
10506 
10507 			if (ConditionalAccess && !IsNullPropagatingValid (type)) {
10508 				Error_OperatorCannotBeApplied (ec, loc, "?", type);
10509 				return null;
10510 			}
10511 
10512 			if (type.IsArray) {
10513 				var aa = new ArrayAccess (this, loc) {
10514 					ConditionalAccess = ConditionalAccess,
10515 				};
10516 
10517 				if (conditionalAccessReceiver)
10518 					aa.SetConditionalAccessReceiver ();
10519 
10520 				return aa;
10521 			}
10522 
10523 			if (type.IsPointer)
10524 				return Expr.MakePointerAccess (ec, type, Arguments);
10525 
10526 			FieldExpr fe = Expr as FieldExpr;
10527 			if (fe != null) {
10528 				var ff = fe.Spec as FixedFieldSpec;
10529 				if (ff != null) {
10530 					return Expr.MakePointerAccess (ec, ff.ElementType, Arguments);
10531 				}
10532 			}
10533 
10534 			var indexers = MemberCache.FindMembers (type, MemberCache.IndexerNameAlias, false);
10535 			if (indexers != null || type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
10536 				var indexer = new IndexerExpr (indexers, type, this) {
10537 					ConditionalAccess = ConditionalAccess
10538 				};
10539 
10540 				if (conditionalAccessReceiver)
10541 					indexer.SetConditionalAccessReceiver ();
10542 
10543 				return indexer;
10544 			}
10545 
10546 			Error_CannotApplyIndexing (ec, type, loc);
10547 
10548 			return null;
10549 		}
10550 
CreateExpressionTree(ResolveContext ec)10551 		public override Expression CreateExpressionTree (ResolveContext ec)
10552 		{
10553 			Arguments args = Arguments.CreateForExpressionTree (ec, Arguments,
10554 				Expr.CreateExpressionTree (ec));
10555 
10556 			return CreateExpressionFactoryCall (ec, "ArrayIndex", args);
10557 		}
10558 
Error_CannotApplyIndexing(ResolveContext rc, TypeSpec type, Location loc)10559 		public static void Error_CannotApplyIndexing (ResolveContext rc, TypeSpec type, Location loc)
10560 		{
10561 			if (type != InternalType.ErrorType) {
10562 				rc.Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `{0}'",
10563 					type.GetSignatureForError ());
10564 			}
10565 		}
10566 
HasConditionalAccess()10567 		public override bool HasConditionalAccess ()
10568 		{
10569 			return ConditionalAccess || Expr.HasConditionalAccess ();
10570 		}
10571 
ResolveConditionalAccessReceiver(ResolveContext rc)10572 		void ResolveConditionalAccessReceiver (ResolveContext rc)
10573 		{
10574 			if (!rc.HasSet (ResolveContext.Options.DontSetConditionalAccessReceiver) && HasConditionalAccess ()) {
10575 				conditional_access_receiver = true;
10576 			}
10577 		}
10578 
DoResolve(ResolveContext rc)10579 		protected override Expression DoResolve (ResolveContext rc)
10580 		{
10581 			ResolveConditionalAccessReceiver (rc);
10582 
10583 			var expr = CreateAccessExpression (rc, conditional_access_receiver);
10584 			if (expr == null)
10585 				return null;
10586 
10587 			return expr.Resolve (rc);
10588 		}
10589 
DoResolveLValue(ResolveContext ec, Expression rhs)10590 		public override Expression DoResolveLValue (ResolveContext ec, Expression rhs)
10591 		{
10592 			var res = CreateAccessExpression (ec, false);
10593 			if (res == null)
10594 				return null;
10595 
10596 			return res.ResolveLValue (ec, rhs);
10597 		}
10598 
Emit(EmitContext ec)10599 		public override void Emit (EmitContext ec)
10600 		{
10601 			throw new Exception ("Should never be reached");
10602 		}
10603 
FlowAnalysis(FlowAnalysisContext fc)10604 		public override void FlowAnalysis (FlowAnalysisContext fc)
10605 		{
10606 			Expr.FlowAnalysis (fc);
10607 
10608 			Arguments.FlowAnalysis (fc);
10609 		}
10610 
GetSignatureForError()10611 		public override string GetSignatureForError ()
10612 		{
10613 			return Expr.GetSignatureForError ();
10614 		}
10615 
CloneTo(CloneContext clonectx, Expression t)10616 		protected override void CloneTo (CloneContext clonectx, Expression t)
10617 		{
10618 			ElementAccess target = (ElementAccess) t;
10619 
10620 			target.Expr = Expr.Clone (clonectx);
10621 			if (Arguments != null)
10622 				target.Arguments = Arguments.Clone (clonectx);
10623 		}
10624 
Accept(StructuralVisitor visitor)10625 		public override object Accept (StructuralVisitor visitor)
10626 		{
10627 			return visitor.Visit (this);
10628 		}
10629 	}
10630 
10631 	/// <summary>
10632 	///   Implements array access
10633 	/// </summary>
10634 	public class ArrayAccess : Expression, IDynamicAssign, IMemoryLocation {
10635 		//
10636 		// Points to our "data" repository
10637 		//
10638 		ElementAccess ea;
10639 
10640 		LocalTemporary temp;
10641 		bool prepared;
10642 		bool? has_await_args;
10643 		bool conditional_access_receiver;
10644 
ArrayAccess(ElementAccess ea_data, Location l)10645 		public ArrayAccess (ElementAccess ea_data, Location l)
10646 		{
10647 			ea = ea_data;
10648 			loc = l;
10649 		}
10650 
10651 		public bool ConditionalAccess { get; set; }
10652 
AddressOf(EmitContext ec, AddressOp mode)10653 		public void AddressOf (EmitContext ec, AddressOp mode)
10654 		{
10655 			var ac = (ArrayContainer) ea.Expr.Type;
10656 
10657 			if (!has_await_args.HasValue && ec.HasSet (BuilderContext.Options.AsyncBody) && ea.Arguments.ContainsEmitWithAwait ()) {
10658 				LoadInstanceAndArguments (ec, false, true);
10659 			}
10660 
10661 			LoadInstanceAndArguments (ec, false, false);
10662 
10663 			if (ac.Element.IsGenericParameter && mode == AddressOp.Load)
10664 				ec.Emit (OpCodes.Readonly);
10665 
10666 			ec.EmitArrayAddress (ac);
10667 		}
10668 
CreateExpressionTree(ResolveContext ec)10669 		public override Expression CreateExpressionTree (ResolveContext ec)
10670 		{
10671 			if (ConditionalAccess)
10672 				Error_NullShortCircuitInsideExpressionTree (ec);
10673 
10674 			return ea.CreateExpressionTree (ec);
10675 		}
10676 
ContainsEmitWithAwait()10677 		public override bool ContainsEmitWithAwait ()
10678 		{
10679 			return ea.ContainsEmitWithAwait ();
10680 		}
10681 
DoResolveLValue(ResolveContext ec, Expression right_side)10682 		public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
10683 		{
10684 			if (HasConditionalAccess ())
10685 				Error_NullPropagatingLValue (ec);
10686 
10687 			return DoResolve (ec);
10688 		}
10689 
DoResolve(ResolveContext ec)10690 		protected override Expression DoResolve (ResolveContext ec)
10691 		{
10692 			// dynamic is used per argument in ConvertExpressionToArrayIndex case
10693 			bool dynamic;
10694 			ea.Arguments.Resolve (ec, out dynamic);
10695 
10696 			var ac = ea.Expr.Type as ArrayContainer;
10697 			int rank = ea.Arguments.Count;
10698 			if (ac.Rank != rank) {
10699 				ec.Report.Error (22, ea.Location, "Wrong number of indexes `{0}' inside [], expected `{1}'",
10700 					  rank.ToString (), ac.Rank.ToString ());
10701 				return null;
10702 			}
10703 
10704 			type = ac.Element;
10705 			if (type.IsPointer) {
10706 				if (ec.CurrentIterator != null) {
10707 					UnsafeInsideIteratorError (ec, ea.Location);
10708 				} else if (!ec.IsUnsafe) {
10709 					UnsafeError (ec, ea.Location);
10710 				}
10711 			}
10712 
10713 			if (conditional_access_receiver)
10714 				type = LiftMemberType (ec, type);
10715 
10716 			foreach (Argument a in ea.Arguments) {
10717 				var na = a as NamedArgument;
10718 				if (na != null)
10719 					ElementAccess.Error_NamedArgument (na, ec.Report);
10720 
10721 				a.Expr = ConvertExpressionToArrayIndex (ec, a.Expr);
10722 			}
10723 
10724 			eclass = ExprClass.Variable;
10725 
10726 			return this;
10727 		}
10728 
Error_NegativeArrayIndex(ResolveContext ec, Location loc)10729 		protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc)
10730 		{
10731 			ec.Report.Warning (251, 2, loc, "Indexing an array with a negative index (array indices always start at zero)");
10732 		}
10733 
FlowAnalysis(FlowAnalysisContext fc)10734 		public override void FlowAnalysis (FlowAnalysisContext fc)
10735 		{
10736 			var da = conditional_access_receiver ? fc.BranchDefiniteAssignment () : null;
10737 
10738 			ea.FlowAnalysis (fc);
10739 
10740 			if (conditional_access_receiver)
10741 				fc.DefiniteAssignment = da;
10742 		}
10743 
HasConditionalAccess()10744 		public override bool HasConditionalAccess ()
10745 		{
10746 			return ConditionalAccess || ea.Expr.HasConditionalAccess ();
10747 		}
10748 
10749 		//
10750 		// Load the array arguments into the stack.
10751 		//
LoadInstanceAndArguments(EmitContext ec, bool duplicateArguments, bool prepareAwait)10752 		void LoadInstanceAndArguments (EmitContext ec, bool duplicateArguments, bool prepareAwait)
10753 		{
10754 			if (prepareAwait) {
10755 				ea.Expr = ea.Expr.EmitToField (ec);
10756 			} else {
10757 				var ie = new InstanceEmitter (ea.Expr, false);
10758 				ie.Emit (ec, ConditionalAccess);
10759 
10760 				if (duplicateArguments) {
10761 					ec.Emit (OpCodes.Dup);
10762 
10763 					var copy = new LocalTemporary (ea.Expr.Type);
10764 					copy.Store (ec);
10765 					ea.Expr = copy;
10766 				}
10767 			}
10768 
10769 			var dup_args = ea.Arguments.Emit (ec, duplicateArguments, prepareAwait);
10770 			if (dup_args != null)
10771 				ea.Arguments = dup_args;
10772 		}
10773 
Emit(EmitContext ec, bool leave_copy)10774 		public void Emit (EmitContext ec, bool leave_copy)
10775 		{
10776 			if (prepared) {
10777 				ec.EmitLoadFromPtr (type);
10778 			} else {
10779 				if (!has_await_args.HasValue && ec.HasSet (BuilderContext.Options.AsyncBody) && ea.Arguments.ContainsEmitWithAwait ()) {
10780 					LoadInstanceAndArguments (ec, false, true);
10781 				}
10782 
10783 				if (conditional_access_receiver)
10784 					ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ());
10785 
10786 				var ac = (ArrayContainer) ea.Expr.Type;
10787 				LoadInstanceAndArguments (ec, false, false);
10788 				ec.EmitArrayLoad (ac);
10789 
10790 				if (conditional_access_receiver)
10791 					ec.CloseConditionalAccess (type.IsNullableType && type != ac.Element ? type : null);
10792 			}
10793 
10794 			if (leave_copy) {
10795 				ec.Emit (OpCodes.Dup);
10796 				temp = new LocalTemporary (this.type);
10797 				temp.Store (ec);
10798 			}
10799 		}
10800 
Emit(EmitContext ec)10801 		public override void Emit (EmitContext ec)
10802 		{
10803 			Emit (ec, false);
10804 		}
10805 
EmitAssign(EmitContext ec, Expression source, bool leave_copy, bool isCompound)10806 		public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
10807 		{
10808 			var ac = (ArrayContainer) ea.Expr.Type;
10809 			TypeSpec t = source.Type;
10810 
10811 			has_await_args = ec.HasSet (BuilderContext.Options.AsyncBody) && (ea.Arguments.ContainsEmitWithAwait () || source.ContainsEmitWithAwait ());
10812 
10813 			//
10814 			// When we are dealing with a struct, get the address of it to avoid value copy
10815 			// Same cannot be done for reference type because array covariance and the
10816 			// check in ldelema requires to specify the type of array element stored at the index
10817 			//
10818 			if (t.IsStruct && ((isCompound && !(source is DynamicExpressionStatement)) || !BuiltinTypeSpec.IsPrimitiveType (t))) {
10819 				LoadInstanceAndArguments (ec, false, has_await_args.Value);
10820 
10821 				if (has_await_args.Value) {
10822 					if (source.ContainsEmitWithAwait ()) {
10823 						source = source.EmitToField (ec);
10824 						isCompound = false;
10825 						prepared = true;
10826 					}
10827 
10828 					LoadInstanceAndArguments (ec, isCompound, false);
10829 				} else {
10830 					prepared = true;
10831 				}
10832 
10833 				ec.EmitArrayAddress (ac);
10834 
10835 				if (isCompound) {
10836 					ec.Emit (OpCodes.Dup);
10837 					prepared = true;
10838 				}
10839 			} else {
10840 				LoadInstanceAndArguments (ec, isCompound, has_await_args.Value);
10841 
10842 				if (has_await_args.Value) {
10843 					if (source.ContainsEmitWithAwait ())
10844 						source = source.EmitToField (ec);
10845 
10846 					LoadInstanceAndArguments (ec, false, false);
10847 				}
10848 			}
10849 
10850 			source.Emit (ec);
10851 
10852 			if (isCompound) {
10853 				var lt = ea.Expr as LocalTemporary;
10854 				if (lt != null)
10855 					lt.Release (ec);
10856 			}
10857 
10858 			if (leave_copy) {
10859 				ec.Emit (OpCodes.Dup);
10860 				temp = new LocalTemporary (this.type);
10861 				temp.Store (ec);
10862 			}
10863 
10864 			if (prepared) {
10865 				ec.EmitStoreFromPtr (t);
10866 			} else {
10867 				ec.EmitArrayStore (ac);
10868 			}
10869 
10870 			if (temp != null) {
10871 				temp.Emit (ec);
10872 				temp.Release (ec);
10873 			}
10874 		}
10875 
EmitToField(EmitContext ec)10876 		public override Expression EmitToField (EmitContext ec)
10877 		{
10878 			//
10879 			// Have to be specialized for arrays to get access to
10880 			// underlying element. Instead of another result copy we
10881 			// need direct access to element
10882 			//
10883 			// Consider:
10884 			//
10885 			// CallRef (ref a[await Task.Factory.StartNew (() => 1)]);
10886 			//
10887 			ea.Expr = ea.Expr.EmitToField (ec);
10888 			ea.Arguments = ea.Arguments.Emit (ec, false, true);
10889 			return this;
10890 		}
10891 
MakeAssignExpression(BuilderContext ctx, Expression source)10892 		public SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source)
10893 		{
10894 			return SLE.Expression.ArrayAccess (ea.Expr.MakeExpression (ctx), MakeExpressionArguments (ctx));
10895 		}
10896 
MakeExpression(BuilderContext ctx)10897 		public override SLE.Expression MakeExpression (BuilderContext ctx)
10898 		{
10899 			return SLE.Expression.ArrayIndex (ea.Expr.MakeExpression (ctx), MakeExpressionArguments (ctx));
10900 		}
10901 
MakeExpressionArguments(BuilderContext ctx)10902 		SLE.Expression[] MakeExpressionArguments (BuilderContext ctx)
10903 		{
10904 			using (ctx.With (BuilderContext.Options.CheckedScope, true)) {
10905 				return Arguments.MakeExpression (ea.Arguments, ctx);
10906 			}
10907 		}
10908 
SetConditionalAccessReceiver()10909 		public void SetConditionalAccessReceiver ()
10910 		{
10911 			conditional_access_receiver = true;
10912 		}
10913 	}
10914 
10915 	//
10916 	// Indexer access expression
10917 	//
10918 	class IndexerExpr : PropertyOrIndexerExpr<IndexerSpec>, OverloadResolver.IBaseMembersProvider
10919 	{
10920 		IList<MemberSpec> indexers;
10921 		Arguments arguments;
10922 		TypeSpec queried_type;
10923 
IndexerExpr(IList<MemberSpec> indexers, TypeSpec queriedType, ElementAccess ea)10924 		public IndexerExpr (IList<MemberSpec> indexers, TypeSpec queriedType, ElementAccess ea)
10925 			: this (indexers, queriedType, ea.Expr, ea.Arguments, ea.Location)
10926 		{
10927 		}
10928 
IndexerExpr(IList<MemberSpec> indexers, TypeSpec queriedType, Expression instance, Arguments args, Location loc)10929 		public IndexerExpr (IList<MemberSpec> indexers, TypeSpec queriedType, Expression instance, Arguments args, Location loc)
10930 			: base (loc)
10931 		{
10932 			this.indexers = indexers;
10933 			this.queried_type = queriedType;
10934 			this.InstanceExpression = instance;
10935 			this.arguments = args;
10936 		}
10937 
10938 		#region Properties
10939 
10940 		protected override Arguments Arguments {
10941 			get {
10942 				return arguments;
10943 			}
10944 			set {
10945 				arguments = value;
10946 			}
10947 		}
10948 
10949 		protected override TypeSpec DeclaringType {
10950 			get {
10951 				return best_candidate.DeclaringType;
10952 			}
10953 		}
10954 
10955 		public override bool IsInstance {
10956 			get {
10957 				return true;
10958 			}
10959 		}
10960 
10961 		public override bool IsStatic {
10962 			get {
10963 				return false;
10964 			}
10965 		}
10966 
10967 		public override string KindName {
10968 			get { return "indexer"; }
10969 		}
10970 
10971 		public override string Name {
10972 			get {
10973 				return "this";
10974 			}
10975 		}
10976 
10977 		#endregion
10978 
ContainsEmitWithAwait()10979 		public override bool ContainsEmitWithAwait ()
10980 		{
10981 			return base.ContainsEmitWithAwait () || arguments.ContainsEmitWithAwait ();
10982 		}
10983 
CreateExpressionTree(ResolveContext ec)10984 		public override Expression CreateExpressionTree (ResolveContext ec)
10985 		{
10986 			if (ConditionalAccess) {
10987 				Error_NullShortCircuitInsideExpressionTree (ec);
10988 			}
10989 
10990 			Arguments args = Arguments.CreateForExpressionTree (ec, arguments,
10991 				InstanceExpression.CreateExpressionTree (ec),
10992 				new TypeOfMethod (Getter, loc));
10993 
10994 			return CreateExpressionFactoryCall (ec, "Call", args);
10995 		}
10996 
EmitAssign(EmitContext ec, Expression source, bool leave_copy, bool isCompound)10997 		public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
10998 		{
10999 			LocalTemporary await_source_arg = null;
11000 
11001 			if (isCompound) {
11002 				emitting_compound_assignment = true;
11003 				if (source is DynamicExpressionStatement) {
11004 					Emit (ec, false);
11005 				} else {
11006 					source.Emit (ec);
11007 				}
11008 				emitting_compound_assignment = false;
11009 
11010 				if (has_await_arguments) {
11011 					await_source_arg = new LocalTemporary (Type);
11012 					await_source_arg.Store (ec);
11013 
11014 					arguments.Add (new Argument (await_source_arg));
11015 
11016 					if (leave_copy) {
11017 						temp = await_source_arg;
11018 					}
11019 
11020 					has_await_arguments = false;
11021 				} else {
11022 					arguments = null;
11023 
11024 					if (leave_copy) {
11025 						ec.Emit (OpCodes.Dup);
11026 						temp = new LocalTemporary (Type);
11027 						temp.Store (ec);
11028 					}
11029 				}
11030 			} else {
11031 				if (leave_copy) {
11032 					if (ec.HasSet (BuilderContext.Options.AsyncBody) && (arguments.ContainsEmitWithAwait () || source.ContainsEmitWithAwait ())) {
11033 						source = source.EmitToField (ec);
11034 					} else {
11035 						temp = new LocalTemporary (Type);
11036 						source.Emit (ec);
11037 						temp.Store (ec);
11038 						source = temp;
11039 					}
11040 				}
11041 
11042 				arguments.Add (new Argument (source));
11043 			}
11044 
11045 			var call = new CallEmitter ();
11046 			call.InstanceExpression = InstanceExpression;
11047 			if (arguments == null)
11048 				call.InstanceExpressionOnStack = true;
11049 
11050 			call.Emit (ec, Setter, arguments, loc);
11051 
11052 			if (temp != null) {
11053 				temp.Emit (ec);
11054 				temp.Release (ec);
11055 			} else if (leave_copy) {
11056 				source.Emit (ec);
11057 			}
11058 
11059 			if (await_source_arg != null) {
11060 				await_source_arg.Release (ec);
11061 			}
11062 		}
11063 
FlowAnalysis(FlowAnalysisContext fc)11064 		public override void FlowAnalysis (FlowAnalysisContext fc)
11065 		{
11066 			var da = conditional_access_receiver ? fc.BranchDefiniteAssignment () : null;
11067 
11068 			base.FlowAnalysis (fc);
11069 			arguments.FlowAnalysis (fc);
11070 
11071 			if (conditional_access_receiver)
11072 				fc.DefiniteAssignment = da;
11073 		}
11074 
GetSignatureForError()11075 		public override string GetSignatureForError ()
11076 		{
11077 			return best_candidate.GetSignatureForError ();
11078 		}
11079 
MakeAssignExpression(BuilderContext ctx, Expression source)11080 		public override SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source)
11081 		{
11082 #if STATIC
11083 			throw new NotSupportedException ();
11084 #else
11085 			var value = new[] { source.MakeExpression (ctx) };
11086 			var args = Arguments.MakeExpression (arguments, ctx).Concat (value);
11087 			return SLE.Expression.Block (
11088 					SLE.Expression.Call (InstanceExpression.MakeExpression (ctx), (MethodInfo) Setter.GetMetaInfo (), args),
11089 					value [0]);
11090 #endif
11091 		}
11092 
MakeExpression(BuilderContext ctx)11093 		public override SLE.Expression MakeExpression (BuilderContext ctx)
11094 		{
11095 #if STATIC
11096 			return base.MakeExpression (ctx);
11097 #else
11098 			var args = Arguments.MakeExpression (arguments, ctx);
11099 			return SLE.Expression.Call (InstanceExpression.MakeExpression (ctx), (MethodInfo) Getter.GetMetaInfo (), args);
11100 #endif
11101 		}
11102 
OverloadResolve(ResolveContext rc, Expression right_side)11103 		protected override Expression OverloadResolve (ResolveContext rc, Expression right_side)
11104 		{
11105 			if (best_candidate != null)
11106 				return this;
11107 
11108 			eclass = ExprClass.IndexerAccess;
11109 
11110 			bool dynamic;
11111 			using (rc.With (ResolveContext.Options.DontSetConditionalAccessReceiver, false)) {
11112 				arguments.Resolve (rc, out dynamic);
11113 			}
11114 
11115 			if (indexers == null && InstanceExpression.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
11116 				dynamic = true;
11117 			} else {
11118 				var res = new OverloadResolver (indexers, OverloadResolver.Restrictions.None, loc);
11119 				res.BaseMembersProvider = this;
11120 				res.InstanceQualifier = this;
11121 
11122 				// TODO: Do I need 2 argument sets?
11123 				best_candidate = res.ResolveMember<IndexerSpec> (rc, ref arguments);
11124 				if (best_candidate != null)
11125 					type = res.BestCandidateReturnType;
11126 				else if (!res.BestCandidateIsDynamic)
11127 					return null;
11128 			}
11129 
11130 			//
11131 			// It has dynamic arguments
11132 			//
11133 			if (dynamic) {
11134 				Arguments args = new Arguments (arguments.Count + 1);
11135 				if (IsBase) {
11136 					rc.Report.Error (1972, loc,
11137 						"The indexer base access cannot be dynamically dispatched. Consider casting the dynamic arguments or eliminating the base access");
11138 				} else {
11139 					args.Add (new Argument (InstanceExpression));
11140 				}
11141 				args.AddRange (arguments);
11142 
11143 				best_candidate = null;
11144 				return new DynamicIndexBinder (args, conditional_access_receiver, ConditionalAccess, loc);
11145 			}
11146 
11147 			//
11148 			// Try to avoid resolving left expression again
11149 			//
11150 			if (right_side != null)
11151 				ResolveInstanceExpression (rc, right_side);
11152 
11153 			return this;
11154 		}
11155 
CloneTo(CloneContext clonectx, Expression t)11156 		protected override void CloneTo (CloneContext clonectx, Expression t)
11157 		{
11158 			IndexerExpr target = (IndexerExpr) t;
11159 
11160 			if (arguments != null)
11161 				target.arguments = arguments.Clone (clonectx);
11162 		}
11163 
SetConditionalAccessReceiver()11164 		public void SetConditionalAccessReceiver ()
11165 		{
11166 			conditional_access_receiver = true;
11167 		}
11168 
SetTypeArguments(ResolveContext ec, TypeArguments ta)11169 		public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
11170 		{
11171 			Error_TypeArgumentsCannotBeUsed (ec, "indexer", GetSignatureForError (), loc);
11172 		}
11173 
11174 		#region IBaseMembersProvider Members
11175 
OverloadResolver.IBaseMembersProvider.GetBaseMembers(TypeSpec type)11176 		IList<MemberSpec> OverloadResolver.IBaseMembersProvider.GetBaseMembers (TypeSpec type)
11177 		{
11178 			var baseType = type.BaseType;
11179 			var members = baseType == null ? null : MemberCache.FindMembers (baseType, MemberCache.IndexerNameAlias, false);
11180 
11181 			if (members == null && !type.IsInterface) {
11182 				var tps = queried_type as TypeParameterSpec;
11183 				if (tps != null)
11184 					members = MemberCache.FindInterfaceMembers (tps, MemberCache.IndexerNameAlias);
11185 			}
11186 
11187 			return members;
11188 		}
11189 
OverloadResolver.IBaseMembersProvider.GetOverrideMemberParameters(MemberSpec member)11190 		IParametersMember OverloadResolver.IBaseMembersProvider.GetOverrideMemberParameters (MemberSpec member)
11191 		{
11192 			if (queried_type == member.DeclaringType)
11193 				return null;
11194 
11195 			var filter = new MemberFilter (MemberCache.IndexerNameAlias, 0, MemberKind.Indexer, ((IndexerSpec) member).Parameters, null);
11196 			return MemberCache.FindMember (queried_type, filter, BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly) as IParametersMember;
11197 		}
11198 
OverloadResolver.IBaseMembersProvider.LookupExtensionMethod(ResolveContext rc)11199 		MethodGroupExpr OverloadResolver.IBaseMembersProvider.LookupExtensionMethod (ResolveContext rc)
11200 		{
11201 			return null;
11202 		}
11203 
11204 		#endregion
11205 	}
11206 
11207 	//
11208 	// A base access expression
11209 	//
11210 	public class BaseThis : This
11211 	{
BaseThis(Location loc)11212 		public BaseThis (Location loc)
11213 			: base (loc)
11214 		{
11215 		}
11216 
BaseThis(TypeSpec type, Location loc)11217 		public BaseThis (TypeSpec type, Location loc)
11218 			: base (loc)
11219 		{
11220 			this.type = type;
11221 			eclass = ExprClass.Variable;
11222 		}
11223 
11224 		#region Properties
11225 
11226 		public override string Name {
11227 			get {
11228 				return "base";
11229 			}
11230 		}
11231 
11232 		#endregion
11233 
CreateExpressionTree(ResolveContext ec)11234 		public override Expression CreateExpressionTree (ResolveContext ec)
11235 		{
11236 			ec.Report.Error (831, loc, "An expression tree may not contain a base access");
11237 			return base.CreateExpressionTree (ec);
11238 		}
11239 
Emit(EmitContext ec)11240 		public override void Emit (EmitContext ec)
11241 		{
11242 			base.Emit (ec);
11243 
11244 			if (type == ec.Module.Compiler.BuiltinTypes.ValueType) {
11245 				var context_type = ec.CurrentType;
11246 				ec.Emit (OpCodes.Ldobj, context_type);
11247 				ec.Emit (OpCodes.Box, context_type);
11248 			}
11249 		}
11250 
Error_ThisNotAvailable(ResolveContext ec)11251 		protected override void Error_ThisNotAvailable (ResolveContext ec)
11252 		{
11253 			if (ec.IsStatic) {
11254 				ec.Report.Error (1511, loc, "Keyword `base' is not available in a static method");
11255 			} else {
11256 				ec.Report.Error (1512, loc, "Keyword `base' is not available in the current context");
11257 			}
11258 		}
11259 
ResolveBase(ResolveContext ec)11260 		public override void ResolveBase (ResolveContext ec)
11261 		{
11262 			base.ResolveBase (ec);
11263 			type = ec.CurrentType.BaseType;
11264 		}
11265 
Accept(StructuralVisitor visitor)11266 		public override object Accept (StructuralVisitor visitor)
11267 		{
11268 			return visitor.Visit (this);
11269 		}
11270 	}
11271 
11272 	/// <summary>
11273 	///   This class exists solely to pass the Type around and to be a dummy
11274 	///   that can be passed to the conversion functions (this is used by
11275 	///   foreach implementation to typecast the object return value from
11276 	///   get_Current into the proper type.  All code has been generated and
11277 	///   we only care about the side effect conversions to be performed
11278 	///
11279 	///   This is also now used as a placeholder where a no-action expression
11280 	///   is needed (the `New' class).
11281 	/// </summary>
11282 	public class EmptyExpression : Expression
11283 	{
11284 		sealed class OutAccessExpression : EmptyExpression
11285 		{
OutAccessExpression(TypeSpec t)11286 			public OutAccessExpression (TypeSpec t)
11287 				: base (t)
11288 			{
11289 			}
11290 
DoResolveLValue(ResolveContext rc, Expression right_side)11291 			public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
11292 			{
11293 				rc.Report.Error (206, right_side.Location,
11294 					"A property, indexer or dynamic member access may not be passed as `ref' or `out' parameter");
11295 
11296 				return null;
11297 			}
11298 		}
11299 
11300 		public static readonly EmptyExpression LValueMemberAccess = new EmptyExpression (InternalType.FakeInternalType);
11301 		public static readonly EmptyExpression LValueMemberOutAccess = new EmptyExpression (InternalType.FakeInternalType);
11302 		public static readonly EmptyExpression UnaryAddress = new EmptyExpression (InternalType.FakeInternalType);
11303 		public static readonly EmptyExpression EventAddition = new EmptyExpression (InternalType.FakeInternalType);
11304 		public static readonly EmptyExpression EventSubtraction = new EmptyExpression (InternalType.FakeInternalType);
11305 		public static readonly EmptyExpression MissingValue = new EmptyExpression (InternalType.FakeInternalType);
11306 		public static readonly Expression Null = new EmptyExpression (InternalType.FakeInternalType);
11307 		public static readonly EmptyExpression OutAccess = new OutAccessExpression (InternalType.FakeInternalType);
11308 
EmptyExpression(TypeSpec t)11309 		public EmptyExpression (TypeSpec t)
11310 		{
11311 			type = t;
11312 			eclass = ExprClass.Value;
11313 			loc = Location.Null;
11314 		}
11315 
CloneTo(CloneContext clonectx, Expression target)11316 		protected override void CloneTo (CloneContext clonectx, Expression target)
11317 		{
11318 		}
11319 
ContainsEmitWithAwait()11320 		public override bool ContainsEmitWithAwait ()
11321 		{
11322 			return false;
11323 		}
11324 
CreateExpressionTree(ResolveContext ec)11325 		public override Expression CreateExpressionTree (ResolveContext ec)
11326 		{
11327 			throw new NotSupportedException ("ET");
11328 		}
11329 
DoResolve(ResolveContext ec)11330 		protected override Expression DoResolve (ResolveContext ec)
11331 		{
11332 			return this;
11333 		}
11334 
Emit(EmitContext ec)11335 		public override void Emit (EmitContext ec)
11336 		{
11337 			// nothing, as we only exist to not do anything.
11338 		}
11339 
EmitBranchable(EmitContext ec, Label target, bool on_true)11340 		public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
11341 		{
11342 		}
11343 
EmitSideEffect(EmitContext ec)11344 		public override void EmitSideEffect (EmitContext ec)
11345 		{
11346 		}
11347 
Accept(StructuralVisitor visitor)11348 		public override object Accept (StructuralVisitor visitor)
11349 		{
11350 			return visitor.Visit (this);
11351 		}
11352 	}
11353 
11354 	sealed class EmptyAwaitExpression : EmptyExpression
11355 	{
EmptyAwaitExpression(TypeSpec type)11356 		public EmptyAwaitExpression (TypeSpec type)
11357 			: base (type)
11358 		{
11359 		}
11360 
ContainsEmitWithAwait()11361 		public override bool ContainsEmitWithAwait ()
11362 		{
11363 			return true;
11364 		}
11365 	}
11366 
11367 	//
11368 	// Empty statement expression
11369 	//
11370 	public sealed class EmptyExpressionStatement : ExpressionStatement
11371 	{
11372 		public static readonly EmptyExpressionStatement Instance = new EmptyExpressionStatement ();
11373 
EmptyExpressionStatement()11374 		private EmptyExpressionStatement ()
11375 		{
11376 			loc = Location.Null;
11377 		}
11378 
ContainsEmitWithAwait()11379 		public override bool ContainsEmitWithAwait ()
11380 		{
11381 			return false;
11382 		}
11383 
CreateExpressionTree(ResolveContext ec)11384 		public override Expression CreateExpressionTree (ResolveContext ec)
11385 		{
11386 			return null;
11387 		}
11388 
EmitStatement(EmitContext ec)11389 		public override void EmitStatement (EmitContext ec)
11390 		{
11391 			// Do nothing
11392 		}
11393 
DoResolve(ResolveContext ec)11394 		protected override Expression DoResolve (ResolveContext ec)
11395 		{
11396 			eclass = ExprClass.Value;
11397 			type = ec.BuiltinTypes.Object;
11398 			return this;
11399 		}
11400 
Emit(EmitContext ec)11401 		public override void Emit (EmitContext ec)
11402 		{
11403 			// Do nothing
11404 		}
11405 
Accept(StructuralVisitor visitor)11406 		public override object Accept (StructuralVisitor visitor)
11407 		{
11408 			return visitor.Visit (this);
11409 		}
11410 	}
11411 
11412 	public class ErrorExpression : EmptyExpression
11413 	{
11414 		public static readonly ErrorExpression Instance = new ErrorExpression ();
11415 
ErrorExpression()11416 		private ErrorExpression ()
11417 			: base (InternalType.ErrorType)
11418 		{
11419 		}
11420 
CreateExpressionTree(ResolveContext ec)11421 		public override Expression CreateExpressionTree (ResolveContext ec)
11422 		{
11423 			return this;
11424 		}
11425 
DoResolveLValue(ResolveContext rc, Expression right_side)11426 		public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
11427 		{
11428 			return this;
11429 		}
11430 
Error_ValueAssignment(ResolveContext rc, Expression rhs)11431 		public override void Error_ValueAssignment (ResolveContext rc, Expression rhs)
11432 		{
11433 		}
11434 
Error_UnexpectedKind(ResolveContext ec, ResolveFlags flags, Location loc)11435 		public override void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc)
11436 		{
11437 		}
11438 
Error_ValueCannotBeConverted(ResolveContext ec, TypeSpec target, bool expl)11439 		public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
11440 		{
11441 		}
11442 
Error_OperatorCannotBeApplied(ResolveContext rc, Location loc, string oper, TypeSpec t)11443 		public override void Error_OperatorCannotBeApplied (ResolveContext rc, Location loc, string oper, TypeSpec t)
11444 		{
11445 		}
11446 
Accept(StructuralVisitor visitor)11447 		public override object Accept (StructuralVisitor visitor)
11448 		{
11449 			return visitor.Visit (this);
11450 		}
11451 	}
11452 
11453 	public class UserCast : Expression {
11454 		MethodSpec method;
11455 		Expression source;
11456 
UserCast(MethodSpec method, Expression source, Location l)11457 		public UserCast (MethodSpec method, Expression source, Location l)
11458 		{
11459 			if (source == null)
11460 				throw new ArgumentNullException ("source");
11461 
11462 			this.method = method;
11463 			this.source = source;
11464 			type = method.ReturnType;
11465 			loc = l;
11466 		}
11467 
11468 		public Expression Source {
11469 			get {
11470 				return source;
11471 			}
11472 			set {
11473 				source = value;
11474 			}
11475 		}
11476 
ContainsEmitWithAwait()11477 		public override bool ContainsEmitWithAwait ()
11478 		{
11479 			return source.ContainsEmitWithAwait ();
11480 		}
11481 
CreateExpressionTree(ResolveContext ec)11482 		public override Expression CreateExpressionTree (ResolveContext ec)
11483 		{
11484 			Arguments args = new Arguments (3);
11485 			args.Add (new Argument (source.CreateExpressionTree (ec)));
11486 			args.Add (new Argument (new TypeOf (type, loc)));
11487 			args.Add (new Argument (new TypeOfMethod (method, loc)));
11488 			return CreateExpressionFactoryCall (ec, "Convert", args);
11489 		}
11490 
DoResolve(ResolveContext ec)11491 		protected override Expression DoResolve (ResolveContext ec)
11492 		{
11493 			method.CheckObsoleteness (ec, source.Location);
11494 
11495 			eclass = ExprClass.Value;
11496 			return this;
11497 		}
11498 
Emit(EmitContext ec)11499 		public override void Emit (EmitContext ec)
11500 		{
11501 			source.Emit (ec);
11502 			ec.MarkCallEntry (loc);
11503 			ec.Emit (OpCodes.Call, method);
11504 		}
11505 
FlowAnalysis(FlowAnalysisContext fc)11506 		public override void FlowAnalysis (FlowAnalysisContext fc)
11507 		{
11508 			source.FlowAnalysis (fc);
11509 		}
11510 
GetSignatureForError()11511 		public override string GetSignatureForError ()
11512 		{
11513 			return TypeManager.CSharpSignature (method);
11514 		}
11515 
MakeExpression(BuilderContext ctx)11516 		public override SLE.Expression MakeExpression (BuilderContext ctx)
11517 		{
11518 #if STATIC
11519 			return base.MakeExpression (ctx);
11520 #else
11521 			return SLE.Expression.Convert (source.MakeExpression (ctx), type.GetMetaInfo (), (MethodInfo) method.GetMetaInfo ());
11522 #endif
11523 		}
11524 	}
11525 
11526 	//
11527 	// Holds additional type specifiers like ?, *, []
11528 	//
11529 	public class ComposedTypeSpecifier
11530 	{
11531 		public static readonly ComposedTypeSpecifier SingleDimension = new ComposedTypeSpecifier (1, Location.Null);
11532 
11533 		public readonly int Dimension;
11534 		public readonly Location Location;
11535 
ComposedTypeSpecifier(int specifier, Location loc)11536 		public ComposedTypeSpecifier (int specifier, Location loc)
11537 		{
11538 			this.Dimension = specifier;
11539 			this.Location = loc;
11540 		}
11541 
11542 		#region Properties
11543 		public bool IsNullable {
11544 			get {
11545 				return Dimension == -1;
11546 			}
11547 		}
11548 
11549 		public bool IsPointer {
11550 			get {
11551 				return Dimension == -2;
11552 			}
11553 		}
11554 
11555 		public ComposedTypeSpecifier Next { get; set; }
11556 
11557 		#endregion
11558 
CreateArrayDimension(int dimension, Location loc)11559 		public static ComposedTypeSpecifier CreateArrayDimension (int dimension, Location loc)
11560 		{
11561 			return new ComposedTypeSpecifier (dimension, loc);
11562 		}
11563 
CreateNullable(Location loc)11564 		public static ComposedTypeSpecifier CreateNullable (Location loc)
11565 		{
11566 			return new ComposedTypeSpecifier (-1, loc);
11567 		}
11568 
CreatePointer(Location loc)11569 		public static ComposedTypeSpecifier CreatePointer (Location loc)
11570 		{
11571 			return new ComposedTypeSpecifier (-2, loc);
11572 		}
11573 
GetSignatureForError()11574 		public string GetSignatureForError ()
11575 		{
11576 			string s =
11577 				IsPointer ? "*" :
11578 				IsNullable ? "?" :
11579 				ArrayContainer.GetPostfixSignature (Dimension);
11580 
11581 			return Next != null ? s + Next.GetSignatureForError () : s;
11582 		}
11583 	}
11584 
11585 	// <summary>
11586 	//   This class is used to "construct" the type during a typecast
11587 	//   operation.  Since the Type.GetType class in .NET can parse
11588 	//   the type specification, we just use this to construct the type
11589 	//   one bit at a time.
11590 	// </summary>
11591 	public class ComposedCast : TypeExpr {
11592 		FullNamedExpression left;
11593 		ComposedTypeSpecifier spec;
11594 
ComposedCast(FullNamedExpression left, ComposedTypeSpecifier spec)11595 		public ComposedCast (FullNamedExpression left, ComposedTypeSpecifier spec)
11596 		{
11597 			if (spec == null)
11598 				throw new ArgumentNullException ("spec");
11599 
11600 			this.left = left;
11601 			this.spec = spec;
11602 			this.loc = left.Location;
11603 		}
11604 
ResolveAsType(IMemberContext ec, bool allowUnboundTypeArguments)11605 		public override TypeSpec ResolveAsType (IMemberContext ec, bool allowUnboundTypeArguments)
11606 		{
11607 			type = left.ResolveAsType (ec);
11608 			if (type == null)
11609 				return null;
11610 
11611 			eclass = ExprClass.Type;
11612 
11613 			var single_spec = spec;
11614 
11615 			if (single_spec.IsNullable) {
11616 				type = new Nullable.NullableType (type, loc).ResolveAsType (ec);
11617 				if (type == null)
11618 					return null;
11619 
11620 				single_spec = single_spec.Next;
11621 			} else if (single_spec.IsPointer) {
11622 				//
11623 				// Declared fields cannot have unmanaged check done before all types are defined
11624 				//
11625 				if (!(ec.CurrentMemberDefinition is Field) && !TypeManager.VerifyUnmanaged (ec.Module, type, loc))
11626 					return null;
11627 
11628 				var rc = ec as ResolveContext;
11629 				if (rc?.CurrentIterator != null) {
11630 					UnsafeInsideIteratorError (ec.Module.Compiler.Report, loc);
11631 				} else if (!ec.IsUnsafe) {
11632 					UnsafeError (ec.Module.Compiler.Report, loc);
11633 				}
11634 
11635 				do {
11636 					type = PointerContainer.MakeType (ec.Module, type);
11637 					single_spec = single_spec.Next;
11638 				} while (single_spec != null && single_spec.IsPointer);
11639 			}
11640 
11641 			if (single_spec != null && single_spec.Dimension > 0) {
11642 				if (type.IsSpecialRuntimeType || type.IsByRefLike) {
11643 					ec.Module.Compiler.Report.Error (611, loc, "Array elements cannot be of type `{0}'", type.GetSignatureForError ());
11644 				} else if (type.IsStatic) {
11645 					ec.Module.Compiler.Report.SymbolRelatedToPreviousError (type);
11646 					ec.Module.Compiler.Report.Error (719, loc, "Array elements cannot be of static type `{0}'",
11647 						type.GetSignatureForError ());
11648 				} else {
11649 					MakeArray (ec.Module, single_spec);
11650 				}
11651 			}
11652 
11653 			return type;
11654 		}
11655 
MakeArray(ModuleContainer module, ComposedTypeSpecifier spec)11656 		void MakeArray (ModuleContainer module, ComposedTypeSpecifier spec)
11657 		{
11658 			if (spec.Next != null)
11659 				MakeArray (module, spec.Next);
11660 
11661 			type = ArrayContainer.MakeType (module, type, spec.Dimension);
11662 		}
11663 
GetSignatureForError()11664 		public override string GetSignatureForError ()
11665 		{
11666 			return left.GetSignatureForError () + spec.GetSignatureForError ();
11667 		}
11668 
Accept(StructuralVisitor visitor)11669 		public override object Accept (StructuralVisitor visitor)
11670 		{
11671 			return visitor.Visit (this);
11672 		}
11673 	}
11674 
11675 	class ReferenceTypeExpr : TypeExpr
11676 	{
11677 		FullNamedExpression element;
11678 		readonly bool readOnly;
11679 
ReferenceTypeExpr(FullNamedExpression element, bool readOnly, Location loc)11680 		public ReferenceTypeExpr (FullNamedExpression element, bool readOnly, Location loc)
11681 			: this (element, loc)
11682 		{
11683 			this.readOnly = readOnly;
11684 		}
11685 
ReferenceTypeExpr(FullNamedExpression element, Location loc)11686 		public ReferenceTypeExpr (FullNamedExpression element, Location loc)
11687 		{
11688 			this.element = element;
11689 			this.loc = loc;
11690 		}
11691 
ResolveAsType(IMemberContext mc, bool allowUnboundTypeArguments = false)11692 		public override TypeSpec ResolveAsType (IMemberContext mc, bool allowUnboundTypeArguments = false)
11693 		{
11694 			type = element.ResolveAsType (mc);
11695 			if (type == null)
11696 				return null;
11697 
11698 			eclass = ExprClass.Type;
11699 			type = readOnly ?
11700 				ReadOnlyReferenceContainer.MakeType (mc.Module, type) :
11701 				ReferenceContainer.MakeType (mc.Module, type);
11702 
11703 			return type;
11704 		}
11705 
GetSignatureForError()11706 		public override string GetSignatureForError ()
11707 		{
11708 			var prefix = readOnly ? "ref " : "ref readonly ";
11709 			return prefix + element.GetSignatureForError ();
11710 		}
11711 
Accept(StructuralVisitor visitor)11712 		public override object Accept (StructuralVisitor visitor)
11713 		{
11714 			return visitor.Visit (this);
11715 		}
11716 	}
11717 
11718 	class FixedBufferPtr : Expression
11719 	{
11720 		readonly Expression array;
11721 
FixedBufferPtr(Expression array, TypeSpec array_type, Location l)11722 		public FixedBufferPtr (Expression array, TypeSpec array_type, Location l)
11723 		{
11724 			this.type = array_type;
11725 			this.array = array;
11726 			this.loc = l;
11727 		}
11728 
ContainsEmitWithAwait()11729 		public override bool ContainsEmitWithAwait ()
11730 		{
11731 			throw new NotImplementedException ();
11732 		}
11733 
CreateExpressionTree(ResolveContext ec)11734 		public override Expression CreateExpressionTree (ResolveContext ec)
11735 		{
11736 			Error_PointerInsideExpressionTree (ec);
11737 			return null;
11738 		}
11739 
Emit(EmitContext ec)11740 		public override void Emit(EmitContext ec)
11741 		{
11742 			array.Emit (ec);
11743 		}
11744 
DoResolve(ResolveContext ec)11745 		protected override Expression DoResolve (ResolveContext ec)
11746 		{
11747 			type = PointerContainer.MakeType (ec.Module, type);
11748 			eclass = ExprClass.Value;
11749 			return this;
11750 		}
11751 	}
11752 
11753 
11754 	//
11755 	// This class is used to represent the address of an array, used
11756 	// only by the Fixed statement, this generates "&a [0]" construct
11757 	// for fixed (char *pa = a)
11758 	//
11759 	class ArrayPtr : FixedBufferPtr
11760 	{
ArrayPtr(Expression array, TypeSpec array_type, Location l)11761 		public ArrayPtr (Expression array, TypeSpec array_type, Location l):
11762 			base (array, array_type, l)
11763 		{
11764 		}
11765 
Emit(EmitContext ec)11766 		public override void Emit (EmitContext ec)
11767 		{
11768 			base.Emit (ec);
11769 
11770 			ec.EmitInt (0);
11771 			ec.Emit (OpCodes.Ldelema, ((PointerContainer) type).Element);
11772 		}
11773 	}
11774 
11775 	//
11776 	// Encapsulates a conversion rules required for array indexes
11777 	//
11778 	public class ArrayIndexCast : TypeCast
11779 	{
ArrayIndexCast(Expression expr, TypeSpec returnType)11780 		public ArrayIndexCast (Expression expr, TypeSpec returnType)
11781 			: base (expr, returnType)
11782 		{
11783 			if (expr.Type == returnType) // int -> int
11784 				throw new ArgumentException ("unnecessary array index conversion");
11785 		}
11786 
CreateExpressionTree(ResolveContext ec)11787 		public override Expression CreateExpressionTree (ResolveContext ec)
11788 		{
11789 			using (ec.Set (ResolveContext.Options.CheckedScope)) {
11790 				return base.CreateExpressionTree (ec);
11791 			}
11792 		}
11793 
Emit(EmitContext ec)11794 		public override void Emit (EmitContext ec)
11795 		{
11796 			child.Emit (ec);
11797 
11798 			switch (child.Type.BuiltinType) {
11799 			case BuiltinTypeSpec.Type.UInt:
11800 				ec.Emit (OpCodes.Conv_U);
11801 				break;
11802 			case BuiltinTypeSpec.Type.Long:
11803 				ec.Emit (OpCodes.Conv_Ovf_I);
11804 				break;
11805 			case BuiltinTypeSpec.Type.ULong:
11806 				ec.Emit (OpCodes.Conv_Ovf_I_Un);
11807 				break;
11808 			default:
11809 				throw new InternalErrorException ("Cannot emit cast to unknown array element type", type);
11810 			}
11811 		}
11812 	}
11813 
11814 	//
11815 	// Implements the `stackalloc' keyword
11816 	//
11817 	public class StackAlloc : Expression {
11818 		TypeSpec otype;
11819 		Expression texpr;
11820 		Expression count;
11821 		MethodSpec ctor;
11822 
StackAlloc(Expression type, Expression count, Location l)11823 		public StackAlloc (Expression type, Expression count, Location l)
11824 		{
11825 			texpr = type;
11826 			this.count = count;
11827 			loc = l;
11828 		}
11829 
11830 		public Expression TypeExpression {
11831 			get {
11832 				return texpr;
11833 			}
11834 		}
11835 
11836 		public Expression CountExpression {
11837 			get {
11838 				return this.count;
11839 			}
11840 		}
11841 
ContainsEmitWithAwait()11842 		public override bool ContainsEmitWithAwait ()
11843 		{
11844 			return false;
11845 		}
11846 
CreateExpressionTree(ResolveContext ec)11847 		public override Expression CreateExpressionTree (ResolveContext ec)
11848 		{
11849 			throw new NotSupportedException ("ET");
11850 		}
11851 
DoResolve(ResolveContext ec)11852 		protected override Expression DoResolve (ResolveContext ec)
11853 		{
11854 			count = count.Resolve (ec);
11855 			if (count == null)
11856 				return null;
11857 
11858 			if (count.Type.BuiltinType != BuiltinTypeSpec.Type.UInt){
11859 				count = Convert.ImplicitConversionRequired (ec, count, ec.BuiltinTypes.Int, loc);
11860 				if (count == null)
11861 					return null;
11862 			}
11863 
11864 			Constant c = count as Constant;
11865 			if (c != null && c.IsNegative) {
11866 				ec.Report.Error (247, loc, "Cannot use a negative size with stackalloc");
11867 			}
11868 
11869 			if (ec.HasAny (ResolveContext.Options.CatchScope | ResolveContext.Options.FinallyScope)) {
11870 				ec.Report.Error (255, loc, "Cannot use stackalloc in finally or catch");
11871 			}
11872 
11873 			otype = texpr.ResolveAsType (ec);
11874 			if (otype == null)
11875 				return null;
11876 
11877 			if (!TypeManager.VerifyUnmanaged (ec.Module, otype, loc))
11878 				return null;
11879 
11880 			type = PointerContainer.MakeType (ec.Module, otype);
11881 			eclass = ExprClass.Value;
11882 
11883 			return this;
11884 		}
11885 
Emit(EmitContext ec)11886 		public override void Emit (EmitContext ec)
11887 		{
11888 			int size = BuiltinTypeSpec.GetSize (otype);
11889 
11890 			count.Emit (ec);
11891 			bool count_on_stack = false;
11892 			if (ctor != null && !ExpressionAnalyzer.IsInexpensiveLoad (count)) {
11893 				ec.Emit (OpCodes.Dup);
11894 				count_on_stack = true;
11895 			}
11896 
11897 			if (size == 0)
11898 				ec.Emit (OpCodes.Sizeof, otype);
11899 			else
11900 				ec.EmitInt (size);
11901 
11902 			ec.Emit (OpCodes.Mul_Ovf_Un);
11903 			ec.Emit (OpCodes.Localloc);
11904 
11905 			if (ctor != null) {
11906 				if (!count_on_stack)
11907 					count.Emit (ec);
11908 				ec.Emit (OpCodes.Newobj, ctor);
11909 			}
11910 		}
11911 
Error_ValueCannotBeConverted(ResolveContext rc, TypeSpec target, bool expl)11912 		public override void Error_ValueCannotBeConverted (ResolveContext rc, TypeSpec target, bool expl)
11913 		{
11914 			var etype = ((PointerContainer)type).Element;
11915 			rc.Report.Error (8346, loc, "Cannot convert a stackalloc expression of type `{0}' to type `{1}'",
11916 			                 etype.GetSignatureForError (), target.GetSignatureForError ());
11917 		}
11918 
CloneTo(CloneContext clonectx, Expression t)11919 		protected override void CloneTo (CloneContext clonectx, Expression t)
11920 		{
11921 			StackAlloc target = (StackAlloc) t;
11922 			target.count = count.Clone (clonectx);
11923 			target.texpr = texpr.Clone (clonectx);
11924 		}
11925 
Accept(StructuralVisitor visitor)11926 		public override object Accept (StructuralVisitor visitor)
11927 		{
11928 			return visitor.Visit (this);
11929 		}
11930 
ResolveSpanConversion(ResolveContext rc, TypeSpec spanType)11931 		public bool ResolveSpanConversion (ResolveContext rc, TypeSpec spanType)
11932 		{
11933 			ctor = MemberCache.FindMember (spanType, MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (PointerContainer.MakeType (rc.Module, rc.Module.Compiler.BuiltinTypes.Void), rc.Module.Compiler.BuiltinTypes.Int)), BindingRestriction.DeclaredOnly) as MethodSpec;
11934 			if (ctor == null)
11935 				return false;
11936 
11937 			this.type = spanType;
11938 			return true;
11939 		}
11940 	}
11941 
11942 	//
11943 	// An object initializer expression
11944 	//
11945 	public class ElementInitializer : Assign
11946 	{
11947 		public readonly string Name;
11948 
ElementInitializer(string name, Expression initializer, Location loc)11949 		public ElementInitializer (string name, Expression initializer, Location loc)
11950 			: base (null, initializer, loc)
11951 		{
11952 			this.Name = name;
11953 		}
11954 
11955 		public bool IsDictionaryInitializer {
11956 			get {
11957 				return Name == null;
11958 			}
11959 		}
11960 
CloneTo(CloneContext clonectx, Expression t)11961 		protected override void CloneTo (CloneContext clonectx, Expression t)
11962 		{
11963 			ElementInitializer target = (ElementInitializer) t;
11964 			target.source = source.Clone (clonectx);
11965 		}
11966 
CreateExpressionTree(ResolveContext ec)11967 		public override Expression CreateExpressionTree (ResolveContext ec)
11968 		{
11969 			Arguments args = new Arguments (2);
11970 			FieldExpr fe = target as FieldExpr;
11971 			if (fe != null)
11972 				args.Add (new Argument (fe.CreateTypeOfExpression ()));
11973 			else
11974 				args.Add (new Argument (((PropertyExpr) target).CreateSetterTypeOfExpression (ec)));
11975 
11976 			string mname;
11977 			Expression arg_expr;
11978 			var cinit = source as CollectionOrObjectInitializers;
11979 			if (cinit == null) {
11980 				mname = "Bind";
11981 				arg_expr = source.CreateExpressionTree (ec);
11982 			} else {
11983 				mname = cinit.IsEmpty || cinit.Initializers[0] is ElementInitializer ? "MemberBind" : "ListBind";
11984 				arg_expr = cinit.CreateExpressionTree (ec, !cinit.IsEmpty);
11985 			}
11986 
11987 			args.Add (new Argument (arg_expr));
11988 			return CreateExpressionFactoryCall (ec, mname, args);
11989 		}
11990 
DoResolve(ResolveContext ec)11991 		protected override Expression DoResolve (ResolveContext ec)
11992 		{
11993 			if (source == null)
11994 				return EmptyExpressionStatement.Instance;
11995 
11996 			if (!ResolveElement (ec))
11997 				return null;
11998 
11999 			if (source is CollectionOrObjectInitializers) {
12000 				target = target.Resolve (ec);
12001 				if (target == null)
12002 					return null;
12003 
12004 				Expression previous = ec.CurrentInitializerVariable;
12005 				ec.CurrentInitializerVariable = target;
12006 				source = source.Resolve (ec);
12007 				ec.CurrentInitializerVariable = previous;
12008 				if (source == null)
12009 					return null;
12010 
12011 				eclass = source.eclass;
12012 				type = source.Type;
12013 
12014 				return this;
12015 			}
12016 
12017 			return base.DoResolve (ec);
12018 		}
12019 
EmitStatement(EmitContext ec)12020 		public override void EmitStatement (EmitContext ec)
12021 		{
12022 			if (source is CollectionOrObjectInitializers)
12023 				source.Emit (ec);
12024 			else
12025 				base.EmitStatement (ec);
12026 		}
12027 
ResolveElement(ResolveContext rc)12028 		protected virtual bool ResolveElement (ResolveContext rc)
12029 		{
12030 			var t = rc.CurrentInitializerVariable.Type;
12031 			if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
12032 				Arguments args = new Arguments (1);
12033 				args.Add (new Argument (rc.CurrentInitializerVariable));
12034 				target = new DynamicMemberBinder (Name, args, loc);
12035 			} else {
12036 				var member = MemberLookup (rc, false, t, Name, 0, MemberLookupRestrictions.ExactArity, loc);
12037 				if (member == null) {
12038 					member = Expression.MemberLookup (rc, true, t, Name, 0, MemberLookupRestrictions.ExactArity, loc);
12039 
12040 					if (member != null) {
12041 						// TODO: ec.Report.SymbolRelatedToPreviousError (member);
12042 						ErrorIsInaccesible (rc, member.GetSignatureForError (), loc);
12043 						return false;
12044 					}
12045 				}
12046 
12047 				if (member == null) {
12048 					Error_TypeDoesNotContainDefinition (rc, loc, t, Name);
12049 					return false;
12050 				}
12051 
12052 				var me = member as MemberExpr;
12053 				if (me is EventExpr) {
12054 					me = me.ResolveMemberAccess (rc, null, null);
12055 				} else if (!(member is PropertyExpr || member is FieldExpr)) {
12056 					rc.Report.Error (1913, loc,
12057 						"Member `{0}' cannot be initialized. An object initializer may only be used for fields, or properties",
12058 						member.GetSignatureForError ());
12059 
12060 					return false;
12061 				}
12062 
12063 				if (me.IsStatic) {
12064 					rc.Report.Error (1914, loc,
12065 						"Static field or property `{0}' cannot be assigned in an object initializer",
12066 						me.GetSignatureForError ());
12067 				}
12068 
12069 				target = me;
12070 				me.InstanceExpression = rc.CurrentInitializerVariable;
12071 			}
12072 
12073 			return true;
12074 		}
12075 	}
12076 
12077 	//
12078 	// A collection initializer expression
12079 	//
12080 	class CollectionElementInitializer : Invocation
12081 	{
12082 		public class ElementInitializerArgument : Argument
12083 		{
ElementInitializerArgument(Expression e)12084 			public ElementInitializerArgument (Expression e)
12085 				: base (e)
12086 			{
12087 			}
12088 		}
12089 
12090 		sealed class AddMemberAccess : MemberAccess
12091 		{
AddMemberAccess(Expression expr, Location loc)12092 			public AddMemberAccess (Expression expr, Location loc)
12093 				: base (expr, "Add", loc)
12094 			{
12095 			}
12096 
Error_TypeDoesNotContainDefinition(ResolveContext ec, TypeSpec type, string name)12097 			public override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name)
12098 			{
12099 				if (TypeManager.HasElementType (type))
12100 					return;
12101 
12102 				base.Error_TypeDoesNotContainDefinition (ec, type, name);
12103 			}
12104 		}
12105 
CollectionElementInitializer(Expression argument)12106 		public CollectionElementInitializer (Expression argument)
12107 			: base (null, new Arguments (1))
12108 		{
12109 			base.arguments.Add (new ElementInitializerArgument (argument));
12110 			this.loc = argument.Location;
12111 		}
12112 
CollectionElementInitializer(List<Expression> arguments, Location loc)12113 		public CollectionElementInitializer (List<Expression> arguments, Location loc)
12114 			: base (null, new Arguments (arguments.Count))
12115 		{
12116 			foreach (Expression e in arguments)
12117 				base.arguments.Add (new ElementInitializerArgument (e));
12118 
12119 			this.loc = loc;
12120 		}
12121 
CollectionElementInitializer(Location loc)12122 		public CollectionElementInitializer (Location loc)
12123 			: base (null, null)
12124 		{
12125 			this.loc = loc;
12126 		}
12127 
CreateExpressionTree(ResolveContext ec)12128 		public override Expression CreateExpressionTree (ResolveContext ec)
12129 		{
12130 			Arguments args = new Arguments (2);
12131 			args.Add (new Argument (mg.CreateExpressionTree (ec)));
12132 
12133 			var expr_initializers = new ArrayInitializer (arguments.Count, loc);
12134 			foreach (Argument a in arguments) {
12135 				if (a.ArgType == Argument.AType.ExtensionType) {
12136 					ec.Report.Error (8075, a.Expr.Location, "An expression tree cannot contain a collection initializer with extension method");
12137 					continue;
12138 				}
12139 				expr_initializers.Add (a.CreateExpressionTree (ec));
12140 			}
12141 
12142 			args.Add (new Argument (new ArrayCreation (
12143 				CreateExpressionTypeExpression (ec, loc), expr_initializers, loc)));
12144 			return CreateExpressionFactoryCall (ec, "ElementInit", args);
12145 		}
12146 
CloneTo(CloneContext clonectx, Expression t)12147 		protected override void CloneTo (CloneContext clonectx, Expression t)
12148 		{
12149 			CollectionElementInitializer target = (CollectionElementInitializer) t;
12150 			if (arguments != null)
12151 				target.arguments = arguments.Clone (clonectx);
12152 		}
12153 
DoResolve(ResolveContext ec)12154 		protected override Expression DoResolve (ResolveContext ec)
12155 		{
12156 			base.expr = new AddMemberAccess (ec.CurrentInitializerVariable, loc);
12157 
12158 			return base.DoResolve (ec);
12159 		}
12160 	}
12161 
12162 	class DictionaryElementInitializer : ElementInitializer
12163 	{
12164 		readonly Arguments args;
12165 
DictionaryElementInitializer(Arguments arguments, Expression initializer, Location loc)12166 		public DictionaryElementInitializer (Arguments arguments, Expression initializer, Location loc)
12167 			: base (null, initializer, loc)
12168 		{
12169 			this.args = arguments;
12170 		}
12171 
CreateExpressionTree(ResolveContext ec)12172 		public override Expression CreateExpressionTree (ResolveContext ec)
12173 		{
12174 			ec.Report.Error (8074, loc, "Expression tree cannot contain a dictionary initializer");
12175 			return null;
12176 		}
12177 
ResolveElement(ResolveContext rc)12178 		protected override bool ResolveElement (ResolveContext rc)
12179 		{
12180 			var init = rc.CurrentInitializerVariable;
12181 			var type = init.Type;
12182 
12183 			if (type.IsArray) {
12184 				target = new ArrayAccess (new ElementAccess (init, args, loc), loc);
12185 				return true;
12186 			}
12187 
12188 			if (type.IsPointer) {
12189 				target = init.MakePointerAccess (rc, type, args);
12190 				return true;
12191 			}
12192 
12193 			var indexers = MemberCache.FindMembers (type, MemberCache.IndexerNameAlias, false);
12194 			if (indexers == null && type.BuiltinType != BuiltinTypeSpec.Type.Dynamic) {
12195 				ElementAccess.Error_CannotApplyIndexing (rc, type, loc);
12196 				return false;
12197 			}
12198 
12199 			target = new IndexerExpr (indexers, type, init, args, loc);
12200 			return true;
12201 		}
12202 	}
12203 
12204 	//
12205 	// A block of object or collection initializers
12206 	//
12207 	public class CollectionOrObjectInitializers : ExpressionStatement
12208 	{
12209 		IList<Expression> initializers;
12210 		bool is_collection_initialization;
12211 
CollectionOrObjectInitializers(Location loc)12212 		public CollectionOrObjectInitializers (Location loc)
12213 			: this (new Expression[0], loc)
12214 		{
12215 		}
12216 
CollectionOrObjectInitializers(IList<Expression> initializers, Location loc)12217 		public CollectionOrObjectInitializers (IList<Expression> initializers, Location loc)
12218 		{
12219 			this.initializers = initializers;
12220 			this.loc = loc;
12221 		}
12222 
12223 		public IList<Expression> Initializers {
12224 			get {
12225 				return initializers;
12226 			}
12227 		}
12228 
12229 		public bool IsEmpty {
12230 			get {
12231 				return initializers.Count == 0;
12232 			}
12233 		}
12234 
12235 		public bool IsCollectionInitializer {
12236 			get {
12237 				return is_collection_initialization;
12238 			}
12239 		}
12240 
CloneTo(CloneContext clonectx, Expression target)12241 		protected override void CloneTo (CloneContext clonectx, Expression target)
12242 		{
12243 			CollectionOrObjectInitializers t = (CollectionOrObjectInitializers) target;
12244 
12245 			t.initializers = new List<Expression> (initializers.Count);
12246 			foreach (var e in initializers)
12247 				t.initializers.Add (e.Clone (clonectx));
12248 		}
12249 
ContainsEmitWithAwait()12250 		public override bool ContainsEmitWithAwait ()
12251 		{
12252 			foreach (var e in initializers) {
12253 				if (e.ContainsEmitWithAwait ())
12254 					return true;
12255 			}
12256 
12257 			return false;
12258 		}
12259 
CreateExpressionTree(ResolveContext ec)12260 		public override Expression CreateExpressionTree (ResolveContext ec)
12261 		{
12262 			return CreateExpressionTree (ec, false);
12263 		}
12264 
CreateExpressionTree(ResolveContext ec, bool inferType)12265 		public Expression CreateExpressionTree (ResolveContext ec, bool inferType)
12266 		{
12267 			var expr_initializers = new ArrayInitializer (initializers.Count, loc);
12268 			foreach (Expression e in initializers) {
12269 				Expression expr = e.CreateExpressionTree (ec);
12270 				if (expr != null)
12271 					expr_initializers.Add (expr);
12272 			}
12273 
12274 			if (inferType)
12275 				return new ImplicitlyTypedArrayCreation (expr_initializers, loc);
12276 
12277 			return new ArrayCreation (new TypeExpression (ec.Module.PredefinedTypes.MemberBinding.Resolve (), loc), expr_initializers, loc);
12278 		}
12279 
DoResolve(ResolveContext ec)12280 		protected override Expression DoResolve (ResolveContext ec)
12281 		{
12282 			List<string> element_names = null;
12283 			for (int i = 0; i < initializers.Count; ++i) {
12284 				Expression initializer = initializers [i];
12285 				ElementInitializer element_initializer = initializer as ElementInitializer;
12286 
12287 				if (i == 0) {
12288 					if (element_initializer != null) {
12289 						element_names = new List<string> (initializers.Count);
12290 						if (!element_initializer.IsDictionaryInitializer)
12291 							element_names.Add (element_initializer.Name);
12292 					} else if (initializer is CompletingExpression) {
12293 						initializer.Resolve (ec);
12294 						throw new InternalErrorException ("This line should never be reached");
12295 					} else {
12296 						var t = ec.CurrentInitializerVariable.Type;
12297 						// LAMESPEC: The collection must implement IEnumerable only, no dynamic support
12298 						if (!t.ImplementsInterface (ec.BuiltinTypes.IEnumerable, false) && t.BuiltinType != BuiltinTypeSpec.Type.Dynamic) {
12299 							ec.Report.Error (1922, loc, "A field or property `{0}' cannot be initialized with a collection " +
12300 								"object initializer because type `{1}' does not implement `{2}' interface",
12301 								ec.CurrentInitializerVariable.GetSignatureForError (),
12302 								ec.CurrentInitializerVariable.Type.GetSignatureForError (),
12303 								ec.BuiltinTypes.IEnumerable.GetSignatureForError ());
12304 							return null;
12305 						}
12306 						is_collection_initialization = true;
12307 					}
12308 				} else {
12309 					if (is_collection_initialization != (element_initializer == null)) {
12310 						ec.Report.Error (747, initializer.Location, "Inconsistent `{0}' member declaration",
12311 							is_collection_initialization ? "collection initializer" : "object initializer");
12312 						continue;
12313 					}
12314 
12315 					if (!is_collection_initialization && !element_initializer.IsDictionaryInitializer) {
12316 						if (element_names.Contains (element_initializer.Name)) {
12317 							ec.Report.Error (1912, element_initializer.Location,
12318 								"An object initializer includes more than one member `{0}' initialization",
12319 								element_initializer.Name);
12320 						} else {
12321 							element_names.Add (element_initializer.Name);
12322 						}
12323 					}
12324 				}
12325 
12326 				Expression e = initializer.Resolve (ec);
12327 				if (e == EmptyExpressionStatement.Instance)
12328 					initializers.RemoveAt (i--);
12329 				else
12330 					initializers [i] = e;
12331 			}
12332 
12333 			type = ec.CurrentInitializerVariable.Type;
12334 			if (is_collection_initialization) {
12335 				if (TypeManager.HasElementType (type)) {
12336 					ec.Report.Error (1925, loc, "Cannot initialize object of type `{0}' with a collection initializer",
12337 						type.GetSignatureForError ());
12338 				}
12339 			}
12340 
12341 			eclass = ExprClass.Variable;
12342 			return this;
12343 		}
12344 
Emit(EmitContext ec)12345 		public override void Emit (EmitContext ec)
12346 		{
12347 			EmitStatement (ec);
12348 		}
12349 
EmitStatement(EmitContext ec)12350 		public override void EmitStatement (EmitContext ec)
12351 		{
12352 			foreach (ExpressionStatement e in initializers) {
12353 				// TODO: need location region
12354 				ec.Mark (e.Location);
12355 				e.EmitStatement (ec);
12356 			}
12357 		}
12358 
FlowAnalysis(FlowAnalysisContext fc)12359 		public override void FlowAnalysis (FlowAnalysisContext fc)
12360 		{
12361 			foreach (var initializer in initializers) {
12362 				if (initializer != null)
12363 					initializer.FlowAnalysis (fc);
12364 			}
12365 		}
12366 	}
12367 
12368 	//
12369 	// New expression with element/object initializers
12370 	//
12371 	public class NewInitialize : New
12372 	{
12373 		//
12374 		// This class serves as a proxy for variable initializer target instances.
12375 		// A real variable is assigned later when we resolve left side of an
12376 		// assignment
12377 		//
12378 		sealed class InitializerTargetExpression : Expression, IMemoryLocation
12379 		{
12380 			NewInitialize new_instance;
12381 
InitializerTargetExpression(NewInitialize newInstance)12382 			public InitializerTargetExpression (NewInitialize newInstance)
12383 			{
12384 				this.type = newInstance.type;
12385 				this.loc = newInstance.loc;
12386 				this.eclass = newInstance.eclass;
12387 				this.new_instance = newInstance;
12388 			}
12389 
ContainsEmitWithAwait()12390 			public override bool ContainsEmitWithAwait ()
12391 			{
12392 				return false;
12393 			}
12394 
CreateExpressionTree(ResolveContext ec)12395 			public override Expression CreateExpressionTree (ResolveContext ec)
12396 			{
12397 				// Should not be reached
12398 				throw new NotSupportedException ("ET");
12399 			}
12400 
DoResolve(ResolveContext ec)12401 			protected override Expression DoResolve (ResolveContext ec)
12402 			{
12403 				return this;
12404 			}
12405 
DoResolveLValue(ResolveContext ec, Expression right_side)12406 			public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
12407 			{
12408 				return this;
12409 			}
12410 
Emit(EmitContext ec)12411 			public override void Emit (EmitContext ec)
12412 			{
12413 				Expression e = (Expression) new_instance.instance;
12414 				e.Emit (ec);
12415 			}
12416 
EmitToField(EmitContext ec)12417 			public override Expression EmitToField (EmitContext ec)
12418 			{
12419 				return (Expression) new_instance.instance;
12420 			}
12421 
12422 			#region IMemoryLocation Members
12423 
AddressOf(EmitContext ec, AddressOp mode)12424 			public void AddressOf (EmitContext ec, AddressOp mode)
12425 			{
12426 				new_instance.instance.AddressOf (ec, mode);
12427 			}
12428 
12429 			#endregion
12430 		}
12431 
12432 		CollectionOrObjectInitializers initializers;
12433 		IMemoryLocation instance;
12434 		DynamicExpressionStatement dynamic;
12435 
NewInitialize(FullNamedExpression requested_type, Arguments arguments, CollectionOrObjectInitializers initializers, Location l)12436 		public NewInitialize (FullNamedExpression requested_type, Arguments arguments, CollectionOrObjectInitializers initializers, Location l)
12437 			: base (requested_type, arguments, l)
12438 		{
12439 			this.initializers = initializers;
12440 		}
12441 
12442 		public CollectionOrObjectInitializers Initializers {
12443 			get {
12444 				return initializers;
12445 			}
12446 		}
12447 
CloneTo(CloneContext clonectx, Expression t)12448 		protected override void CloneTo (CloneContext clonectx, Expression t)
12449 		{
12450 			base.CloneTo (clonectx, t);
12451 
12452 			NewInitialize target = (NewInitialize) t;
12453 			target.initializers = (CollectionOrObjectInitializers) initializers.Clone (clonectx);
12454 		}
12455 
ContainsEmitWithAwait()12456 		public override bool ContainsEmitWithAwait ()
12457 		{
12458 			return base.ContainsEmitWithAwait () || initializers.ContainsEmitWithAwait ();
12459 		}
12460 
CreateExpressionTree(ResolveContext ec)12461 		public override Expression CreateExpressionTree (ResolveContext ec)
12462 		{
12463 			Arguments args = new Arguments (2);
12464 			args.Add (new Argument (base.CreateExpressionTree (ec)));
12465 			if (!initializers.IsEmpty)
12466 				args.Add (new Argument (initializers.CreateExpressionTree (ec, initializers.IsCollectionInitializer)));
12467 
12468 			return CreateExpressionFactoryCall (ec,
12469 				initializers.IsCollectionInitializer ? "ListInit" : "MemberInit",
12470 				args);
12471 		}
12472 
DoResolve(ResolveContext rc)12473 		protected override Expression DoResolve (ResolveContext rc)
12474 		{
12475 			Expression e = base.DoResolve (rc);
12476 			if (type == null)
12477 				return null;
12478 
12479 			if (type.IsDelegate) {
12480 				rc.Report.Error (1958, Initializers.Location,
12481 					"Object and collection initializers cannot be used to instantiate a delegate");
12482 			}
12483 
12484 			Expression previous = rc.CurrentInitializerVariable;
12485 			rc.CurrentInitializerVariable = new InitializerTargetExpression (this);
12486 			using (rc.With (ResolveContext.Options.DontSetConditionalAccessReceiver, false)) {
12487 				initializers.Resolve (rc);
12488 			}
12489 			rc.CurrentInitializerVariable = previous;
12490 
12491 			dynamic = e as DynamicExpressionStatement;
12492 			if (dynamic != null)
12493 				return this;
12494 
12495 			return e;
12496 		}
12497 
Emit(EmitContext ec)12498 		public override void Emit (EmitContext ec)
12499 		{
12500 			if (!CanEmitOptimizedLocalTarget (ec)) {
12501 				var fe = ec.GetTemporaryField (type);
12502 
12503 				if (!Emit (ec, fe))
12504 					fe.Emit (ec);
12505 
12506 				return;
12507 			}
12508 
12509 			base.Emit (ec);
12510 		}
12511 
Emit(EmitContext ec, IMemoryLocation target)12512 		public override bool Emit (EmitContext ec, IMemoryLocation target)
12513 		{
12514 			//
12515 			// Expression is initialized into temporary target then moved
12516 			// to real one for atomicity
12517 			//
12518 			IMemoryLocation temp_target = target;
12519 
12520 			LocalTemporary temp = null;
12521 			bool by_ref = false;
12522 			if (!initializers.IsEmpty) {
12523 				temp_target = target as LocalTemporary;
12524 				if (temp_target == null)
12525 					temp_target = target as StackFieldExpr;
12526 
12527 				if (temp_target == null) {
12528 					var vr = target as VariableReference;
12529 					if (vr != null && vr.IsRef) {
12530 						vr.EmitLoad (ec);
12531 						by_ref = true;
12532 					}
12533 				}
12534 
12535 				if (temp_target == null)
12536 					temp_target = temp = new LocalTemporary (type);
12537 			}
12538 
12539 			bool left_on_stack;
12540 			if (dynamic != null) {
12541 				dynamic.Emit (ec);
12542 				left_on_stack = true;
12543 			} else {
12544 				left_on_stack = base.Emit (ec, temp_target);
12545 			}
12546 
12547 			if (initializers.IsEmpty)
12548 				return left_on_stack;
12549 
12550 			StackFieldExpr sf = null;
12551 
12552 			// Move a new instance (reference-type) to local temporary variable
12553 			if (left_on_stack) {
12554 				if (by_ref) {
12555 					temp_target = temp = new LocalTemporary (type);
12556 				}
12557 
12558 				if (temp != null)
12559 					temp.Store (ec);
12560 
12561 				if (ec.HasSet (BuilderContext.Options.AsyncBody) && initializers.ContainsEmitWithAwait ()) {
12562 					if (temp == null)
12563 						throw new NotImplementedException ();
12564 
12565 					sf = ec.GetTemporaryField (type);
12566 					sf.AutomaticallyReuse = false;
12567 					sf.EmitAssign (ec, temp, false, false);
12568 					temp_target = sf;
12569 					temp.Release (ec);
12570 					left_on_stack = false;
12571 				}
12572 			}
12573 
12574 			instance = temp_target;
12575 
12576 			initializers.Emit (ec);
12577 
12578 			((Expression)temp_target).Emit (ec);
12579 
12580 			if (temp != null)
12581 				temp.Release (ec);
12582 
12583 			if (sf != null)
12584 				sf.PrepareCleanup (ec);
12585 
12586 			return true;
12587 		}
12588 
CanEmitOptimizedLocalTarget(EmitContext ec)12589 		public override bool CanEmitOptimizedLocalTarget (EmitContext ec)
12590 		{
12591 			return !(method == null && TypeSpec.IsValueType (type) &&
12592 					initializers.Initializers.Count > 1 && ec.HasSet (BuilderContext.Options.AsyncBody) &&
12593 					initializers.ContainsEmitWithAwait ());
12594 		}
12595 
EmitAddressOf(EmitContext ec, AddressOp Mode)12596 		protected override IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp Mode)
12597 		{
12598 			instance = base.EmitAddressOf (ec, Mode);
12599 
12600 			if (!initializers.IsEmpty)
12601 				initializers.Emit (ec);
12602 
12603 			return instance;
12604 		}
12605 
FlowAnalysis(FlowAnalysisContext fc)12606 		public override void FlowAnalysis (FlowAnalysisContext fc)
12607 		{
12608 			base.FlowAnalysis (fc);
12609 			initializers.FlowAnalysis (fc);
12610 		}
12611 
Accept(StructuralVisitor visitor)12612 		public override object Accept (StructuralVisitor visitor)
12613 		{
12614 			return visitor.Visit (this);
12615 		}
12616 	}
12617 
12618 	public class NewAnonymousType : New
12619 	{
12620 		static readonly AnonymousTypeParameter[] EmptyParameters = new AnonymousTypeParameter[0];
12621 
12622 		List<AnonymousTypeParameter> parameters;
12623 		readonly TypeContainer parent;
12624 		AnonymousTypeClass anonymous_type;
12625 
NewAnonymousType(List<AnonymousTypeParameter> parameters, TypeContainer parent, Location loc)12626 		public NewAnonymousType (List<AnonymousTypeParameter> parameters, TypeContainer parent, Location loc)
12627 			 : base (null, null, loc)
12628 		{
12629 			this.parameters = parameters;
12630 			this.parent = parent;
12631 		}
12632 
12633 		public List<AnonymousTypeParameter> Parameters {
12634 			get {
12635 				return this.parameters;
12636 			}
12637 		}
12638 
CloneTo(CloneContext clonectx, Expression target)12639 		protected override void CloneTo (CloneContext clonectx, Expression target)
12640 		{
12641 			if (parameters == null)
12642 				return;
12643 
12644 			NewAnonymousType t = (NewAnonymousType) target;
12645 			t.parameters = new List<AnonymousTypeParameter> (parameters.Count);
12646 			foreach (AnonymousTypeParameter atp in parameters)
12647 				t.parameters.Add ((AnonymousTypeParameter) atp.Clone (clonectx));
12648 		}
12649 
CreateAnonymousType(ResolveContext ec, IList<AnonymousTypeParameter> parameters)12650 		AnonymousTypeClass CreateAnonymousType (ResolveContext ec, IList<AnonymousTypeParameter> parameters)
12651 		{
12652 			AnonymousTypeClass type = parent.Module.GetAnonymousType (parameters);
12653 			if (type != null)
12654 				return type;
12655 
12656 			type = AnonymousTypeClass.Create (parent, parameters, loc);
12657 			if (type == null)
12658 				return null;
12659 
12660 			int errors = ec.Report.Errors;
12661 			type.CreateContainer ();
12662 			type.DefineContainer ();
12663 			type.ExpandBaseInterfaces ();
12664 			type.Define ();
12665 			if ((ec.Report.Errors - errors) == 0) {
12666 				parent.Module.AddAnonymousType (type);
12667 				type.PrepareEmit ();
12668 			}
12669 
12670 			return type;
12671 		}
12672 
CreateExpressionTree(ResolveContext ec)12673 		public override Expression CreateExpressionTree (ResolveContext ec)
12674 		{
12675 			if (parameters == null)
12676 				return base.CreateExpressionTree (ec);
12677 
12678 			var init = new ArrayInitializer (parameters.Count, loc);
12679 			foreach (var m in anonymous_type.Members) {
12680 				var p = m as Property;
12681 				if (p != null)
12682 					init.Add (new TypeOfMethod (MemberCache.GetMember (type, p.Get.Spec), loc));
12683 			}
12684 
12685 			var ctor_args = new ArrayInitializer (arguments.Count, loc);
12686 			foreach (Argument a in arguments)
12687 				ctor_args.Add (a.CreateExpressionTree (ec));
12688 
12689 			Arguments args = new Arguments (3);
12690 			args.Add (new Argument (new TypeOfMethod (method, loc)));
12691 			args.Add (new Argument (new ArrayCreation (CreateExpressionTypeExpression (ec, loc), ctor_args, loc)));
12692 			args.Add (new Argument (new ImplicitlyTypedArrayCreation (init, loc)));
12693 
12694 			return CreateExpressionFactoryCall (ec, "New", args);
12695 		}
12696 
DoResolve(ResolveContext ec)12697 		protected override Expression DoResolve (ResolveContext ec)
12698 		{
12699 			if (ec.HasSet (ResolveContext.Options.ConstantScope)) {
12700 				ec.Report.Error (836, loc, "Anonymous types cannot be used in this expression");
12701 				return null;
12702 			}
12703 
12704 			if (parameters == null) {
12705 				anonymous_type = CreateAnonymousType (ec, EmptyParameters);
12706 				RequestedType = new TypeExpression (anonymous_type.Definition, loc);
12707 				return base.DoResolve (ec);
12708 			}
12709 
12710 			bool error = false;
12711 			arguments = new Arguments (parameters.Count);
12712 			var t_args = new TypeSpec [parameters.Count];
12713 			for (int i = 0; i < parameters.Count; ++i) {
12714 				Expression e = parameters [i].Resolve (ec);
12715 				if (e == null) {
12716 					error = true;
12717 					continue;
12718 				}
12719 
12720 				arguments.Add (new Argument (e));
12721 				t_args [i] = e.Type;
12722 			}
12723 
12724 			if (error)
12725 				return null;
12726 
12727 			anonymous_type = CreateAnonymousType (ec, parameters);
12728 			if (anonymous_type == null)
12729 				return null;
12730 
12731 			type = anonymous_type.Definition.MakeGenericType (ec.Module, t_args);
12732 			method = (MethodSpec) MemberCache.FindMember (type, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly);
12733 			eclass = ExprClass.Value;
12734 			return this;
12735 		}
12736 
Accept(StructuralVisitor visitor)12737 		public override object Accept (StructuralVisitor visitor)
12738 		{
12739 			return visitor.Visit (this);
12740 		}
12741 	}
12742 
12743 	public class AnonymousTypeParameter : ShimExpression
12744 	{
12745 		public readonly string Name;
12746 
AnonymousTypeParameter(Expression initializer, string name, Location loc)12747 		public AnonymousTypeParameter (Expression initializer, string name, Location loc)
12748 			: base (initializer)
12749 		{
12750 			this.Name = name;
12751 			this.loc = loc;
12752 		}
12753 
AnonymousTypeParameter(Parameter parameter)12754 		public AnonymousTypeParameter (Parameter parameter)
12755 			: base (new SimpleName (parameter.Name, parameter.Location))
12756 		{
12757 			this.Name = parameter.Name;
12758 			this.loc = parameter.Location;
12759 		}
12760 
Equals(object o)12761 		public override bool Equals (object o)
12762 		{
12763 			AnonymousTypeParameter other = o as AnonymousTypeParameter;
12764 			return other != null && Name == other.Name;
12765 		}
12766 
GetHashCode()12767 		public override int GetHashCode ()
12768 		{
12769 			return Name.GetHashCode ();
12770 		}
12771 
DoResolve(ResolveContext ec)12772 		protected override Expression DoResolve (ResolveContext ec)
12773 		{
12774 			Expression e = expr.Resolve (ec);
12775 			if (e == null)
12776 				return null;
12777 
12778 			if (e.eclass == ExprClass.MethodGroup) {
12779 				Error_InvalidInitializer (ec, e.ExprClassName);
12780 				return null;
12781 			}
12782 
12783 			type = e.Type;
12784 			if (type.Kind == MemberKind.Void || InternalType.HasNoType (type) || type.IsPointer || (e is TupleLiteral && TupleLiteral.ContainsNoTypeElement (type))) {
12785 				Error_InvalidInitializer (ec, type.GetSignatureForError ());
12786 				return null;
12787 			}
12788 
12789 			return e;
12790 		}
12791 
Error_InvalidInitializer(ResolveContext ec, string initializer)12792 		protected virtual void Error_InvalidInitializer (ResolveContext ec, string initializer)
12793 		{
12794 			ec.Report.Error (828, loc, "An anonymous type property `{0}' cannot be initialized with `{1}'",
12795 				Name, initializer);
12796 		}
12797 	}
12798 
12799 	public class CatchFilterExpression : BooleanExpression
12800 	{
CatchFilterExpression(Expression expr, Location loc)12801 		public CatchFilterExpression (Expression expr, Location loc)
12802 			: base (expr)
12803 		{
12804 			this.loc = loc;
12805 		}
12806 	}
12807 
12808 	public class InterpolatedString : Expression
12809 	{
12810 		readonly StringLiteral start, end;
12811 		List<Expression> interpolations;
12812 		Arguments arguments;
12813 
InterpolatedString(StringLiteral start, List<Expression> interpolations, StringLiteral end)12814 		public InterpolatedString (StringLiteral start, List<Expression> interpolations, StringLiteral end)
12815 		{
12816 			this.start = start;
12817 			this.end = end;
12818 			this.interpolations = interpolations;
12819 			loc = start.Location;
12820 		}
12821 
CloneTo(CloneContext clonectx, Expression t)12822 		protected override void CloneTo (CloneContext clonectx, Expression t)
12823 		{
12824 			InterpolatedString target = (InterpolatedString) t;
12825 
12826 			if (interpolations != null) {
12827 				target.interpolations = new List<Expression> ();
12828 				foreach (var interpolation in interpolations) {
12829 					target.interpolations.Add (interpolation.Clone (clonectx));
12830 				}
12831 			}
12832 		}
12833 
ConvertTo(ResolveContext rc, TypeSpec type)12834 		public Expression ConvertTo (ResolveContext rc, TypeSpec type)
12835 		{
12836 			var factory = rc.Module.PredefinedTypes.FormattableStringFactory.Resolve ();
12837 			if (factory == null)
12838 				return null;
12839 
12840 			var ma = new MemberAccess (new TypeExpression (factory, loc), "Create", loc);
12841 			var res = new Invocation (ma, arguments).Resolve (rc);
12842 			if (res != null && res.Type != type)
12843 				res = Convert.ExplicitConversion (rc, res, type, loc);
12844 
12845 			return res;
12846 		}
12847 
ContainsEmitWithAwait()12848 		public override bool ContainsEmitWithAwait ()
12849 		{
12850 			if (interpolations == null)
12851 				return false;
12852 
12853 			foreach (var expr in interpolations) {
12854 				if (expr.ContainsEmitWithAwait ())
12855 					return true;
12856 			}
12857 
12858 			return false;
12859 		}
12860 
CreateExpressionTree(ResolveContext rc)12861 		public override Expression CreateExpressionTree (ResolveContext rc)
12862 		{
12863 			var best = ResolveBestFormatOverload (rc);
12864 			if (best == null)
12865 				return null;
12866 
12867 			Expression instance = new NullLiteral (loc);
12868 			var args = Arguments.CreateForExpressionTree (rc, arguments, instance, new TypeOfMethod (best, loc));
12869 			return CreateExpressionFactoryCall (rc, "Call", args);
12870 		}
12871 
DoResolve(ResolveContext rc)12872 		protected override Expression DoResolve (ResolveContext rc)
12873 		{
12874 			string str;
12875 
12876 			if (interpolations == null) {
12877 				str = start.Value;
12878 				arguments = new Arguments (1);
12879 			} else {
12880 				arguments = new Arguments (interpolations.Count);
12881 
12882 				var sb = new StringBuilder (start.Value);
12883 				for (int i = 0; i < interpolations.Count; ++i) {
12884 					if (i % 2 == 0) {
12885 						sb.Append ('{').Append (i / 2);
12886 						var isi = (InterpolatedStringInsert)interpolations [i];
12887 						if (isi.Alignment != null) {
12888 							sb.Append (',');
12889 							var value = isi.ResolveAligment (rc);
12890 							if (value != null)
12891 								sb.Append (value.Value);
12892 						}
12893 
12894 						if (isi.Format != null) {
12895 							sb.Append (':');
12896 							sb.Append (isi.Format);
12897 						}
12898 
12899 						sb.Append ('}');
12900 						arguments.Add (new Argument (isi.Resolve (rc)));
12901 					} else {
12902 						sb.Append (((StringLiteral)interpolations [i]).Value);
12903 					}
12904 				}
12905 
12906 				sb.Append (end.Value);
12907 				str = sb.ToString ();
12908 			}
12909 
12910 			arguments.Insert (0, new Argument (new StringLiteral (rc.BuiltinTypes, str, start.Location)));
12911 
12912 			eclass = ExprClass.Value;
12913 			type = rc.BuiltinTypes.String;
12914 			return this;
12915 		}
12916 
Emit(EmitContext ec)12917 		public override void Emit (EmitContext ec)
12918 		{
12919 			// No interpolation, convert to simple string result (needs to match string.Format unescaping)
12920 			if (interpolations == null) {
12921 				var str = start.Value.Replace ("{{", "{").Replace ("}}", "}");
12922 				if (str != start.Value)
12923 					new StringConstant (ec.BuiltinTypes, str, loc).Emit (ec);
12924 				else
12925 					start.Emit (ec);
12926 
12927 				return;
12928 			}
12929 
12930 			var best = ResolveBestFormatOverload (new ResolveContext (ec.MemberContext));
12931 			if (best == null)
12932 				return;
12933 
12934 			var ca = new CallEmitter ();
12935 			ca.Emit (ec, best, arguments, loc);
12936 		}
12937 
FlowAnalysis(FlowAnalysisContext fc)12938 		public override void FlowAnalysis (FlowAnalysisContext fc)
12939 		{
12940 			if (interpolations != null) {
12941 				foreach (var expr in interpolations) {
12942 					expr.FlowAnalysis (fc);
12943 				}
12944 			}
12945 		}
12946 
ResolveBestFormatOverload(ResolveContext rc)12947 		MethodSpec ResolveBestFormatOverload (ResolveContext rc)
12948 		{
12949 			var members = MemberCache.FindMembers (rc.BuiltinTypes.String, "Format", true);
12950 			var res = new OverloadResolver (members, OverloadResolver.Restrictions.NoBaseMembers, loc);
12951 			return res.ResolveMember<MethodSpec> (rc, ref arguments);
12952 		}
12953 	}
12954 
12955 	public class InterpolatedStringInsert : CompositeExpression
12956 	{
InterpolatedStringInsert(Expression expr)12957 		public InterpolatedStringInsert (Expression expr)
12958 			: base (expr)
12959 		{
12960 		}
12961 
12962 		public Expression Alignment { get; set; }
12963 		public string Format { get; set; }
12964 
CloneTo(CloneContext clonectx, Expression t)12965 		protected override void CloneTo (CloneContext clonectx, Expression t)
12966 		{
12967 			var target = (InterpolatedStringInsert)t;
12968 			target.expr = expr.Clone (clonectx);
12969 			if (Alignment != null)
12970 				target.Alignment = Alignment.Clone (clonectx);
12971 		}
12972 
DoResolve(ResolveContext rc)12973 		protected override Expression DoResolve (ResolveContext rc)
12974 		{
12975 			var expr = base.DoResolve (rc);
12976 			if (expr == null)
12977 				return null;
12978 
12979 			//
12980 			// For better error reporting, assumes the built-in implementation uses object
12981 			// as argument(s)
12982 			//
12983 			return Convert.ImplicitConversionRequired (rc, expr, rc.BuiltinTypes.Object, expr.Location);
12984 		}
12985 
FlowAnalysis(FlowAnalysisContext fc)12986 		public override void FlowAnalysis (FlowAnalysisContext fc)
12987 		{
12988 			Child.FlowAnalysis (fc);
12989 		}
12990 
ResolveAligment(ResolveContext rc)12991 		public int? ResolveAligment (ResolveContext rc)
12992 		{
12993 			var c = Alignment.ResolveLabelConstant (rc);
12994 			if (c == null)
12995 				return null;
12996 
12997 			c = c.ImplicitConversionRequired (rc, rc.BuiltinTypes.Int);
12998 			if (c == null)
12999 				return null;
13000 
13001 			var value = (int) c.GetValueAsLong ();
13002 			if (value > 32767 || value < -32767) {
13003 				rc.Report.Warning (8094, 1, Alignment.Location,
13004 					"Alignment value has a magnitude greater than 32767 and may result in a large formatted string");
13005 			}
13006 
13007 			return value;
13008 		}
13009 	}
13010 
13011 	class ThrowExpression : ExpressionStatement
13012 	{
13013 		Expression expr;
13014 
ThrowExpression(Expression expr, Location loc)13015 		public ThrowExpression (Expression expr, Location loc)
13016 		{
13017 			this.expr = expr;
13018 			this.loc = loc;
13019 		}
13020 
CloneTo(CloneContext clonectx, Expression t)13021 		protected override void CloneTo (CloneContext clonectx, Expression t)
13022 		{
13023 			var target = (ThrowExpression)t;
13024 			target.expr = expr.Clone (clonectx);
13025 		}
13026 
ContainsEmitWithAwait()13027 		public override bool ContainsEmitWithAwait ()
13028 		{
13029 			return expr.ContainsEmitWithAwait ();
13030 		}
13031 
CreateExpressionTree(ResolveContext rc)13032 		public override Expression CreateExpressionTree (ResolveContext rc)
13033 		{
13034 			rc.Report.Error (8188, loc, "An expression tree cannot not contain a throw expression");
13035 			return expr;
13036 		}
13037 
DoResolve(ResolveContext rc)13038 		protected override Expression DoResolve (ResolveContext rc)
13039 		{
13040 			expr = expr.Resolve (rc, ResolveFlags.Type | ResolveFlags.VariableOrValue);
13041 
13042 			if (expr == null)
13043 				return null;
13044 
13045 			expr = Throw.ConvertType (rc, expr);
13046 
13047 			eclass = ExprClass.Value;
13048 			type = InternalType.ThrowExpr;
13049 			return this;
13050 		}
13051 
Emit(EmitContext ec)13052 		public override void Emit (EmitContext ec)
13053 		{
13054 			EmitStatement (ec);
13055 		}
13056 
EmitStatement(EmitContext ec)13057 		public override void EmitStatement (EmitContext ec)
13058 		{
13059 			expr.Emit (ec);
13060 
13061 			ec.Emit (OpCodes.Throw);
13062 		}
13063 
FlowAnalysis(FlowAnalysisContext fc)13064 		public override void FlowAnalysis (FlowAnalysisContext fc)
13065 		{
13066 			expr.FlowAnalysis (fc);
13067 		}
13068 
MarkReachable(Reachability rc)13069 		public override Reachability MarkReachable (Reachability rc)
13070 		{
13071 			return Reachability.CreateUnreachable ();
13072 		}
13073 	}
13074 
13075 	class ReferenceExpression : CompositeExpression
13076 	{
ReferenceExpression(Expression expr, Location loc)13077 		public ReferenceExpression (Expression expr, Location loc)
13078 			: base (expr)
13079 		{
13080 			this.loc = loc;
13081 		}
13082 
CanBeByRef(Expression expr)13083 		static bool CanBeByRef (Expression expr)
13084 		{
13085 			if (expr is IAssignMethod)
13086 				return true;
13087 
13088 			var invocation = expr as Invocation;
13089 			if (invocation?.Type.Kind == MemberKind.ByRef)
13090 				return true;
13091 
13092 			return false;
13093 		}
13094 
CreateExpressionTree(ResolveContext rc)13095 		public override Expression CreateExpressionTree (ResolveContext rc)
13096 		{
13097 			throw new NotSupportedException ("ET");
13098 		}
13099 
DoResolve(ResolveContext rc)13100 		protected override Expression DoResolve (ResolveContext rc)
13101 		{
13102 			var res = expr.DoResolveLValue (rc, EmptyExpression.OutAccess);
13103 			if (res == null || !CanBeByRef (res)) {
13104 				if (res?.Type != InternalType.ErrorType)
13105 					rc.Report.Error (8156, expr.Location, "An expression cannot be used in this context because it may not be returned by reference");
13106 				return ErrorExpression.Instance;
13107 			}
13108 
13109 			type = res.Type;
13110 			var type_container = type as ReferenceContainer;
13111 			if (type_container != null)
13112 				type = type_container.Element;
13113 
13114 			expr = res;
13115 			eclass = ExprClass.Value;
13116 			return this;
13117 		}
13118 
Emit(EmitContext ec)13119 		public override void Emit (EmitContext ec)
13120 		{
13121 			var ml = expr as IMemoryLocation;
13122 			if (ml != null)
13123 				ml.AddressOf (ec, AddressOp.LoadStore);
13124 			else
13125 				expr.Emit (ec);
13126 		}
13127 
Error_ValueCannotBeConverted(ResolveContext rc, TypeSpec target, bool expl)13128 		public override void Error_ValueCannotBeConverted (ResolveContext rc, TypeSpec target, bool expl)
13129 		{
13130 			rc.Report.Error (8173, loc, "The expression must be of type `{0}' because it is being assigned by reference", target.GetSignatureForError ());
13131 		}
13132 	}
13133 
13134 	class ByRefDereference : CompositeExpression, IMemoryLocation, IAssignMethod
13135 	{
13136 		bool prepared;
13137 		LocalTemporary temporary;
13138 
ByRefDereference(Expression expr)13139 		private ByRefDereference (Expression expr)
13140 			: base (expr)
13141 		{
13142 		}
13143 
Create(Expression expr)13144 		public static Expression Create (Expression expr)
13145 		{
13146 			var rc = expr.Type as ReferenceContainer;
13147 			if (rc == null)
13148 				return expr;
13149 
13150 			return new ByRefDereference (expr) {
13151 				type = rc.Element
13152 			};
13153 		}
13154 
AddressOf(EmitContext ec, AddressOp mode)13155 		public void AddressOf (EmitContext ec, AddressOp mode)
13156 		{
13157 			expr.Emit (ec);
13158 		}
13159 
CreateExpressionTree(ResolveContext rc)13160 		public override Expression CreateExpressionTree (ResolveContext rc)
13161 		{
13162 			rc.Report.Error (8153, Location, "An expression tree lambda cannot contain a call to a method, property, or indexer that returns by reference");
13163 			return null;
13164 		}
13165 
Emit(EmitContext ec, bool leave_copy)13166 		public void Emit (EmitContext ec, bool leave_copy)
13167 		{
13168 			Emit (ec);
13169 			if (leave_copy) {
13170 				ec.Emit (OpCodes.Dup);
13171 				temporary = new LocalTemporary (type);
13172 				temporary.Store (ec);
13173 			}
13174 		}
13175 
EmitAssign(EmitContext ec, Expression source, bool leave_copy, bool isCompound)13176 		public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
13177 		{
13178 			prepared = isCompound;
13179 
13180 			expr.Emit (ec);
13181 
13182 			if (isCompound)
13183 				ec.Emit (OpCodes.Dup);
13184 
13185 			source.Emit (ec);
13186 			if (leave_copy) {
13187 				throw new NotImplementedException ("leave_copy");
13188 			}
13189 
13190 			ec.EmitStoreFromPtr (type);
13191 
13192 			if (temporary != null) {
13193 				temporary.Emit (ec);
13194 				temporary.Release (ec);
13195 			}
13196 		}
13197 
DoResolve(ResolveContext rc)13198 		protected override Expression DoResolve (ResolveContext rc)
13199 		{
13200 			eclass = ExprClass.Variable;
13201 			return this;
13202 		}
13203 
DoResolveLValue(ResolveContext rc, Expression right_side)13204 		public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
13205 		{
13206 			if (expr.ContainsEmitWithAwait ()) {
13207 				rc.Report.Error (8178, loc, "`await' cannot be used in an expression containing a call to `{0}' because it returns by reference",
13208 					expr.GetSignatureForError ());
13209 			}
13210 
13211 			return DoResolve (rc);
13212 		}
13213 
Emit(EmitContext ec)13214 		public override void Emit (EmitContext ec)
13215 		{
13216 			if (!prepared)
13217 				base.Emit(ec);
13218 
13219 			ec.EmitLoadFromPtr (type);
13220 		}
13221 
Accept(StructuralVisitor visitor)13222 		public override object Accept (StructuralVisitor visitor)
13223 		{
13224 			return visitor.Visit (this);
13225 		}
13226 	}
13227 
13228 	class DefaultLiteralExpression : Expression
13229 	{
DefaultLiteralExpression(Location loc)13230 		public DefaultLiteralExpression (Location loc)
13231 		{
13232 			this.loc = loc;
13233 		}
13234 
CreateExpressionTree(ResolveContext ec)13235 		public override Expression CreateExpressionTree (ResolveContext ec)
13236 		{
13237 			throw new NotImplementedException ();
13238 		}
13239 
DoResolve(ResolveContext rc)13240 		protected override Expression DoResolve (ResolveContext rc)
13241 		{
13242 			type = InternalType.DefaultType;
13243 			eclass = ExprClass.Value;
13244 			return this;
13245 		}
13246 
Emit(EmitContext ec)13247 		public override void Emit (EmitContext ec)
13248 		{
13249 			throw new NotSupportedException ();
13250 		}
13251 	}
13252 
13253 	class Discard : Expression, IAssignMethod, IMemoryLocation
13254 	{
Discard(Location loc)13255 		public Discard (Location loc)
13256 		{
13257 			this.loc = loc;
13258 		}
13259 
CreateExpressionTree(ResolveContext rc)13260 		public override Expression CreateExpressionTree (ResolveContext rc)
13261 		{
13262 			rc.Report.Error (8207, loc, "An expression tree cannot contain a discard");
13263 			return null;
13264 		}
13265 
DoResolve(ResolveContext rc)13266 		protected override Expression DoResolve (ResolveContext rc)
13267 		{
13268 			type = InternalType.Discard;
13269 			eclass = ExprClass.Variable;
13270 			return this;
13271 		}
13272 
DoResolveLValue(ResolveContext rc, Expression right_side)13273 		public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
13274 		{
13275 			if (right_side.Type == InternalType.DefaultType) {
13276 				rc.Report.Error (8183, loc, "Cannot infer the type of implicitly-typed discard");
13277 				type = InternalType.ErrorType;
13278 				return this;
13279 			}
13280 
13281 			if (right_side.Type.Kind == MemberKind.Void) {
13282 				rc.Report.Error (8209, loc, "Cannot assign void to a discard");
13283 				type = InternalType.ErrorType;
13284 				return this;
13285 			}
13286 
13287 			if (right_side != EmptyExpression.OutAccess) {
13288 				type = right_side.Type;
13289 			}
13290 
13291 			return this;
13292 		}
13293 
Emit(EmitContext ec)13294 		public override void Emit (EmitContext ec)
13295 		{
13296 			throw new NotImplementedException ();
13297 		}
13298 
Emit(EmitContext ec, bool leave_copy)13299 		public void Emit (EmitContext ec, bool leave_copy)
13300 		{
13301 			throw new NotImplementedException ();
13302 		}
13303 
EmitAssign(EmitContext ec, Expression source, bool leave_copy, bool isCompound)13304 		public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
13305 		{
13306 			if (leave_copy)
13307 				source.Emit (ec);
13308 			else
13309 				source.EmitSideEffect (ec);
13310 		}
13311 
AddressOf(EmitContext ec, AddressOp mode)13312 		public void AddressOf (EmitContext ec, AddressOp mode)
13313 		{
13314 			var temp = ec.GetTemporaryLocal (type);
13315 			ec.Emit (OpCodes.Ldloca, temp);
13316 
13317 			// TODO: Should free it on next statement but don't have mechanism for that yet
13318 			// ec.FreeTemporaryLocal (temp, type);
13319 		}
13320 	}
13321 }
13322