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