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