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