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