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