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