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