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