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