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