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