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