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