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