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