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