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