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