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