2004-05-30 Ben Maurer <bmaurer@users.sourceforge.net>
[mono.git] / mcs / mcs / expression.cs
1 //
2 // expression.cs: Expression representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001, 2002, 2003 Ximian, Inc.
8 // (C) 2003, 2004 Novell, Inc.
9 //
10 #define USE_OLD
11
12 namespace Mono.CSharp {
13         using System;
14         using System.Collections;
15         using System.Reflection;
16         using System.Reflection.Emit;
17         using System.Text;
18
19         /// <summary>
20         ///   This is just a helper class, it is generated by Unary, UnaryMutator
21         ///   when an overloaded method has been found.  It just emits the code for a
22         ///   static call.
23         /// </summary>
24         public class StaticCallExpr : ExpressionStatement {
25                 ArrayList args;
26                 MethodInfo mi;
27
28                 public StaticCallExpr (MethodInfo m, ArrayList a, Location l)
29                 {
30                         mi = m;
31                         args = a;
32
33                         type = m.ReturnType;
34                         eclass = ExprClass.Value;
35                         loc = l;
36                 }
37
38                 public override Expression DoResolve (EmitContext ec)
39                 {
40                         //
41                         // We are born fully resolved
42                         //
43                         return this;
44                 }
45
46                 public override void Emit (EmitContext ec)
47                 {
48                         if (args != null) 
49                                 Invocation.EmitArguments (ec, mi, args);
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 = null;
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                                 } else if (IsParamsMethodApplicable (ec, Arguments, candidate)) {
4750                                         if (candidate_to_form == null)
4751                                                 candidate_to_form = new PtrHashtable ();
4752                                         
4753                                         // Candidate is applicable in expanded form
4754                                         candidates.Add (candidate);
4755                                         applicable_type = candidate.DeclaringType;
4756                                         found_applicable = true; 
4757                                         candidate_to_form [candidate] = candidate;
4758                                 }
4759                         }
4760                         
4761
4762                         //
4763                         // Now we actually find the best method
4764                         //
4765                         int candidate_top = candidates.Count;
4766                         for (int ix = 0; ix < candidate_top; ix++){
4767                                 MethodBase candidate = (MethodBase) candidates [ix];
4768
4769                                 bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
4770                                 bool method_params = false;
4771
4772                                 if (method != null)
4773                                         method_params = candidate_to_form != null && candidate_to_form.Contains (method);
4774                                 
4775                                 int x = BetterFunction (ec, Arguments,
4776                                                         candidate, cand_params,
4777                                                         method, method_params,
4778                                                         loc);
4779                                 
4780                                 if (x == 0)
4781                                         continue;
4782                                 
4783                                 method = candidate;
4784                         }
4785
4786                         if (Arguments == null)
4787                                 argument_count = 0;
4788                         else
4789                                 argument_count = Arguments.Count;
4790                         
4791
4792                         if (method == null) {
4793                                 //
4794                                 // Okay so we have failed to find anything so we
4795                                 // return by providing info about the closest match
4796                                 //
4797                                 for (int i = 0; i < me.Methods.Length; ++i) {
4798
4799                                         MethodBase c = (MethodBase) me.Methods [i];
4800                                         ParameterData pd = GetParameterData (c);
4801
4802                                         if (pd.Count != argument_count)
4803                                                 continue;
4804
4805                                         VerifyArgumentsCompat (ec, Arguments, argument_count, c, false,
4806                                                                null, loc);
4807                                         break;
4808                                 }
4809
4810                                 if (!Location.IsNull (loc)) {
4811                                         string report_name = me.Name;
4812                                         if (report_name == ".ctor")
4813                                                 report_name = me.DeclaringType.ToString ();
4814                                         
4815                                         Error_WrongNumArguments (loc, report_name, argument_count);
4816                                 }
4817                                 
4818                                 return null;
4819                         }
4820
4821                         //
4822                         // Now check that there are no ambiguities i.e the selected method
4823                         // should be better than all the others
4824                         //
4825                         bool best_params = candidate_to_form != null && candidate_to_form.Contains (method);
4826
4827                         for (int ix = 0; ix < candidate_top; ix++){
4828                                 MethodBase candidate = (MethodBase) candidates [ix];
4829
4830                                 if (candidate == method)
4831                                         continue;
4832                                                
4833                                 //
4834                                 // If a normal method is applicable in
4835                                 // the sense that it has the same
4836                                 // number of arguments, then the
4837                                 // expanded params method is never
4838                                 // applicable so we debar the params
4839                                 // method.
4840                                 //
4841                                 // if ((IsParamsMethodApplicable (ec, Arguments, candidate) &&
4842 //                                      IsApplicable (ec, Arguments, method)))
4843 //                                         continue;
4844                                 
4845                                 bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
4846                                 int x = BetterFunction (ec, Arguments,
4847                                                         method, best_params,
4848                                                         candidate, cand_params,
4849                                                         loc);
4850
4851                                 if (x != 1) {
4852                                         Report.Error (
4853                                                 121, loc,
4854                                                 "Ambiguous call when selecting function due to implicit casts");
4855                                         return null;
4856                                 }
4857                         }
4858
4859                         //
4860                         // And now check if the arguments are all
4861                         // compatible, perform conversions if
4862                         // necessary etc. and return if everything is
4863                         // all right
4864                         //
4865                         if (!VerifyArgumentsCompat (ec, Arguments, argument_count, method,
4866                                                     best_params, null, loc))
4867                                 return null;
4868
4869                         return method;
4870                 }
4871
4872                 static void Error_WrongNumArguments (Location loc, String name, int arg_count)
4873                 {
4874                         Report.Error (1501, loc,
4875                                       "No overload for method `" + name + "' takes `" +
4876                                       arg_count + "' arguments");
4877                 }
4878
4879                 static void Error_InvokeOnDelegate (Location loc)
4880                 {
4881                         Report.Error (1533, loc,
4882                                       "Invoke cannot be called directly on a delegate");
4883                 }
4884                         
4885                 static void Error_InvalidArguments (Location loc, int idx, MethodBase method,
4886                                                     Type delegate_type, string arg_sig, string par_desc)
4887                 {
4888                         if (delegate_type == null) 
4889                                 Report.Error (1502, loc,
4890                                               "The best overloaded match for method '" +
4891                                               FullMethodDesc (method) +
4892                                               "' has some invalid arguments");
4893                         else
4894                                 Report.Error (1594, loc,
4895                                               "Delegate '" + delegate_type.ToString () +
4896                                               "' has some invalid arguments.");
4897                         Report.Error (1503, loc,
4898                                       String.Format ("Argument {0}: Cannot convert from '{1}' to '{2}'",
4899                                                      idx, arg_sig, par_desc));
4900                 }
4901                 
4902                 public static bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments,
4903                                                           int argument_count,
4904                                                           MethodBase method, 
4905                                                           bool chose_params_expanded,
4906                                                           Type delegate_type,
4907                                                           Location loc)
4908                 {
4909                         ParameterData pd = GetParameterData (method);
4910                         int pd_count = pd.Count;
4911                         
4912                         for (int j = 0; j < argument_count; j++) {
4913                                 Argument a = (Argument) Arguments [j];
4914                                 Expression a_expr = a.Expr;
4915                                 Type parameter_type = pd.ParameterType (j);
4916                                 Parameter.Modifier pm = pd.ParameterModifier (j);
4917                                 
4918                                 if (pm == Parameter.Modifier.PARAMS){
4919                                         if ((pm & ~Parameter.Modifier.PARAMS) != a.GetParameterModifier ()) {
4920                                                 if (!Location.IsNull (loc))
4921                                                         Error_InvalidArguments (
4922                                                                 loc, j, method, delegate_type,
4923                                                                 Argument.FullDesc (a), pd.ParameterDesc (j));
4924                                                 return false;
4925                                         }
4926
4927                                         if (chose_params_expanded)
4928                                                 parameter_type = TypeManager.GetElementType (parameter_type);
4929                                 } else {
4930                                         //
4931                                         // Check modifiers
4932                                         //
4933                                         if (pd.ParameterModifier (j) != a.GetParameterModifier ()){
4934                                                 if (!Location.IsNull (loc))
4935                                                         Error_InvalidArguments (
4936                                                                 loc, j, method, delegate_type,
4937                                                                 Argument.FullDesc (a), pd.ParameterDesc (j));
4938                                                 return false;
4939                                         }
4940                                 }
4941
4942                                 //
4943                                 // Check Type
4944                                 //
4945                                 if (a.Type != parameter_type){
4946                                         Expression conv;
4947                                         
4948                                         conv = Convert.ImplicitConversion (ec, a_expr, parameter_type, loc);
4949
4950                                         if (conv == null) {
4951                                                 if (!Location.IsNull (loc)) 
4952                                                         Error_InvalidArguments (
4953                                                                 loc, j, method, delegate_type,
4954                                                                 Argument.FullDesc (a), pd.ParameterDesc (j));
4955                                                 return false;
4956                                         }
4957                                         
4958                                         //
4959                                         // Update the argument with the implicit conversion
4960                                         //
4961                                         if (a_expr != conv)
4962                                                 a.Expr = conv;
4963                                 }
4964
4965                                 Parameter.Modifier a_mod = a.GetParameterModifier () &
4966                                         ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
4967                                 Parameter.Modifier p_mod = pd.ParameterModifier (j) &
4968                                         ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
4969                                 
4970                                 if (a_mod != p_mod &&
4971                                     pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
4972                                         if (!Location.IsNull (loc)) {
4973                                                 Report.Error (1502, loc,
4974                                                        "The best overloaded match for method '" + FullMethodDesc (method)+
4975                                                        "' has some invalid arguments");
4976                                                 Report.Error (1503, loc,
4977                                                        "Argument " + (j+1) +
4978                                                        ": Cannot convert from '" + Argument.FullDesc (a) 
4979                                                        + "' to '" + pd.ParameterDesc (j) + "'");
4980                                         }
4981                                         
4982                                         return false;
4983                                 }
4984                         }
4985
4986                         return true;
4987                 }
4988
4989                 public override Expression DoResolve (EmitContext ec)
4990                 {
4991                         //
4992                         // First, resolve the expression that is used to
4993                         // trigger the invocation
4994                         //
4995                         if (expr is BaseAccess)
4996                                 is_base = true;
4997
4998                         expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
4999                         if (expr == null)
5000                                 return null;
5001
5002                         if (!(expr is MethodGroupExpr)) {
5003                                 Type expr_type = expr.Type;
5004
5005                                 if (expr_type != null){
5006                                         bool IsDelegate = TypeManager.IsDelegateType (expr_type);
5007                                         if (IsDelegate)
5008                                                 return (new DelegateInvocation (
5009                                                         this.expr, Arguments, loc)).Resolve (ec);
5010                                 }
5011                         }
5012
5013                         if (!(expr is MethodGroupExpr)){
5014                                 expr.Error_UnexpectedKind (ResolveFlags.MethodGroup);
5015                                 return null;
5016                         }
5017
5018                         //
5019                         // Next, evaluate all the expressions in the argument list
5020                         //
5021                         if (Arguments != null){
5022                                 foreach (Argument a in Arguments){
5023                                         if (!a.Resolve (ec, loc))
5024                                                 return null;
5025                                 }
5026                         }
5027
5028                         MethodGroupExpr mg = (MethodGroupExpr) expr;
5029                         method = OverloadResolve (ec, mg, Arguments, loc);
5030
5031                         if (method == null){
5032                                 Error (-6,
5033                                        "Could not find any applicable function for this argument list");
5034                                 return null;
5035                         }
5036                         
5037                         MethodInfo mi = method as MethodInfo;
5038                         if (mi != null) {
5039                                 type = TypeManager.TypeToCoreType (mi.ReturnType);
5040                                 if (!mi.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null)) {
5041                                         SimpleName.Error_ObjectRefRequired (ec, loc, mi.Name);
5042                                         return null;
5043                                 }
5044
5045                                 Expression iexpr = mg.InstanceExpression;
5046                                 if (mi.IsStatic && (iexpr != null) && !(iexpr is This)) {
5047                                         if (mg.IdenticalTypeName)
5048                                                 mg.InstanceExpression = null;
5049                                         else {
5050                                                 MemberAccess.error176 (loc, mi.Name);
5051                                                 return null;
5052                                         }
5053                                 }
5054                         }
5055
5056                         if (type.IsPointer){
5057                                 if (!ec.InUnsafe){
5058                                         UnsafeError (loc);
5059                                         return null;
5060                                 }
5061                         }
5062                         
5063                         //
5064                         // Only base will allow this invocation to happen.
5065                         //
5066                         if (is_base && method.IsAbstract){
5067                                 Report.Error (205, loc, "Cannot call an abstract base member: " +
5068                                               FullMethodDesc (method));
5069                                 return null;
5070                         }
5071
5072                         if ((method.Attributes & MethodAttributes.SpecialName) != 0){
5073                                 if (TypeManager.IsSpecialMethod (method))
5074                                         Report.Error (571, loc, method.Name + ": can not call operator or accessor");
5075                         }
5076                         
5077                         eclass = ExprClass.Value;
5078                         return this;
5079                 }
5080
5081                 // <summary>
5082                 //   Emits the list of arguments as an array
5083                 // </summary>
5084                 static void EmitParams (EmitContext ec, int idx, ArrayList arguments)
5085                 {
5086                         ILGenerator ig = ec.ig;
5087                         int count = arguments.Count - idx;
5088                         Argument a = (Argument) arguments [idx];
5089                         Type t = a.Expr.Type;
5090                         
5091                         IntConstant.EmitInt (ig, count);
5092                         ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
5093
5094                         int top = arguments.Count;
5095                         for (int j = idx; j < top; j++){
5096                                 a = (Argument) arguments [j];
5097                                 
5098                                 ig.Emit (OpCodes.Dup);
5099                                 IntConstant.EmitInt (ig, j - idx);
5100
5101                                 bool is_stobj;
5102                                 OpCode op = ArrayAccess.GetStoreOpcode (t, out is_stobj);
5103                                 if (is_stobj)
5104                                         ig.Emit (OpCodes.Ldelema, t);
5105
5106                                 a.Emit (ec);
5107
5108                                 if (is_stobj)
5109                                         ig.Emit (OpCodes.Stobj, t);
5110                                 else
5111                                         ig.Emit (op);
5112                         }
5113                 }
5114                 
5115                 /// <summary>
5116                 ///   Emits a list of resolved Arguments that are in the arguments
5117                 ///   ArrayList.
5118                 /// 
5119                 ///   The MethodBase argument might be null if the
5120                 ///   emission of the arguments is known not to contain
5121                 ///   a `params' field (for example in constructors or other routines
5122                 ///   that keep their arguments in this structure)
5123                 /// </summary>
5124                 public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments)
5125                 {
5126                         ParameterData pd;
5127                         if (mb != null)
5128                                 pd = GetParameterData (mb);
5129                         else
5130                                 pd = null;
5131
5132                         //
5133                         // If we are calling a params method with no arguments, special case it
5134                         //
5135                         if (arguments == null){
5136                                 if (pd != null && pd.Count > 0 &&
5137                                     pd.ParameterModifier (0) == Parameter.Modifier.PARAMS){
5138                                         ILGenerator ig = ec.ig;
5139
5140                                         IntConstant.EmitInt (ig, 0);
5141                                         ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (0)));
5142                                 }
5143
5144                                 return;
5145                         }
5146
5147                         int top = arguments.Count;
5148
5149                         for (int i = 0; i < top; i++){
5150                                 Argument a = (Argument) arguments [i];
5151
5152                                 if (pd != null){
5153                                         if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){
5154                                                 //
5155                                                 // Special case if we are passing the same data as the
5156                                                 // params argument, do not put it in an array.
5157                                                 //
5158                                                 if (pd.ParameterType (i) == a.Type)
5159                                                         a.Emit (ec);
5160                                                 else
5161                                                         EmitParams (ec, i, arguments);
5162                                                 return;
5163                                         }
5164                                 }
5165                                             
5166                                 a.Emit (ec);
5167                         }
5168
5169                         if (pd != null && pd.Count > top &&
5170                             pd.ParameterModifier (top) == Parameter.Modifier.PARAMS){
5171                                 ILGenerator ig = ec.ig;
5172
5173                                 IntConstant.EmitInt (ig, 0);
5174                                 ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (top)));
5175                         }
5176                 }
5177
5178                 /// <remarks>
5179                 ///   is_base tells whether we want to force the use of the `call'
5180                 ///   opcode instead of using callvirt.  Call is required to call
5181                 ///   a specific method, while callvirt will always use the most
5182                 ///   recent method in the vtable.
5183                 ///
5184                 ///   is_static tells whether this is an invocation on a static method
5185                 ///
5186                 ///   instance_expr is an expression that represents the instance
5187                 ///   it must be non-null if is_static is false.
5188                 ///
5189                 ///   method is the method to invoke.
5190                 ///
5191                 ///   Arguments is the list of arguments to pass to the method or constructor.
5192                 /// </remarks>
5193                 public static void EmitCall (EmitContext ec, bool is_base,
5194                                              bool is_static, Expression instance_expr,
5195                                              MethodBase method, ArrayList Arguments, Location loc)
5196                 {
5197                         ILGenerator ig = ec.ig;
5198                         bool struct_call = false;
5199                         bool this_call = false;
5200
5201                         Type decl_type = method.DeclaringType;
5202
5203                         if (!RootContext.StdLib) {
5204                                 // Replace any calls to the system's System.Array type with calls to
5205                                 // the newly created one.
5206                                 if (method == TypeManager.system_int_array_get_length)
5207                                         method = TypeManager.int_array_get_length;
5208                                 else if (method == TypeManager.system_int_array_get_rank)
5209                                         method = TypeManager.int_array_get_rank;
5210                                 else if (method == TypeManager.system_object_array_clone)
5211                                         method = TypeManager.object_array_clone;
5212                                 else if (method == TypeManager.system_int_array_get_length_int)
5213                                         method = TypeManager.int_array_get_length_int;
5214                                 else if (method == TypeManager.system_int_array_get_lower_bound_int)
5215                                         method = TypeManager.int_array_get_lower_bound_int;
5216                                 else if (method == TypeManager.system_int_array_get_upper_bound_int)
5217                                         method = TypeManager.int_array_get_upper_bound_int;
5218                                 else if (method == TypeManager.system_void_array_copyto_array_int)
5219                                         method = TypeManager.void_array_copyto_array_int;
5220                         }
5221
5222                         //
5223                         // This checks ObsoleteAttribute on the method and on the declaring type
5224                         //
5225                         ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (method);
5226                         if (oa != null)
5227                                 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (method), loc);
5228
5229
5230                         //
5231                         // This checks the `ConditionalAttribute' on the method
5232                         //
5233                         TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (method);
5234                         if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
5235                                 return;
5236                         
5237                         if (!is_static){
5238                                 if (decl_type.IsValueType)
5239                                         struct_call = true;
5240                                 //
5241                                 // If this is ourselves, push "this"
5242                                 //
5243                                 if (instance_expr == null) {
5244                                         this_call = true;
5245                                         ig.Emit (OpCodes.Ldarg_0);
5246                                 } else {
5247                                         //
5248                                         // Push the instance expression
5249                                         //
5250                                         if (instance_expr.Type.IsValueType){
5251                                                 //
5252                                                 // Special case: calls to a function declared in a 
5253                                                 // reference-type with a value-type argument need
5254                                                 // to have their value boxed.  
5255
5256                                                 struct_call = true;
5257                                                 if (decl_type.IsValueType){
5258                                                         //
5259                                                         // If the expression implements IMemoryLocation, then
5260                                                         // we can optimize and use AddressOf on the
5261                                                         // return.
5262                                                         //
5263                                                         // If not we have to use some temporary storage for
5264                                                         // it.
5265                                                         if (instance_expr is IMemoryLocation){
5266                                                                 ((IMemoryLocation)instance_expr).
5267                                                                         AddressOf (ec, AddressOp.LoadStore);
5268                                                         }
5269                                                         else {
5270                                                                 Type t = instance_expr.Type;
5271                                                                 
5272                                                                 instance_expr.Emit (ec);
5273                                                                 LocalBuilder temp = ig.DeclareLocal (t);
5274                                                                 ig.Emit (OpCodes.Stloc, temp);
5275                                                                 ig.Emit (OpCodes.Ldloca, temp);
5276                                                         }
5277                                                 } else {
5278                                                         instance_expr.Emit (ec);
5279                                                         ig.Emit (OpCodes.Box, instance_expr.Type);
5280                                                 } 
5281                                         } else
5282                                                 instance_expr.Emit (ec);
5283                                 }
5284                         }
5285
5286                         EmitArguments (ec, method, Arguments);
5287                         //
5288                         // If you have:
5289                         // this.DoFoo ();
5290                         // and DoFoo is not virtual, you can omit the callvirt,
5291                         // because you don't need the null checking behavior.
5292                         //
5293                         if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)){
5294                                 if (method is MethodInfo) {
5295                                         ig.Emit (OpCodes.Call, (MethodInfo) method);
5296                                 } else
5297                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
5298                         } else {
5299                                 if (method is MethodInfo)
5300                                         ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
5301                                 else
5302                                         ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
5303                         }
5304                 }
5305                 
5306                 public override void Emit (EmitContext ec)
5307                 {
5308                         MethodGroupExpr mg = (MethodGroupExpr) this.expr;
5309
5310                         EmitCall (ec, is_base, method.IsStatic, mg.InstanceExpression, method, Arguments, loc);
5311                 }
5312                 
5313                 public override void EmitStatement (EmitContext ec)
5314                 {
5315                         Emit (ec);
5316
5317                         // 
5318                         // Pop the return value if there is one
5319                         //
5320                         if (method is MethodInfo){
5321                                 Type ret = ((MethodInfo)method).ReturnType;
5322                                 if (TypeManager.TypeToCoreType (ret) != TypeManager.void_type)
5323                                         ec.ig.Emit (OpCodes.Pop);
5324                         }
5325                 }
5326         }
5327
5328         public class InvocationOrCast : ExpressionStatement
5329         {
5330                 Expression expr;
5331                 Expression argument;
5332
5333                 public InvocationOrCast (Expression expr, Expression argument, Location loc)
5334                 {
5335                         this.expr = expr;
5336                         this.argument = argument;
5337                         this.loc = loc;
5338                 }
5339
5340                 public override Expression DoResolve (EmitContext ec)
5341                 {
5342                         //
5343                         // First try to resolve it as a cast.
5344                         //
5345                         type = ec.DeclSpace.ResolveType (expr, true, loc);
5346                         if (type != null) {
5347                                 Cast cast = new Cast (new TypeExpression (type, loc), argument, loc);
5348                                 return cast.Resolve (ec);
5349                         }
5350
5351                         //
5352                         // This can either be a type or a delegate invocation.
5353                         // Let's just resolve it and see what we'll get.
5354                         //
5355                         expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
5356                         if (expr == null)
5357                                 return null;
5358
5359                         //
5360                         // Ok, so it's a Cast.
5361                         //
5362                         if (expr.eclass == ExprClass.Type) {
5363                                 Cast cast = new Cast (new TypeExpression (expr.Type, loc), argument, loc);
5364                                 return cast.Resolve (ec);
5365                         }
5366
5367                         //
5368                         // It's a delegate invocation.
5369                         //
5370                         if (!TypeManager.IsDelegateType (expr.Type)) {
5371                                 Error (149, "Method name expected");
5372                                 return null;
5373                         }
5374
5375                         ArrayList args = new ArrayList ();
5376                         args.Add (new Argument (argument, Argument.AType.Expression));
5377                         DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
5378                         return invocation.Resolve (ec);
5379                 }
5380
5381                 void error201 ()
5382                 {
5383                         Error (201, "Only assignment, call, increment, decrement and new object " +
5384                                "expressions can be used as a statement");
5385                 }
5386
5387                 public override ExpressionStatement ResolveStatement (EmitContext ec)
5388                 {
5389                         //
5390                         // First try to resolve it as a cast.
5391                         //
5392                         type = ec.DeclSpace.ResolveType (expr, true, loc);
5393                         if (type != null) {
5394                                 error201 ();
5395                                 return null;
5396                         }
5397
5398                         //
5399                         // This can either be a type or a delegate invocation.
5400                         // Let's just resolve it and see what we'll get.
5401                         //
5402                         expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
5403                         if ((expr == null) || (expr.eclass == ExprClass.Type)) {
5404                                 error201 ();
5405                                 return null;
5406                         }
5407
5408                         //
5409                         // It's a delegate invocation.
5410                         //
5411                         if (!TypeManager.IsDelegateType (expr.Type)) {
5412                                 Error (149, "Method name expected");
5413                                 return null;
5414                         }
5415
5416                         ArrayList args = new ArrayList ();
5417                         args.Add (new Argument (argument, Argument.AType.Expression));
5418                         DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
5419                         return invocation.ResolveStatement (ec);
5420                 }
5421
5422                 public override void Emit (EmitContext ec)
5423                 {
5424                         throw new Exception ("Cannot happen");
5425                 }
5426
5427                 public override void EmitStatement (EmitContext ec)
5428                 {
5429                         throw new Exception ("Cannot happen");
5430                 }
5431         }
5432
5433         //
5434         // This class is used to "disable" the code generation for the
5435         // temporary variable when initializing value types.
5436         //
5437         class EmptyAddressOf : EmptyExpression, IMemoryLocation {
5438                 public void AddressOf (EmitContext ec, AddressOp Mode)
5439                 {
5440                         // nothing
5441                 }
5442         }
5443         
5444         /// <summary>
5445         ///    Implements the new expression 
5446         /// </summary>
5447         public class New : ExpressionStatement, IMemoryLocation {
5448                 public readonly ArrayList Arguments;
5449
5450                 //
5451                 // During bootstrap, it contains the RequestedType,
5452                 // but if `type' is not null, it *might* contain a NewDelegate
5453                 // (because of field multi-initialization)
5454                 //
5455                 public Expression RequestedType;
5456
5457                 MethodBase method = null;
5458
5459                 //
5460                 // If set, the new expression is for a value_target, and
5461                 // we will not leave anything on the stack.
5462                 //
5463                 Expression value_target;
5464                 bool value_target_set = false;
5465                 
5466                 public New (Expression requested_type, ArrayList arguments, Location l)
5467                 {
5468                         RequestedType = requested_type;
5469                         Arguments = arguments;
5470                         loc = l;
5471                 }
5472
5473                 public bool SetValueTypeVariable (Expression value)
5474                 {
5475                         value_target = value;
5476                         value_target_set = true;
5477                         if (!(value_target is IMemoryLocation)){
5478                                 Error_UnexpectedKind ("variable");
5479                                 return false;
5480                         }
5481                         return true;
5482                 }
5483
5484                 //
5485                 // This function is used to disable the following code sequence for
5486                 // value type initialization:
5487                 //
5488                 // AddressOf (temporary)
5489                 // Construct/Init
5490                 // LoadTemporary
5491                 //
5492                 // Instead the provide will have provided us with the address on the
5493                 // stack to store the results.
5494                 //
5495                 static Expression MyEmptyExpression;
5496                 
5497                 public void DisableTemporaryValueType ()
5498                 {
5499                         if (MyEmptyExpression == null)
5500                                 MyEmptyExpression = new EmptyAddressOf ();
5501
5502                         //
5503                         // To enable this, look into:
5504                         // test-34 and test-89 and self bootstrapping.
5505                         //
5506                         // For instance, we can avoid a copy by using `newobj'
5507                         // instead of Call + Push-temp on value types.
5508 //                      value_target = MyEmptyExpression;
5509                 }
5510
5511                 public override Expression DoResolve (EmitContext ec)
5512                 {
5513                         //
5514                         // The New DoResolve might be called twice when initializing field
5515                         // expressions (see EmitFieldInitializers, the call to
5516                         // GetInitializerExpression will perform a resolve on the expression,
5517                         // and later the assign will trigger another resolution
5518                         //
5519                         // This leads to bugs (#37014)
5520                         //
5521                         if (type != null){
5522                                 if (RequestedType is NewDelegate)
5523                                         return RequestedType;
5524                                 return this;
5525                         }
5526                         
5527                         type = ec.DeclSpace.ResolveType (RequestedType, false, loc);
5528                         
5529                         if (type == null)
5530                                 return null;
5531                         
5532                         bool IsDelegate = TypeManager.IsDelegateType (type);
5533                         
5534                         if (IsDelegate){
5535                                 RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec);
5536                                 if (RequestedType != null)
5537                                         if (!(RequestedType is NewDelegate))
5538                                                 throw new Exception ("NewDelegate.Resolve returned a non NewDelegate: " + RequestedType.GetType ());
5539                                 return RequestedType;
5540                         }
5541
5542                         if (type.IsInterface || type.IsAbstract){
5543                                 Error (144, "It is not possible to create instances of interfaces or abstract classes");
5544                                 return null;
5545                         }
5546                         
5547                         bool is_struct = type.IsValueType;
5548                         eclass = ExprClass.Value;
5549
5550                         //
5551                         // SRE returns a match for .ctor () on structs (the object constructor), 
5552                         // so we have to manually ignore it.
5553                         //
5554                         if (is_struct && Arguments == null)
5555                                 return this;
5556                         
5557                         Expression ml;
5558                         ml = MemberLookupFinal (ec, null, type, ".ctor",
5559                                                 MemberTypes.Constructor,
5560                                                 AllBindingFlags | BindingFlags.DeclaredOnly, loc);
5561
5562                         if (ml == null)
5563                                 return null;
5564                         
5565                         if (! (ml is MethodGroupExpr)){
5566                                 if (!is_struct){
5567                                         ml.Error_UnexpectedKind ("method group");
5568                                         return null;
5569                                 }
5570                         }
5571
5572                         if (ml != null) {
5573                                 if (Arguments != null){
5574                                         foreach (Argument a in Arguments){
5575                                                 if (!a.Resolve (ec, loc))
5576                                                         return null;
5577                                         }
5578                                 }
5579
5580                                 method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, loc);
5581                                 
5582                         }
5583
5584                         if (method == null) { 
5585                                 if (!is_struct || Arguments.Count > 0) {
5586                                         Error (1501, String.Format (
5587                                             "New invocation: Can not find a constructor in `{0}' for this argument list",
5588                                             TypeManager.CSharpName (type)));
5589                                         return null;
5590                                 }
5591                         }
5592
5593                         return this;
5594                 }
5595
5596                 //
5597                 // This DoEmit can be invoked in two contexts:
5598                 //    * As a mechanism that will leave a value on the stack (new object)
5599                 //    * As one that wont (init struct)
5600                 //
5601                 // You can control whether a value is required on the stack by passing
5602                 // need_value_on_stack.  The code *might* leave a value on the stack
5603                 // so it must be popped manually
5604                 //
5605                 // If we are dealing with a ValueType, we have a few
5606                 // situations to deal with:
5607                 //
5608                 //    * The target is a ValueType, and we have been provided
5609                 //      the instance (this is easy, we are being assigned).
5610                 //
5611                 //    * The target of New is being passed as an argument,
5612                 //      to a boxing operation or a function that takes a
5613                 //      ValueType.
5614                 //
5615                 //      In this case, we need to create a temporary variable
5616                 //      that is the argument of New.
5617                 //
5618                 // Returns whether a value is left on the stack
5619                 //
5620                 bool DoEmit (EmitContext ec, bool need_value_on_stack)
5621                 {
5622                         bool is_value_type = type.IsValueType;
5623                         ILGenerator ig = ec.ig;
5624
5625                         if (is_value_type){
5626                                 IMemoryLocation ml;
5627
5628                                 // Allow DoEmit() to be called multiple times.
5629                                 // We need to create a new LocalTemporary each time since
5630                                 // you can't share LocalBuilders among ILGeneators.
5631                                 if (!value_target_set)
5632                                         value_target = new LocalTemporary (ec, type);
5633
5634                                 ml = (IMemoryLocation) value_target;
5635                                 ml.AddressOf (ec, AddressOp.Store);
5636                         }
5637
5638                         if (method != null)
5639                                 Invocation.EmitArguments (ec, method, Arguments);
5640
5641                         if (is_value_type){
5642                                 if (method == null)
5643                                         ig.Emit (OpCodes.Initobj, type);
5644                                 else 
5645                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
5646                                 if (need_value_on_stack){
5647                                         value_target.Emit (ec);
5648                                         return true;
5649                                 }
5650                                 return false;
5651                         } else {
5652                                 ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
5653                                 return true;
5654                         }
5655                 }
5656
5657                 public override void Emit (EmitContext ec)
5658                 {
5659                         DoEmit (ec, true);
5660                 }
5661                 
5662                 public override void EmitStatement (EmitContext ec)
5663                 {
5664                         if (DoEmit (ec, false))
5665                                 ec.ig.Emit (OpCodes.Pop);
5666                 }
5667
5668                 public void AddressOf (EmitContext ec, AddressOp Mode)
5669                 {
5670                         if (!type.IsValueType){
5671                                 //
5672                                 // We throw an exception.  So far, I believe we only need to support
5673                                 // value types:
5674                                 // foreach (int j in new StructType ())
5675                                 // see bug 42390
5676                                 //
5677                                 throw new Exception ("AddressOf should not be used for classes");
5678                         }
5679
5680                         if (!value_target_set)
5681                                 value_target = new LocalTemporary (ec, type);
5682                                         
5683                         IMemoryLocation ml = (IMemoryLocation) value_target;
5684                         ml.AddressOf (ec, AddressOp.Store);
5685                         if (method != null)
5686                                 Invocation.EmitArguments (ec, method, Arguments);
5687
5688                         if (method == null)
5689                                 ec.ig.Emit (OpCodes.Initobj, type);
5690                         else 
5691                                 ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
5692                         
5693                         ((IMemoryLocation) value_target).AddressOf (ec, Mode);
5694                 }
5695         }
5696
5697         /// <summary>
5698         ///   14.5.10.2: Represents an array creation expression.
5699         /// </summary>
5700         ///
5701         /// <remarks>
5702         ///   There are two possible scenarios here: one is an array creation
5703         ///   expression that specifies the dimensions and optionally the
5704         ///   initialization data and the other which does not need dimensions
5705         ///   specified but where initialization data is mandatory.
5706         /// </remarks>
5707         public class ArrayCreation : ExpressionStatement {
5708                 Expression requested_base_type;
5709                 ArrayList initializers;
5710
5711                 //
5712                 // The list of Argument types.
5713                 // This is used to construct the `newarray' or constructor signature
5714                 //
5715                 ArrayList arguments;
5716
5717                 //
5718                 // Method used to create the array object.
5719                 //
5720                 MethodBase new_method = null;
5721                 
5722                 Type array_element_type;
5723                 Type underlying_type;
5724                 bool is_one_dimensional = false;
5725                 bool is_builtin_type = false;
5726                 bool expect_initializers = false;
5727                 int num_arguments = 0;
5728                 int dimensions = 0;
5729                 string rank;
5730
5731                 ArrayList array_data;
5732
5733                 Hashtable bounds;
5734
5735                 //
5736                 // The number of array initializers that we can handle
5737                 // via the InitializeArray method - through EmitStaticInitializers
5738                 //
5739                 int num_automatic_initializers;
5740
5741                 const int max_automatic_initializers = 6;
5742                 
5743                 public ArrayCreation (Expression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l)
5744                 {
5745                         this.requested_base_type = requested_base_type;
5746                         this.initializers = initializers;
5747                         this.rank = rank;
5748                         loc = l;
5749
5750                         arguments = new ArrayList ();
5751
5752                         foreach (Expression e in exprs) {
5753                                 arguments.Add (new Argument (e, Argument.AType.Expression));
5754                                 num_arguments++;
5755                         }
5756                 }
5757
5758                 public ArrayCreation (Expression requested_base_type, string rank, ArrayList initializers, Location l)
5759                 {
5760                         this.requested_base_type = requested_base_type;
5761                         this.initializers = initializers;
5762                         this.rank = rank;
5763                         loc = l;
5764
5765                         //this.rank = rank.Substring (0, rank.LastIndexOf ('['));
5766                         //
5767                         //string tmp = rank.Substring (rank.LastIndexOf ('['));
5768                         //
5769                         //dimensions = tmp.Length - 1;
5770                         expect_initializers = true;
5771                 }
5772
5773                 public Expression FormArrayType (Expression base_type, int idx_count, string rank)
5774                 {
5775                         StringBuilder sb = new StringBuilder (rank);
5776                         
5777                         sb.Append ("[");
5778                         for (int i = 1; i < idx_count; i++)
5779                                 sb.Append (",");
5780                         
5781                         sb.Append ("]");
5782
5783                         return new ComposedCast (base_type, sb.ToString (), loc);
5784                 }
5785
5786                 void Error_IncorrectArrayInitializer ()
5787                 {
5788                         Error (178, "Incorrectly structured array initializer");
5789                 }
5790                 
5791                 public bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims)
5792                 {
5793                         if (specified_dims) { 
5794                                 Argument a = (Argument) arguments [idx];
5795                                 
5796                                 if (!a.Resolve (ec, loc))
5797                                         return false;
5798                                 
5799                                 if (!(a.Expr is Constant)) {
5800                                         Error (150, "A constant value is expected");
5801                                         return false;
5802                                 }
5803                                 
5804                                 int value = (int) ((Constant) a.Expr).GetValue ();
5805                                 
5806                                 if (value != probe.Count) {
5807                                         Error_IncorrectArrayInitializer ();
5808                                         return false;
5809                                 }
5810                                 
5811                                 bounds [idx] = value;
5812                         }
5813
5814                         int child_bounds = -1;
5815                         foreach (object o in probe) {
5816                                 if (o is ArrayList) {
5817                                         int current_bounds = ((ArrayList) o).Count;
5818                                         
5819                                         if (child_bounds == -1) 
5820                                                 child_bounds = current_bounds;
5821
5822                                         else if (child_bounds != current_bounds){
5823                                                 Error_IncorrectArrayInitializer ();
5824                                                 return false;
5825                                         }
5826                                         if (specified_dims && (idx + 1 >= arguments.Count)){
5827                                                 Error (623, "Array initializers can only be used in a variable or field initializer, try using the new expression");
5828                                                 return false;
5829                                         }
5830                                         
5831                                         bool ret = CheckIndices (ec, (ArrayList) o, idx + 1, specified_dims);
5832                                         if (!ret)
5833                                                 return false;
5834                                 } else {
5835                                         if (child_bounds != -1){
5836                                                 Error_IncorrectArrayInitializer ();
5837                                                 return false;
5838                                         }
5839                                         
5840                                         Expression tmp = (Expression) o;
5841                                         tmp = tmp.Resolve (ec);
5842                                         if (tmp == null)
5843                                                 continue;
5844
5845                                         // Console.WriteLine ("I got: " + tmp);
5846                                         // Handle initialization from vars, fields etc.
5847
5848                                         Expression conv = Convert.ImplicitConversionRequired (
5849                                                 ec, tmp, underlying_type, loc);
5850                                         
5851                                         if (conv == null) 
5852                                                 return false;
5853                                         
5854                                         if (conv is StringConstant || conv is DecimalConstant || conv is NullCast) {
5855                                                 // These are subclasses of Constant that can appear as elements of an
5856                                                 // array that cannot be statically initialized (with num_automatic_initializers
5857                                                 // > max_automatic_initializers), so num_automatic_initializers should be left as zero.
5858                                                 array_data.Add (conv);
5859                                         } else if (conv is Constant) {
5860                                                 // These are the types of Constant that can appear in arrays that can be
5861                                                 // statically allocated.
5862                                                 array_data.Add (conv);
5863                                                 num_automatic_initializers++;
5864                                         } else
5865                                                 array_data.Add (conv);
5866                                 }
5867                         }
5868
5869                         return true;
5870                 }
5871                 
5872                 public void UpdateIndices (EmitContext ec)
5873                 {
5874                         int i = 0;
5875                         for (ArrayList probe = initializers; probe != null;) {
5876                                 if (probe.Count > 0 && probe [0] is ArrayList) {
5877                                         Expression e = new IntConstant (probe.Count);
5878                                         arguments.Add (new Argument (e, Argument.AType.Expression));
5879
5880                                         bounds [i++] =  probe.Count;
5881                                         
5882                                         probe = (ArrayList) probe [0];
5883                                         
5884                                 } else {
5885                                         Expression e = new IntConstant (probe.Count);
5886                                         arguments.Add (new Argument (e, Argument.AType.Expression));
5887
5888                                         bounds [i++] = probe.Count;
5889                                         probe = null;
5890                                 }
5891                         }
5892
5893                 }
5894                 
5895                 public bool ValidateInitializers (EmitContext ec, Type array_type)
5896                 {
5897                         if (initializers == null) {
5898                                 if (expect_initializers)
5899                                         return false;
5900                                 else
5901                                         return true;
5902                         }
5903                         
5904                         if (underlying_type == null)
5905                                 return false;
5906                         
5907                         //
5908                         // We use this to store all the date values in the order in which we
5909                         // will need to store them in the byte blob later
5910                         //
5911                         array_data = new ArrayList ();
5912                         bounds = new Hashtable ();
5913                         
5914                         bool ret;
5915
5916                         if (arguments != null) {
5917                                 ret = CheckIndices (ec, initializers, 0, true);
5918                                 return ret;
5919                         } else {
5920                                 arguments = new ArrayList ();
5921
5922                                 ret = CheckIndices (ec, initializers, 0, false);
5923                                 
5924                                 if (!ret)
5925                                         return false;
5926                                 
5927                                 UpdateIndices (ec);
5928                                 
5929                                 if (arguments.Count != dimensions) {
5930                                         Error_IncorrectArrayInitializer ();
5931                                         return false;
5932                                 }
5933
5934                                 return ret;
5935                         }
5936                 }
5937
5938                 void Error_NegativeArrayIndex ()
5939                 {
5940                         Error (284, "Can not create array with a negative size");
5941                 }
5942                 
5943                 //
5944                 // Converts `source' to an int, uint, long or ulong.
5945                 //
5946                 Expression ExpressionToArrayArgument (EmitContext ec, Expression source)
5947                 {
5948                         Expression target;
5949                         
5950                         bool old_checked = ec.CheckState;
5951                         ec.CheckState = true;
5952                         
5953                         target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
5954                         if (target == null){
5955                                 target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
5956                                 if (target == null){
5957                                         target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
5958                                         if (target == null){
5959                                                 target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
5960                                                 if (target == null)
5961                                                         Convert.Error_CannotImplicitConversion (loc, source.Type, TypeManager.int32_type);
5962                                         }
5963                                 }
5964                         } 
5965                         ec.CheckState = old_checked;
5966
5967                         //
5968                         // Only positive constants are allowed at compile time
5969                         //
5970                         if (target is Constant){
5971                                 if (target is IntConstant){
5972                                         if (((IntConstant) target).Value < 0){
5973                                                 Error_NegativeArrayIndex ();
5974                                                 return null;
5975                                         }
5976                                 }
5977
5978                                 if (target is LongConstant){
5979                                         if (((LongConstant) target).Value < 0){
5980                                                 Error_NegativeArrayIndex ();
5981                                                 return null;
5982                                         }
5983                                 }
5984                                 
5985                         }
5986
5987                         return target;
5988                 }
5989
5990                 //
5991                 // Creates the type of the array
5992                 //
5993                 bool LookupType (EmitContext ec)
5994                 {
5995                         StringBuilder array_qualifier = new StringBuilder (rank);
5996
5997                         //
5998                         // `In the first form allocates an array instace of the type that results
5999                         // from deleting each of the individual expression from the expression list'
6000                         //
6001                         if (num_arguments > 0) {
6002                                 array_qualifier.Append ("[");
6003                                 for (int i = num_arguments-1; i > 0; i--)
6004                                         array_qualifier.Append (",");
6005                                 array_qualifier.Append ("]");                           
6006                         }
6007
6008                         //
6009                         // Lookup the type
6010                         //
6011                         Expression array_type_expr;
6012                         array_type_expr = new ComposedCast (requested_base_type, array_qualifier.ToString (), loc);
6013                         type = ec.DeclSpace.ResolveType (array_type_expr, false, loc);
6014
6015                         if (type == null)
6016                                 return false;
6017
6018                         underlying_type = type;
6019                         if (underlying_type.IsArray)
6020                                 underlying_type = TypeManager.GetElementType (underlying_type);
6021                         dimensions = type.GetArrayRank ();
6022
6023                         return true;
6024                 }
6025                 
6026                 public override Expression DoResolve (EmitContext ec)
6027                 {
6028                         int arg_count;
6029
6030                         if (!LookupType (ec))
6031                                 return null;
6032                         
6033                         //
6034                         // First step is to validate the initializers and fill
6035                         // in any missing bits
6036                         //
6037                         if (!ValidateInitializers (ec, type))
6038                                 return null;
6039
6040                         if (arguments == null)
6041                                 arg_count = 0;
6042                         else {
6043                                 arg_count = arguments.Count;
6044                                 foreach (Argument a in arguments){
6045                                         if (!a.Resolve (ec, loc))
6046                                                 return null;
6047
6048                                         Expression real_arg = ExpressionToArrayArgument (ec, a.Expr, loc);
6049                                         if (real_arg == null)
6050                                                 return null;
6051
6052                                         a.Expr = real_arg;
6053                                 }
6054                         }
6055                         
6056                         array_element_type = TypeManager.GetElementType (type);
6057
6058                         if (arg_count == 1) {
6059                                 is_one_dimensional = true;
6060                                 eclass = ExprClass.Value;
6061                                 return this;
6062                         }
6063
6064                         is_builtin_type = TypeManager.IsBuiltinType (type);
6065
6066                         if (is_builtin_type) {
6067                                 Expression ml;
6068                                 
6069                                 ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor,
6070                                                    AllBindingFlags, loc);
6071                                 
6072                                 if (!(ml is MethodGroupExpr)) {
6073                                         ml.Error_UnexpectedKind ("method group");
6074                                         return null;
6075                                 }
6076                                 
6077                                 if (ml == null) {
6078                                         Error (-6, "New invocation: Can not find a constructor for " +
6079                                                       "this argument list");
6080                                         return null;
6081                                 }
6082                                 
6083                                 new_method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, arguments, loc);
6084
6085                                 if (new_method == null) {
6086                                         Error (-6, "New invocation: Can not find a constructor for " +
6087                                                       "this argument list");
6088                                         return null;
6089                                 }
6090                                 
6091                                 eclass = ExprClass.Value;
6092                                 return this;
6093                         } else {
6094                                 ModuleBuilder mb = CodeGen.Module.Builder;
6095                                 ArrayList args = new ArrayList ();
6096                                 
6097                                 if (arguments != null) {
6098                                         for (int i = 0; i < arg_count; i++)
6099                                                 args.Add (TypeManager.int32_type);
6100                                 }
6101                                 
6102                                 Type [] arg_types = null;
6103
6104                                 if (args.Count > 0)
6105                                         arg_types = new Type [args.Count];
6106                                 
6107                                 args.CopyTo (arg_types, 0);
6108                                 
6109                                 new_method = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,
6110                                                             arg_types);
6111
6112                                 if (new_method == null) {
6113                                         Error (-6, "New invocation: Can not find a constructor for " +
6114                                                       "this argument list");
6115                                         return null;
6116                                 }
6117                                 
6118                                 eclass = ExprClass.Value;
6119                                 return this;
6120                         }
6121                 }
6122
6123                 public static byte [] MakeByteBlob (ArrayList array_data, Type underlying_type, Location loc)
6124                 {
6125                         int factor;
6126                         byte [] data;
6127                         byte [] element;
6128                         int count = array_data.Count;
6129
6130                         if (underlying_type.IsEnum)
6131                                 underlying_type = TypeManager.EnumToUnderlying (underlying_type);
6132                         
6133                         factor = GetTypeSize (underlying_type);
6134                         if (factor == 0)
6135                                 throw new Exception ("unrecognized type in MakeByteBlob: " + underlying_type);
6136
6137                         data = new byte [(count * factor + 4) & ~3];
6138                         int idx = 0;
6139                         
6140                         for (int i = 0; i < count; ++i) {
6141                                 object v = array_data [i];
6142
6143                                 if (v is EnumConstant)
6144                                         v = ((EnumConstant) v).Child;
6145                                 
6146                                 if (v is Constant && !(v is StringConstant))
6147                                         v = ((Constant) v).GetValue ();
6148                                 else {
6149                                         idx += factor;
6150                                         continue;
6151                                 }
6152                                 
6153                                 if (underlying_type == TypeManager.int64_type){
6154                                         if (!(v is Expression)){
6155                                                 long val = (long) v;
6156                                                 
6157                                                 for (int j = 0; j < factor; ++j) {
6158                                                         data [idx + j] = (byte) (val & 0xFF);
6159                                                         val = (val >> 8);
6160                                                 }
6161                                         }
6162                                 } else if (underlying_type == TypeManager.uint64_type){
6163                                         if (!(v is Expression)){
6164                                                 ulong val = (ulong) v;
6165
6166                                                 for (int j = 0; j < factor; ++j) {
6167                                                         data [idx + j] = (byte) (val & 0xFF);
6168                                                         val = (val >> 8);
6169                                                 }
6170                                         }
6171                                 } else if (underlying_type == TypeManager.float_type) {
6172                                         if (!(v is Expression)){
6173                                                 element = BitConverter.GetBytes ((float) v);
6174                                                         
6175                                                 for (int j = 0; j < factor; ++j)
6176                                                         data [idx + j] = element [j];
6177                                         }
6178                                 } else if (underlying_type == TypeManager.double_type) {
6179                                         if (!(v is Expression)){
6180                                                 element = BitConverter.GetBytes ((double) v);
6181
6182                                                 for (int j = 0; j < factor; ++j)
6183                                                         data [idx + j] = element [j];
6184                                         }
6185                                 } else if (underlying_type == TypeManager.char_type){
6186                                         if (!(v is Expression)){
6187                                                 int val = (int) ((char) v);
6188                                                 
6189                                                 data [idx] = (byte) (val & 0xff);
6190                                                 data [idx+1] = (byte) (val >> 8);
6191                                         }
6192                                 } else if (underlying_type == TypeManager.short_type){
6193                                         if (!(v is Expression)){
6194                                                 int val = (int) ((short) v);
6195                                         
6196                                                 data [idx] = (byte) (val & 0xff);
6197                                                 data [idx+1] = (byte) (val >> 8);
6198                                         }
6199                                 } else if (underlying_type == TypeManager.ushort_type){
6200                                         if (!(v is Expression)){
6201                                                 int val = (int) ((ushort) v);
6202                                         
6203                                                 data [idx] = (byte) (val & 0xff);
6204                                                 data [idx+1] = (byte) (val >> 8);
6205                                         }
6206                                 } else if (underlying_type == TypeManager.int32_type) {
6207                                         if (!(v is Expression)){
6208                                                 int val = (int) v;
6209                                         
6210                                                 data [idx]   = (byte) (val & 0xff);
6211                                                 data [idx+1] = (byte) ((val >> 8) & 0xff);
6212                                                 data [idx+2] = (byte) ((val >> 16) & 0xff);
6213                                                 data [idx+3] = (byte) (val >> 24);
6214                                         }
6215                                 } else if (underlying_type == TypeManager.uint32_type) {
6216                                         if (!(v is Expression)){
6217                                                 uint val = (uint) v;
6218                                         
6219                                                 data [idx]   = (byte) (val & 0xff);
6220                                                 data [idx+1] = (byte) ((val >> 8) & 0xff);
6221                                                 data [idx+2] = (byte) ((val >> 16) & 0xff);
6222                                                 data [idx+3] = (byte) (val >> 24);
6223                                         }
6224                                 } else if (underlying_type == TypeManager.sbyte_type) {
6225                                         if (!(v is Expression)){
6226                                                 sbyte val = (sbyte) v;
6227                                                 data [idx] = (byte) val;
6228                                         }
6229                                 } else if (underlying_type == TypeManager.byte_type) {
6230                                         if (!(v is Expression)){
6231                                                 byte val = (byte) v;
6232                                                 data [idx] = (byte) val;
6233                                         }
6234                                 } else if (underlying_type == TypeManager.bool_type) {
6235                                         if (!(v is Expression)){
6236                                                 bool val = (bool) v;
6237                                                 data [idx] = (byte) (val ? 1 : 0);
6238                                         }
6239                                 } else if (underlying_type == TypeManager.decimal_type){
6240                                         if (!(v is Expression)){
6241                                                 int [] bits = Decimal.GetBits ((decimal) v);
6242                                                 int p = idx;
6243
6244                                                 // FIXME: For some reason, this doesn't work on the MS runtime.
6245                                                 int [] nbits = new int [4];
6246                                                 nbits [0] = bits [3];
6247                                                 nbits [1] = bits [2];
6248                                                 nbits [2] = bits [0];
6249                                                 nbits [3] = bits [1];
6250                                                 
6251                                                 for (int j = 0; j < 4; j++){
6252                                                         data [p++] = (byte) (nbits [j] & 0xff);
6253                                                         data [p++] = (byte) ((nbits [j] >> 8) & 0xff);
6254                                                         data [p++] = (byte) ((nbits [j] >> 16) & 0xff);
6255                                                         data [p++] = (byte) (nbits [j] >> 24);
6256                                                 }
6257                                         }
6258                                 } else
6259                                         throw new Exception ("Unrecognized type in MakeByteBlob: " + underlying_type);
6260
6261                                 idx += factor;
6262                         }
6263
6264                         return data;
6265                 }
6266
6267                 //
6268                 // Emits the initializers for the array
6269                 //
6270                 void EmitStaticInitializers (EmitContext ec, bool is_expression)
6271                 {
6272                         //
6273                         // First, the static data
6274                         //
6275                         FieldBuilder fb;
6276                         ILGenerator ig = ec.ig;
6277                         
6278                         byte [] data = MakeByteBlob (array_data, underlying_type, loc);
6279
6280                         fb = RootContext.MakeStaticData (data);
6281
6282                         if (is_expression)
6283                                 ig.Emit (OpCodes.Dup);
6284                         ig.Emit (OpCodes.Ldtoken, fb);
6285                         ig.Emit (OpCodes.Call,
6286                                  TypeManager.void_initializearray_array_fieldhandle);
6287                 }
6288
6289                 //
6290                 // Emits pieces of the array that can not be computed at compile
6291                 // time (variables and string locations).
6292                 //
6293                 // This always expect the top value on the stack to be the array
6294                 //
6295                 void EmitDynamicInitializers (EmitContext ec, bool is_expression)
6296                 {
6297                         ILGenerator ig = ec.ig;
6298                         int dims = bounds.Count;
6299                         int [] current_pos = new int [dims];
6300                         int top = array_data.Count;
6301
6302                         MethodInfo set = null;
6303
6304                         if (dims != 1){
6305                                 Type [] args;
6306                                 ModuleBuilder mb = null;
6307                                 mb = CodeGen.Module.Builder;
6308                                 args = new Type [dims + 1];
6309
6310                                 int j;
6311                                 for (j = 0; j < dims; j++)
6312                                         args [j] = TypeManager.int32_type;
6313
6314                                 args [j] = array_element_type;
6315                                 
6316                                 set = mb.GetArrayMethod (
6317                                         type, "Set",
6318                                         CallingConventions.HasThis | CallingConventions.Standard,
6319                                         TypeManager.void_type, args);
6320                         }
6321                         
6322                         for (int i = 0; i < top; i++){
6323
6324                                 Expression e = null;
6325
6326                                 if (array_data [i] is Expression)
6327                                         e = (Expression) array_data [i];
6328
6329                                 if (e != null) {
6330                                         //
6331                                         // Basically we do this for string literals and
6332                                         // other non-literal expressions
6333                                         //
6334                                         if (e is EnumConstant){
6335                                                 e = ((EnumConstant) e).Child;
6336                                         }
6337                                         
6338                                         if (e is StringConstant || e is DecimalConstant || !(e is Constant) ||
6339                                             num_automatic_initializers <= max_automatic_initializers) {
6340                                                 Type etype = e.Type;
6341                                                 
6342                                                 if (is_expression || i != top - 1)
6343                                                         ig.Emit (OpCodes.Dup);
6344
6345                                                 for (int idx = 0; idx < dims; idx++) 
6346                                                         IntConstant.EmitInt (ig, current_pos [idx]);
6347
6348                                                 //
6349                                                 // If we are dealing with a struct, get the
6350                                                 // address of it, so we can store it.
6351                                                 //
6352                                                 if ((dims == 1) && 
6353                                                     etype.IsSubclassOf (TypeManager.value_type) &&
6354                                                     (!TypeManager.IsBuiltinOrEnum (etype) ||
6355                                                      etype == TypeManager.decimal_type)) {
6356                                                         if (e is New){
6357                                                                 New n = (New) e;
6358
6359                                                                 //
6360                                                                 // Let new know that we are providing
6361                                                                 // the address where to store the results
6362                                                                 //
6363                                                                 n.DisableTemporaryValueType ();
6364                                                         }
6365
6366                                                         ig.Emit (OpCodes.Ldelema, etype);
6367                                                 }
6368
6369                                                 e.Emit (ec);
6370
6371                                                 if (dims == 1)
6372                                                         ArrayAccess.EmitStoreOpcode (ig, array_element_type);
6373                                                 else 
6374                                                         ig.Emit (OpCodes.Call, set);
6375
6376                                         }
6377                                 }
6378                                 
6379                                 //
6380                                 // Advance counter
6381                                 //
6382                                 for (int j = dims - 1; j >= 0; j--){
6383                                         current_pos [j]++;
6384                                         if (current_pos [j] < (int) bounds [j])
6385                                                 break;
6386                                         current_pos [j] = 0;
6387                                 }
6388                         }
6389                 }
6390
6391                 void EmitArrayArguments (EmitContext ec)
6392                 {
6393                         ILGenerator ig = ec.ig;
6394                         
6395                         foreach (Argument a in arguments) {
6396                                 Type atype = a.Type;
6397                                 a.Emit (ec);
6398
6399                                 if (atype == TypeManager.uint64_type)
6400                                         ig.Emit (OpCodes.Conv_Ovf_U4);
6401                                 else if (atype == TypeManager.int64_type)
6402                                         ig.Emit (OpCodes.Conv_Ovf_I4);
6403                         }
6404                 }
6405                 
6406                 void DoEmit (EmitContext ec, bool is_statement)
6407                 {
6408                         ILGenerator ig = ec.ig;
6409                         
6410                         EmitArrayArguments (ec);
6411                         if (is_one_dimensional)
6412                                 ig.Emit (OpCodes.Newarr, array_element_type);
6413                         else {
6414                                 if (is_builtin_type) 
6415                                         ig.Emit (OpCodes.Newobj, (ConstructorInfo) new_method);
6416                                 else 
6417                                         ig.Emit (OpCodes.Newobj, (MethodInfo) new_method);
6418                         }
6419                         
6420                         if (initializers != null){
6421                                 //
6422                                 // FIXME: Set this variable correctly.
6423                                 // 
6424                                 bool dynamic_initializers = true;
6425
6426                                 // This will never be true for array types that cannot be statically
6427                                 // initialized. num_automatic_initializers will always be zero.  See
6428                                 // CheckIndices.
6429                                 if (num_automatic_initializers > max_automatic_initializers)
6430                                         EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
6431                                 
6432                                 if (dynamic_initializers)
6433                                         EmitDynamicInitializers (ec, !is_statement);
6434                         }
6435                 }
6436                 
6437                 public override void Emit (EmitContext ec)
6438                 {
6439                         DoEmit (ec, false);
6440                 }
6441
6442                 public override void EmitStatement (EmitContext ec)
6443                 {
6444                         DoEmit (ec, true);
6445                 }
6446
6447                 public object EncodeAsAttribute ()
6448                 {
6449                         if (!is_one_dimensional){
6450                                 Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays");
6451                                 return null;
6452                         }
6453
6454                         if (array_data == null){
6455                                 Report.Error (-212, Location, "array should be initialized when passing it to an attribute");
6456                                 return null;
6457                         }
6458                         
6459                         object [] ret = new object [array_data.Count];
6460                         int i = 0;
6461                         foreach (Expression e in array_data){
6462                                 object v;
6463                                 
6464                                 if (e is NullLiteral)
6465                                         v = null;
6466                                 else {
6467                                         if (!Attribute.GetAttributeArgumentExpression (e, Location, out v))
6468                                                 return null;
6469                                 }
6470                                 ret [i++] = v;
6471                         }
6472                         return ret;
6473                 }
6474
6475                 public Expression TurnIntoConstant ()
6476                 {
6477                         //
6478                         // Should use something like the above attribute thing.
6479                         // It should return a subclass of Constant that just returns
6480                         // the computed value of the array
6481                         //
6482                         throw new Exception ("Does not support yet Turning array into a Constant");
6483                 }
6484         }
6485         
6486         /// <summary>
6487         ///   Represents the `this' construct
6488         /// </summary>
6489         public class This : Expression, IAssignMethod, IMemoryLocation, IVariable {
6490
6491                 Block block;
6492                 VariableInfo variable_info;
6493                 
6494                 public This (Block block, Location loc)
6495                 {
6496                         this.loc = loc;
6497                         this.block = block;
6498                 }
6499
6500                 public This (Location loc)
6501                 {
6502                         this.loc = loc;
6503                 }
6504
6505                 public VariableInfo VariableInfo {
6506                         get { return variable_info; }
6507                 }
6508
6509                 public bool VerifyFixed (bool is_expression)
6510                 {
6511                         if ((variable_info == null) || (variable_info.LocalInfo == null))
6512                                 return false;
6513                         else
6514                                 return variable_info.LocalInfo.IsFixed;
6515                 }
6516
6517                 public bool ResolveBase (EmitContext ec)
6518                 {
6519                         eclass = ExprClass.Variable;
6520                         type = ec.ContainerType;
6521
6522                         if (ec.IsStatic) {
6523                                 Error (26, "Keyword this not valid in static code");
6524                                 return false;
6525                         }
6526
6527                         if ((block != null) && (block.ThisVariable != null))
6528                                 variable_info = block.ThisVariable.VariableInfo;
6529
6530                         return true;
6531                 }
6532
6533                 public override Expression DoResolve (EmitContext ec)
6534                 {
6535                         if (!ResolveBase (ec))
6536                                 return null;
6537
6538                         if ((variable_info != null) && !variable_info.IsAssigned (ec)) {
6539                                 Error (188, "The this object cannot be used before all " +
6540                                        "of its fields are assigned to");
6541                                 variable_info.SetAssigned (ec);
6542                                 return this;
6543                         }
6544
6545                         if (ec.IsFieldInitializer) {
6546                                 Error (27, "Keyword `this' can't be used outside a constructor, " +
6547                                        "a method or a property.");
6548                                 return null;
6549                         }
6550
6551                         return this;
6552                 }
6553
6554                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
6555                 {
6556                         if (!ResolveBase (ec))
6557                                 return null;
6558
6559                         if (variable_info != null)
6560                                 variable_info.SetAssigned (ec);
6561                         
6562                         if (ec.TypeContainer is Class){
6563                                 Error (1604, "Cannot assign to `this'");
6564                                 return null;
6565                         }
6566
6567                         return this;
6568                 }
6569
6570                 public override void Emit (EmitContext ec)
6571                 {
6572                         ILGenerator ig = ec.ig;
6573
6574                         ec.EmitThis ();
6575                         if (ec.TypeContainer is Struct)
6576                                 ig.Emit (OpCodes.Ldobj, type);
6577                 }
6578
6579                 public void EmitAssign (EmitContext ec, Expression source)
6580                 {
6581                         ILGenerator ig = ec.ig;
6582                         
6583                         if (ec.TypeContainer is Struct){
6584                                 ec.EmitThis ();
6585                                 source.Emit (ec);
6586                                 ig.Emit (OpCodes.Stobj, type);
6587                         } else {
6588                                 source.Emit (ec);
6589                                 ig.Emit (OpCodes.Starg, 0);
6590                         }
6591                 }
6592
6593                 public void AddressOf (EmitContext ec, AddressOp mode)
6594                 {
6595                         ec.EmitThis ();
6596
6597                         // FIMXE
6598                         // FIGURE OUT WHY LDARG_S does not work
6599                         //
6600                         // consider: struct X { int val; int P { set { val = value; }}}
6601                         //
6602                         // Yes, this looks very bad. Look at `NOTAS' for
6603                         // an explanation.
6604                         // ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);
6605                 }
6606         }
6607
6608         //
6609         // This produces the value that renders an instance, used by the iterators code
6610         //
6611         public class ProxyInstance : Expression, IMemoryLocation  {
6612                 public override Expression DoResolve (EmitContext ec)
6613                 {
6614                         eclass = ExprClass.Variable;
6615                         type = ec.ContainerType;
6616                         return this;
6617                 }
6618                 
6619                 public override void Emit (EmitContext ec)
6620                 {
6621                         ec.ig.Emit (OpCodes.Ldarg_0);
6622
6623                 }
6624                 
6625                 public void AddressOf (EmitContext ec, AddressOp mode)
6626                 {
6627                         ec.ig.Emit (OpCodes.Ldarg_0);
6628                 }
6629         }
6630
6631         /// <summary>
6632         ///   Implements the typeof operator
6633         /// </summary>
6634         public class TypeOf : Expression {
6635                 public readonly Expression QueriedType;
6636                 protected Type typearg;
6637                 
6638                 public TypeOf (Expression queried_type, Location l)
6639                 {
6640                         QueriedType = queried_type;
6641                         loc = l;
6642                 }
6643
6644                 public override Expression DoResolve (EmitContext ec)
6645                 {
6646                         typearg = ec.DeclSpace.ResolveType (QueriedType, false, loc);
6647
6648                         if (typearg == null)
6649                                 return null;
6650
6651                         if (typearg == TypeManager.void_type) {
6652                                 Error (673, "System.Void cannot be used from C# - " +
6653                                        "use typeof (void) to get the void type object");
6654                                 return null;
6655                         }
6656
6657                         type = TypeManager.type_type;
6658                         eclass = ExprClass.Type;
6659                         return this;
6660                 }
6661
6662                 public override void Emit (EmitContext ec)
6663                 {
6664                         ec.ig.Emit (OpCodes.Ldtoken, typearg);
6665                         ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
6666                 }
6667
6668                 public Type TypeArg { 
6669                         get { return typearg; }
6670                 }
6671         }
6672
6673         /// <summary>
6674         ///   Implements the `typeof (void)' operator
6675         /// </summary>
6676         public class TypeOfVoid : TypeOf {
6677                 public TypeOfVoid (Location l) : base (null, l)
6678                 {
6679                         loc = l;
6680                 }
6681
6682                 public override Expression DoResolve (EmitContext ec)
6683                 {
6684                         type = TypeManager.type_type;
6685                         typearg = TypeManager.void_type;
6686                         eclass = ExprClass.Type;
6687                         return this;
6688                 }
6689         }
6690
6691         /// <summary>
6692         ///   Implements the sizeof expression
6693         /// </summary>
6694         public class SizeOf : Expression {
6695                 public readonly Expression QueriedType;
6696                 Type type_queried;
6697                 
6698                 public SizeOf (Expression queried_type, Location l)
6699                 {
6700                         this.QueriedType = queried_type;
6701                         loc = l;
6702                 }
6703
6704                 public override Expression DoResolve (EmitContext ec)
6705                 {
6706                         if (!ec.InUnsafe) {
6707                                 Report.Error (
6708                                         233, loc, "Sizeof may only be used in an unsafe context " +
6709                                         "(consider using System.Runtime.InteropServices.Marshal.Sizeof");
6710                                 return null;
6711                         }
6712                                 
6713                         type_queried = ec.DeclSpace.ResolveType (QueriedType, false, loc);
6714                         if (type_queried == null)
6715                                 return null;
6716
6717                         if (!TypeManager.IsUnmanagedType (type_queried)){
6718                                 Report.Error (208, loc, "Cannot take the size of an unmanaged type (" + TypeManager.CSharpName (type_queried) + ")");
6719                                 return null;
6720                         }
6721                         
6722                         type = TypeManager.int32_type;
6723                         eclass = ExprClass.Value;
6724                         return this;
6725                 }
6726
6727                 public override void Emit (EmitContext ec)
6728                 {
6729                         int size = GetTypeSize (type_queried);
6730
6731                         if (size == 0)
6732                                 ec.ig.Emit (OpCodes.Sizeof, type_queried);
6733                         else
6734                                 IntConstant.EmitInt (ec.ig, size);
6735                 }
6736         }
6737
6738         /// <summary>
6739         ///   Implements the member access expression
6740         /// </summary>
6741         public class MemberAccess : Expression {
6742                 public readonly string Identifier;
6743                 Expression expr;
6744                 
6745                 public MemberAccess (Expression expr, string id, Location l)
6746                 {
6747                         this.expr = expr;
6748                         Identifier = id;
6749                         loc = l;
6750                 }
6751
6752                 public Expression Expr {
6753                         get {
6754                                 return expr;
6755                         }
6756                 }
6757
6758                 public static void error176 (Location loc, string name)
6759                 {
6760                         Report.Error (176, loc, "Static member `" +
6761                                       name + "' cannot be accessed " +
6762                                       "with an instance reference, qualify with a " +
6763                                       "type name instead");
6764                 }
6765
6766                 static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Location loc)
6767                 {
6768                         if (left_original == null)
6769                                 return false;
6770
6771                         if (!(left_original is SimpleName))
6772                                 return false;
6773
6774                         SimpleName sn = (SimpleName) left_original;
6775
6776                         Type t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc);
6777                         if (t != null)
6778                                 return true;
6779
6780                         return false;
6781                 }
6782                 
6783                 public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup,
6784                                                               Expression left, Location loc,
6785                                                               Expression left_original)
6786                 {
6787                         bool left_is_type, left_is_explicit;
6788
6789                         // If `left' is null, then we're called from SimpleNameResolve and this is
6790                         // a member in the currently defining class.
6791                         if (left == null) {
6792                                 left_is_type = ec.IsStatic || ec.IsFieldInitializer;
6793                                 left_is_explicit = false;
6794
6795                                 // Implicitly default to `this' unless we're static.
6796                                 if (!ec.IsStatic && !ec.IsFieldInitializer && !ec.InEnumContext)
6797                                         left = ec.GetThis (loc);
6798                         } else {
6799                                 left_is_type = left is TypeExpr;
6800                                 left_is_explicit = true;
6801                         }
6802
6803                         if (member_lookup is FieldExpr){
6804                                 FieldExpr fe = (FieldExpr) member_lookup;
6805                                 FieldInfo fi = fe.FieldInfo;
6806                                 Type decl_type = fi.DeclaringType;
6807
6808                                 if (fi is FieldBuilder) {
6809                                         Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
6810                                         
6811                                         if (c != null) {
6812                                                 object o;
6813                                                 if (!c.LookupConstantValue (out o))
6814                                                         return null;
6815
6816                                                 object real_value = ((Constant) c.Expr).GetValue ();
6817
6818                                                 return Constantify (real_value, fi.FieldType);
6819                                         }
6820                                 }
6821
6822                                 if (fi.IsLiteral) {
6823                                         Type t = fi.FieldType;
6824                                         
6825                                         object o;
6826
6827                                         if (fi is FieldBuilder)
6828                                                 o = TypeManager.GetValue ((FieldBuilder) fi);
6829                                         else
6830                                                 o = fi.GetValue (fi);
6831                                         
6832                                         if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
6833                                                 if (left_is_explicit && !left_is_type &&
6834                                                     !IdenticalNameAndTypeName (ec, left_original, loc)) {
6835                                                         error176 (loc, fe.FieldInfo.Name);
6836                                                         return null;
6837                                                 }                                       
6838                                                 
6839                                                 Expression enum_member = MemberLookup (
6840                                                         ec, decl_type, "value__", MemberTypes.Field,
6841                                                         AllBindingFlags, loc); 
6842
6843                                                 Enum en = TypeManager.LookupEnum (decl_type);
6844
6845                                                 Constant c;
6846                                                 if (en != null)
6847                                                         c = Constantify (o, en.UnderlyingType);
6848                                                 else 
6849                                                         c = Constantify (o, enum_member.Type);
6850                                                 
6851                                                 return new EnumConstant (c, decl_type);
6852                                         }
6853                                         
6854                                         Expression exp = Constantify (o, t);
6855
6856                                         if (left_is_explicit && !left_is_type) {
6857                                                 error176 (loc, fe.FieldInfo.Name);
6858                                                 return null;
6859                                         }
6860                                         
6861                                         return exp;
6862                                 }
6863
6864                                 if (fi.FieldType.IsPointer && !ec.InUnsafe){
6865                                         UnsafeError (loc);
6866                                         return null;
6867                                 }
6868                         }
6869
6870                         if (member_lookup is EventExpr) {
6871                                 EventExpr ee = (EventExpr) member_lookup;
6872                                 
6873                                 //
6874                                 // If the event is local to this class, we transform ourselves into
6875                                 // a FieldExpr
6876                                 //
6877
6878                                 if (ee.EventInfo.DeclaringType == ec.ContainerType ||
6879                                     TypeManager.IsNestedChildOf(ec.ContainerType, ee.EventInfo.DeclaringType)) {
6880                                         MemberInfo mi = GetFieldFromEvent (ee);
6881
6882                                         if (mi == null) {
6883                                                 //
6884                                                 // If this happens, then we have an event with its own
6885                                                 // accessors and private field etc so there's no need
6886                                                 // to transform ourselves.
6887                                                 //
6888                                                 ee.InstanceExpression = left;
6889                                                 return ee;
6890                                         }
6891
6892                                         Expression ml = ExprClassFromMemberInfo (ec, mi, loc);
6893                                         
6894                                         if (ml == null) {
6895                                                 Report.Error (-200, loc, "Internal error!!");
6896                                                 return null;
6897                                         }
6898
6899                                         if (!left_is_explicit)
6900                                                 left = null;
6901
6902                                         ee.InstanceExpression = left;
6903
6904                                         return ResolveMemberAccess (ec, ml, left, loc, left_original);
6905                                 }
6906                         }
6907
6908                         if (member_lookup is IMemberExpr) {
6909                                 IMemberExpr me = (IMemberExpr) member_lookup;
6910                                 MethodGroupExpr mg = me as MethodGroupExpr;
6911
6912                                 if (left_is_type){
6913                                         if ((mg != null) && left_is_explicit && left.Type.IsInterface)
6914                                                 mg.IsExplicitImpl = left_is_explicit;
6915
6916                                         if (!me.IsStatic){
6917                                                 if ((ec.IsFieldInitializer || ec.IsStatic) &&
6918                                                     IdenticalNameAndTypeName (ec, left_original, loc))
6919                                                         return member_lookup;
6920
6921                                                 SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
6922                                                 return null;
6923                                         }
6924
6925                                 } else {
6926                                         if (!me.IsInstance){
6927                                                 if (IdenticalNameAndTypeName (ec, left_original, loc))
6928                                                         return member_lookup;
6929
6930                                                 if (left_is_explicit) {
6931                                                         error176 (loc, me.Name);
6932                                                         return null;
6933                                                 }
6934                                         }                                               
6935
6936                                         //
6937                                         // Since we can not check for instance objects in SimpleName,
6938                                         // becaue of the rule that allows types and variables to share
6939                                         // the name (as long as they can be de-ambiguated later, see 
6940                                         // IdenticalNameAndTypeName), we have to check whether left 
6941                                         // is an instance variable in a static context
6942                                         //
6943                                         // However, if the left-hand value is explicitly given, then
6944                                         // it is already our instance expression, so we aren't in
6945                                         // static context.
6946                                         //
6947
6948                                         if (ec.IsStatic && !left_is_explicit && left is IMemberExpr){
6949                                                 IMemberExpr mexp = (IMemberExpr) left;
6950
6951                                                 if (!mexp.IsStatic){
6952                                                         SimpleName.Error_ObjectRefRequired (ec, loc, mexp.Name);
6953                                                         return null;
6954                                                 }
6955                                         }
6956
6957                                         if ((mg != null) && IdenticalNameAndTypeName (ec, left_original, loc))
6958                                                 mg.IdenticalTypeName = true;
6959
6960                                         me.InstanceExpression = left;
6961                                 }
6962
6963                                 return member_lookup;
6964                         }
6965
6966                         Console.WriteLine ("Left is: " + left);
6967                         Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet");
6968                         Environment.Exit (1);
6969                         return null;
6970                 }
6971                 
6972                 public Expression DoResolve (EmitContext ec, Expression right_side, ResolveFlags flags)
6973                 {
6974                         if (type != null)
6975                                 throw new Exception ();
6976
6977                         //
6978                         // Resolve the expression with flow analysis turned off, we'll do the definite
6979                         // assignment checks later.  This is because we don't know yet what the expression
6980                         // will resolve to - it may resolve to a FieldExpr and in this case we must do the
6981                         // definite assignment check on the actual field and not on the whole struct.
6982                         //
6983
6984                         Expression original = expr;
6985                         expr = expr.Resolve (ec, flags | ResolveFlags.DisableFlowAnalysis);
6986                         if (expr == null)
6987                                 return null;
6988
6989                         if (expr is SimpleName){
6990                                 SimpleName child_expr = (SimpleName) expr;
6991
6992                                 Expression new_expr = new SimpleName (child_expr.Name, Identifier, loc);
6993
6994                                 return new_expr.Resolve (ec, flags);
6995                         }
6996                                         
6997                         //
6998                         // TODO: I mailed Ravi about this, and apparently we can get rid
6999                         // of this and put it in the right place.
7000                         // 
7001                         // Handle enums here when they are in transit.
7002                         // Note that we cannot afford to hit MemberLookup in this case because
7003                         // it will fail to find any members at all
7004                         //
7005
7006                         Type expr_type = expr.Type;
7007                         if (expr is TypeExpr){
7008                                 if (!ec.DeclSpace.CheckAccessLevel (expr_type)){
7009                                         Report.Error_T (122, loc, expr_type);
7010                                         return null;
7011                                 }
7012
7013                                 if (expr_type == TypeManager.enum_type || expr_type.IsSubclassOf (TypeManager.enum_type)){
7014                                         Enum en = TypeManager.LookupEnum (expr_type);
7015
7016                                         if (en != null) {
7017                                                 object value = en.LookupEnumValue (ec, Identifier, loc);
7018                                                 
7019                                                 if (value != null){
7020                                                         Constant c = Constantify (value, en.UnderlyingType);
7021                                                         return new EnumConstant (c, expr_type);
7022                                                 }
7023                                         }
7024                                 }
7025                         }
7026                         
7027                         if (expr_type.IsPointer){
7028                                 Error (23, "The `.' operator can not be applied to pointer operands (" +
7029                                        TypeManager.CSharpName (expr_type) + ")");
7030                                 return null;
7031                         }
7032
7033                         Expression member_lookup;
7034                         member_lookup = MemberLookupFinal (ec, expr_type, expr_type, Identifier, loc);
7035                         if (member_lookup == null)
7036                                 return null;
7037
7038                         if (member_lookup is TypeExpr) {
7039                                 if (!(expr is TypeExpr) && !(expr is SimpleName)) {
7040                                         Error (572, "Can't reference type `" + Identifier + "' through an expression; try `" +
7041                                                member_lookup.Type + "' instead");
7042                                         return null;
7043                                 }
7044
7045                                 return member_lookup;
7046                         }
7047                         
7048                         member_lookup = ResolveMemberAccess (ec, member_lookup, expr, loc, original);
7049                         if (member_lookup == null)
7050                                 return null;
7051
7052                         // The following DoResolve/DoResolveLValue will do the definite assignment
7053                         // check.
7054
7055                         if (right_side != null)
7056                                 member_lookup = member_lookup.DoResolveLValue (ec, right_side);
7057                         else
7058                                 member_lookup = member_lookup.DoResolve (ec);
7059
7060                         return member_lookup;
7061                 }
7062
7063                 public override Expression DoResolve (EmitContext ec)
7064                 {
7065                         return DoResolve (ec, null, ResolveFlags.VariableOrValue |
7066                                           ResolveFlags.SimpleName | ResolveFlags.Type);
7067                 }
7068
7069                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
7070                 {
7071                         return DoResolve (ec, right_side, ResolveFlags.VariableOrValue |
7072                                           ResolveFlags.SimpleName | ResolveFlags.Type);
7073                 }
7074
7075                 public override Expression ResolveAsTypeStep (EmitContext ec)
7076                 {
7077                         string fname = null;
7078                         MemberAccess full_expr = this;
7079                         while (full_expr != null) {
7080                                 if (fname != null)
7081                                         fname = String.Concat (full_expr.Identifier, ".", fname);
7082                                 else
7083                                         fname = full_expr.Identifier;
7084
7085                                 if (full_expr.Expr is SimpleName) {
7086                                         string full_name = String.Concat (((SimpleName) full_expr.Expr).Name, ".", fname);
7087                                         Type fully_qualified = ec.DeclSpace.FindType (loc, full_name);
7088                                         if (fully_qualified != null)
7089                                                 return new TypeExpression (fully_qualified, loc);
7090                                 }
7091
7092                                 full_expr = full_expr.Expr as MemberAccess;
7093                         }
7094
7095                         Expression new_expr = expr.ResolveAsTypeStep (ec);
7096
7097                         if (new_expr == null)
7098                                 return null;
7099
7100                         if (new_expr is SimpleName){
7101                                 SimpleName child_expr = (SimpleName) new_expr;
7102                                 
7103                                 new_expr = new SimpleName (child_expr.Name, Identifier, loc);
7104
7105                                 return new_expr.ResolveAsTypeStep (ec);
7106                         }
7107
7108                         Type expr_type = new_expr.Type;
7109                       
7110                         if (expr_type.IsPointer){
7111                                 Error (23, "The `.' operator can not be applied to pointer operands (" +
7112                                        TypeManager.CSharpName (expr_type) + ")");
7113                                 return null;
7114                         }
7115                         
7116                         Expression member_lookup;
7117                         member_lookup = MemberLookupFinal (ec, expr_type, expr_type, Identifier, loc);
7118                         if (member_lookup == null)
7119                                 return null;
7120
7121                         if (member_lookup is TypeExpr){
7122                                 member_lookup.Resolve (ec, ResolveFlags.Type);
7123                                 return member_lookup;
7124                         } 
7125
7126                         return null;                    
7127                 }
7128
7129                 public override void Emit (EmitContext ec)
7130                 {
7131                         throw new Exception ("Should not happen");
7132                 }
7133
7134                 public override string ToString ()
7135                 {
7136                         return expr + "." + Identifier;
7137                 }
7138         }
7139
7140         /// <summary>
7141         ///   Implements checked expressions
7142         /// </summary>
7143         public class CheckedExpr : Expression {
7144
7145                 public Expression Expr;
7146
7147                 public CheckedExpr (Expression e, Location l)
7148                 {
7149                         Expr = e;
7150                         loc = l;
7151                 }
7152
7153                 public override Expression DoResolve (EmitContext ec)
7154                 {
7155                         bool last_check = ec.CheckState;
7156                         bool last_const_check = ec.ConstantCheckState;
7157
7158                         ec.CheckState = true;
7159                         ec.ConstantCheckState = true;
7160                         Expr = Expr.Resolve (ec);
7161                         ec.CheckState = last_check;
7162                         ec.ConstantCheckState = last_const_check;
7163                         
7164                         if (Expr == null)
7165                                 return null;
7166
7167                         if (Expr is Constant)
7168                                 return Expr;
7169                         
7170                         eclass = Expr.eclass;
7171                         type = Expr.Type;
7172                         return this;
7173                 }
7174
7175                 public override void Emit (EmitContext ec)
7176                 {
7177                         bool last_check = ec.CheckState;
7178                         bool last_const_check = ec.ConstantCheckState;
7179                         
7180                         ec.CheckState = true;
7181                         ec.ConstantCheckState = true;
7182                         Expr.Emit (ec);
7183                         ec.CheckState = last_check;
7184                         ec.ConstantCheckState = last_const_check;
7185                 }
7186                 
7187         }
7188
7189         /// <summary>
7190         ///   Implements the unchecked expression
7191         /// </summary>
7192         public class UnCheckedExpr : Expression {
7193
7194                 public Expression Expr;
7195
7196                 public UnCheckedExpr (Expression e, Location l)
7197                 {
7198                         Expr = e;
7199                         loc = l;
7200                 }
7201
7202                 public override Expression DoResolve (EmitContext ec)
7203                 {
7204                         bool last_check = ec.CheckState;
7205                         bool last_const_check = ec.ConstantCheckState;
7206
7207                         ec.CheckState = false;
7208                         ec.ConstantCheckState = false;
7209                         Expr = Expr.Resolve (ec);
7210                         ec.CheckState = last_check;
7211                         ec.ConstantCheckState = last_const_check;
7212
7213                         if (Expr == null)
7214                                 return null;
7215
7216                         if (Expr is Constant)
7217                                 return Expr;
7218                         
7219                         eclass = Expr.eclass;
7220                         type = Expr.Type;
7221                         return this;
7222                 }
7223
7224                 public override void Emit (EmitContext ec)
7225                 {
7226                         bool last_check = ec.CheckState;
7227                         bool last_const_check = ec.ConstantCheckState;
7228                         
7229                         ec.CheckState = false;
7230                         ec.ConstantCheckState = false;
7231                         Expr.Emit (ec);
7232                         ec.CheckState = last_check;
7233                         ec.ConstantCheckState = last_const_check;
7234                 }
7235                 
7236         }
7237
7238         /// <summary>
7239         ///   An Element Access expression.
7240         ///
7241         ///   During semantic analysis these are transformed into 
7242         ///   IndexerAccess, ArrayAccess or a PointerArithmetic.
7243         /// </summary>
7244         public class ElementAccess : Expression {
7245                 public ArrayList  Arguments;
7246                 public Expression Expr;
7247                 
7248                 public ElementAccess (Expression e, ArrayList e_list, Location l)
7249                 {
7250                         Expr = e;
7251
7252                         loc  = l;
7253                         
7254                         if (e_list == null)
7255                                 return;
7256                         
7257                         Arguments = new ArrayList ();
7258                         foreach (Expression tmp in e_list)
7259                                 Arguments.Add (new Argument (tmp, Argument.AType.Expression));
7260                         
7261                 }
7262
7263                 bool CommonResolve (EmitContext ec)
7264                 {
7265                         Expr = Expr.Resolve (ec);
7266
7267                         if (Expr == null) 
7268                                 return false;
7269
7270                         if (Arguments == null)
7271                                 return false;
7272
7273                         foreach (Argument a in Arguments){
7274                                 if (!a.Resolve (ec, loc))
7275                                         return false;
7276                         }
7277
7278                         return true;
7279                 }
7280
7281                 Expression MakePointerAccess ()
7282                 {
7283                         Type t = Expr.Type;
7284
7285                         if (t == TypeManager.void_ptr_type){
7286                                 Error (242, "The array index operation is not valid for void pointers");
7287                                 return null;
7288                         }
7289                         if (Arguments.Count != 1){
7290                                 Error (196, "A pointer must be indexed by a single value");
7291                                 return null;
7292                         }
7293                         Expression p;
7294
7295                         p = new PointerArithmetic (true, Expr, ((Argument)Arguments [0]).Expr, t, loc);
7296                         return new Indirection (p, loc);
7297                 }
7298                 
7299                 public override Expression DoResolve (EmitContext ec)
7300                 {
7301                         if (!CommonResolve (ec))
7302                                 return null;
7303
7304                         //
7305                         // We perform some simple tests, and then to "split" the emit and store
7306                         // code we create an instance of a different class, and return that.
7307                         //
7308                         // I am experimenting with this pattern.
7309                         //
7310                         Type t = Expr.Type;
7311
7312                         if (t == TypeManager.array_type){
7313                                 Report.Error (21, loc, "Cannot use indexer on System.Array");
7314                                 return null;
7315                         }
7316                         
7317                         if (t.IsArray)
7318                                 return (new ArrayAccess (this, loc)).Resolve (ec);
7319                         else if (t.IsPointer)
7320                                 return MakePointerAccess ();
7321                         else
7322                                 return (new IndexerAccess (this, loc)).Resolve (ec);
7323                 }
7324
7325                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
7326                 {
7327                         if (!CommonResolve (ec))
7328                                 return null;
7329
7330                         Type t = Expr.Type;
7331                         if (t.IsArray)
7332                                 return (new ArrayAccess (this, loc)).ResolveLValue (ec, right_side);
7333                         else if (t.IsPointer)
7334                                 return MakePointerAccess ();
7335                         else
7336                                 return (new IndexerAccess (this, loc)).ResolveLValue (ec, right_side);
7337                 }
7338                 
7339                 public override void Emit (EmitContext ec)
7340                 {
7341                         throw new Exception ("Should never be reached");
7342                 }
7343         }
7344
7345         /// <summary>
7346         ///   Implements array access 
7347         /// </summary>
7348         public class ArrayAccess : Expression, IAssignMethod, IMemoryLocation {
7349                 //
7350                 // Points to our "data" repository
7351                 //
7352                 ElementAccess ea;
7353
7354                 LocalTemporary [] cached_locations;
7355                 
7356                 public ArrayAccess (ElementAccess ea_data, Location l)
7357                 {
7358                         ea = ea_data;
7359                         eclass = ExprClass.Variable;
7360                         loc = l;
7361                 }
7362
7363                 public override Expression DoResolve (EmitContext ec)
7364                 {
7365 #if false
7366                         ExprClass eclass = ea.Expr.eclass;
7367
7368                         // As long as the type is valid
7369                         if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
7370                               eclass == ExprClass.Value)) {
7371                                 ea.Expr.Error_UnexpectedKind ("variable or value");
7372                                 return null;
7373                         }
7374 #endif
7375
7376                         Type t = ea.Expr.Type;
7377                         if (t.GetArrayRank () != ea.Arguments.Count){
7378                                 ea.Error (22,
7379                                           "Incorrect number of indexes for array " +
7380                                           " expected: " + t.GetArrayRank () + " got: " +
7381                                           ea.Arguments.Count);
7382                                 return null;
7383                         }
7384
7385                         type = TypeManager.GetElementType (t);
7386                         if (type.IsPointer && !ec.InUnsafe){
7387                                 UnsafeError (ea.Location);
7388                                 return null;
7389                         }
7390
7391                         foreach (Argument a in ea.Arguments){
7392                                 Type argtype = a.Type;
7393
7394                                 if (argtype == TypeManager.int32_type ||
7395                                     argtype == TypeManager.uint32_type ||
7396                                     argtype == TypeManager.int64_type ||
7397                                     argtype == TypeManager.uint64_type)
7398                                         continue;
7399
7400                                 //
7401                                 // Mhm.  This is strage, because the Argument.Type is not the same as
7402                                 // Argument.Expr.Type: the value changes depending on the ref/out setting.
7403                                 //
7404                                 // Wonder if I will run into trouble for this.
7405                                 //
7406                                 a.Expr = ExpressionToArrayArgument (ec, a.Expr, ea.Location);
7407                                 if (a.Expr == null)
7408                                         return null;
7409                         }
7410                         
7411                         eclass = ExprClass.Variable;
7412
7413                         return this;
7414                 }
7415
7416                 /// <summary>
7417                 ///    Emits the right opcode to load an object of Type `t'
7418                 ///    from an array of T
7419                 /// </summary>
7420                 static public void EmitLoadOpcode (ILGenerator ig, Type type)
7421                 {
7422                         if (type == TypeManager.byte_type || type == TypeManager.bool_type)
7423                                 ig.Emit (OpCodes.Ldelem_U1);
7424                         else if (type == TypeManager.sbyte_type)
7425                                 ig.Emit (OpCodes.Ldelem_I1);
7426                         else if (type == TypeManager.short_type)
7427                                 ig.Emit (OpCodes.Ldelem_I2);
7428                         else if (type == TypeManager.ushort_type || type == TypeManager.char_type)
7429                                 ig.Emit (OpCodes.Ldelem_U2);
7430                         else if (type == TypeManager.int32_type)
7431                                 ig.Emit (OpCodes.Ldelem_I4);
7432                         else if (type == TypeManager.uint32_type)
7433                                 ig.Emit (OpCodes.Ldelem_U4);
7434                         else if (type == TypeManager.uint64_type)
7435                                 ig.Emit (OpCodes.Ldelem_I8);
7436                         else if (type == TypeManager.int64_type)
7437                                 ig.Emit (OpCodes.Ldelem_I8);
7438                         else if (type == TypeManager.float_type)
7439                                 ig.Emit (OpCodes.Ldelem_R4);
7440                         else if (type == TypeManager.double_type)
7441                                 ig.Emit (OpCodes.Ldelem_R8);
7442                         else if (type == TypeManager.intptr_type)
7443                                 ig.Emit (OpCodes.Ldelem_I);
7444                         else if (TypeManager.IsEnumType (type)){
7445                                 EmitLoadOpcode (ig, TypeManager.EnumToUnderlying (type));
7446                         } else if (type.IsValueType){
7447                                 ig.Emit (OpCodes.Ldelema, type);
7448                                 ig.Emit (OpCodes.Ldobj, type);
7449                         } else 
7450                                 ig.Emit (OpCodes.Ldelem_Ref);
7451                 }
7452
7453                 /// <summary>
7454                 ///    Emits the right opcode to store an object of Type `t'
7455                 ///    from an array of T.  
7456                 /// </summary>
7457                 static public void EmitStoreOpcode (ILGenerator ig, Type t)
7458                 {
7459                         bool is_stobj;
7460                         OpCode op = GetStoreOpcode (t, out is_stobj);
7461                         if (is_stobj)
7462                                 ig.Emit (OpCodes.Stobj, t);
7463                         else
7464                                 ig.Emit (op);
7465                 }
7466
7467                 /// <summary>
7468                 ///    Returns the right opcode to store an object of Type `t'
7469                 ///    from an array of T.  
7470                 /// </summary>
7471                 static public OpCode GetStoreOpcode (Type t, out bool is_stobj)
7472                 {
7473                         //Console.WriteLine (new System.Diagnostics.StackTrace ());
7474                         is_stobj = false;
7475                         t = TypeManager.TypeToCoreType (t);
7476                         if (TypeManager.IsEnumType (t) && t != TypeManager.enum_type)
7477                                 t = TypeManager.EnumToUnderlying (t);
7478                         if (t == TypeManager.byte_type || t == TypeManager.sbyte_type ||
7479                             t == TypeManager.bool_type)
7480                                 return OpCodes.Stelem_I1;
7481                         else if (t == TypeManager.short_type || t == TypeManager.ushort_type ||
7482                                  t == TypeManager.char_type)
7483                                 return OpCodes.Stelem_I2;
7484                         else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
7485                                 return OpCodes.Stelem_I4;
7486                         else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
7487                                 return OpCodes.Stelem_I8;
7488                         else if (t == TypeManager.float_type)
7489                                 return OpCodes.Stelem_R4;
7490                         else if (t == TypeManager.double_type)
7491                                 return OpCodes.Stelem_R8;
7492                         else if (t == TypeManager.intptr_type) {
7493                                 is_stobj = true;
7494                                 return OpCodes.Stobj;
7495                         } else if (t.IsValueType) {
7496                                 is_stobj = true;
7497                                 return OpCodes.Stobj;
7498                         } else
7499                                 return OpCodes.Stelem_Ref;
7500                 }
7501
7502                 MethodInfo FetchGetMethod ()
7503                 {
7504                         ModuleBuilder mb = CodeGen.Module.Builder;
7505                         int arg_count = ea.Arguments.Count;
7506                         Type [] args = new Type [arg_count];
7507                         MethodInfo get;
7508                         
7509                         for (int i = 0; i < arg_count; i++){
7510                                 //args [i++] = a.Type;
7511                                 args [i] = TypeManager.int32_type;
7512                         }
7513                         
7514                         get = mb.GetArrayMethod (
7515                                 ea.Expr.Type, "Get",
7516                                 CallingConventions.HasThis |
7517                                 CallingConventions.Standard,
7518                                 type, args);
7519                         return get;
7520                 }
7521                                 
7522
7523                 MethodInfo FetchAddressMethod ()
7524                 {
7525                         ModuleBuilder mb = CodeGen.Module.Builder;
7526                         int arg_count = ea.Arguments.Count;
7527                         Type [] args = new Type [arg_count];
7528                         MethodInfo address;
7529                         Type ret_type;
7530                         
7531                         ret_type = TypeManager.GetReferenceType (type);
7532                         
7533                         for (int i = 0; i < arg_count; i++){
7534                                 //args [i++] = a.Type;
7535                                 args [i] = TypeManager.int32_type;
7536                         }
7537                         
7538                         address = mb.GetArrayMethod (
7539                                 ea.Expr.Type, "Address",
7540                                 CallingConventions.HasThis |
7541                                 CallingConventions.Standard,
7542                                 ret_type, args);
7543
7544                         return address;
7545                 }
7546
7547                 //
7548                 // Load the array arguments into the stack.
7549                 //
7550                 // If we have been requested to cache the values (cached_locations array
7551                 // initialized), then load the arguments the first time and store them
7552                 // in locals.  otherwise load from local variables.
7553                 //
7554                 void LoadArrayAndArguments (EmitContext ec)
7555                 {
7556                         ILGenerator ig = ec.ig;
7557                         
7558                         if (cached_locations == null){
7559                                 ea.Expr.Emit (ec);
7560                                 foreach (Argument a in ea.Arguments){
7561                                         Type argtype = a.Expr.Type;
7562                                         
7563                                         a.Expr.Emit (ec);
7564                                         
7565                                         if (argtype == TypeManager.int64_type)
7566                                                 ig.Emit (OpCodes.Conv_Ovf_I);
7567                                         else if (argtype == TypeManager.uint64_type)
7568                                                 ig.Emit (OpCodes.Conv_Ovf_I_Un);
7569                                 }
7570                                 return;
7571                         }
7572
7573                         if (cached_locations [0] == null){
7574                                 cached_locations [0] = new LocalTemporary (ec, ea.Expr.Type);
7575                                 ea.Expr.Emit (ec);
7576                                 ig.Emit (OpCodes.Dup);
7577                                 cached_locations [0].Store (ec);
7578                                 
7579                                 int j = 1;
7580                                 
7581                                 foreach (Argument a in ea.Arguments){
7582                                         Type argtype = a.Expr.Type;
7583                                         
7584                                         cached_locations [j] = new LocalTemporary (ec, TypeManager.intptr_type /* a.Expr.Type */);
7585                                         a.Expr.Emit (ec);
7586                                         if (argtype == TypeManager.int64_type)
7587                                                 ig.Emit (OpCodes.Conv_Ovf_I);
7588                                         else if (argtype == TypeManager.uint64_type)
7589                                                 ig.Emit (OpCodes.Conv_Ovf_I_Un);
7590
7591                                         ig.Emit (OpCodes.Dup);
7592                                         cached_locations [j].Store (ec);
7593                                         j++;
7594                                 }
7595                                 return;
7596                         }
7597
7598                         foreach (LocalTemporary lt in cached_locations)
7599                                 lt.Emit (ec);
7600                 }
7601
7602                 public new void CacheTemporaries (EmitContext ec)
7603                 {
7604                         cached_locations = new LocalTemporary [ea.Arguments.Count + 1];
7605                 }
7606                 
7607                 public override void Emit (EmitContext ec)
7608                 {
7609                         int rank = ea.Expr.Type.GetArrayRank ();
7610                         ILGenerator ig = ec.ig;
7611
7612                         LoadArrayAndArguments (ec);
7613                         
7614                         if (rank == 1)
7615                                 EmitLoadOpcode (ig, type);
7616                         else {
7617                                 MethodInfo method;
7618                                 
7619                                 method = FetchGetMethod ();
7620                                 ig.Emit (OpCodes.Call, method);
7621                         }
7622                 }
7623
7624                 public void EmitAssign (EmitContext ec, Expression source)
7625                 {
7626                         int rank = ea.Expr.Type.GetArrayRank ();
7627                         ILGenerator ig = ec.ig;
7628                         Type t = source.Type;
7629
7630                         LoadArrayAndArguments (ec);
7631
7632                         //
7633                         // The stobj opcode used by value types will need
7634                         // an address on the stack, not really an array/array
7635                         // pair
7636                         //
7637                         if (rank == 1){
7638                                 if (t == TypeManager.enum_type || t == TypeManager.decimal_type ||
7639                                     (t.IsSubclassOf (TypeManager.value_type) && !TypeManager.IsEnumType (t) && !TypeManager.IsBuiltinType (t)))
7640                                         ig.Emit (OpCodes.Ldelema, t);
7641                         }
7642                         
7643                         source.Emit (ec);
7644
7645                         if (rank == 1)
7646                                 EmitStoreOpcode (ig, t);
7647                         else {
7648                                 ModuleBuilder mb = CodeGen.Module.Builder;
7649                                 int arg_count = ea.Arguments.Count;
7650                                 Type [] args = new Type [arg_count + 1];
7651                                 MethodInfo set;
7652                                 
7653                                 for (int i = 0; i < arg_count; i++){
7654                                         //args [i++] = a.Type;
7655                                         args [i] = TypeManager.int32_type;
7656                                 }
7657
7658                                 args [arg_count] = type;
7659                                 
7660                                 set = mb.GetArrayMethod (
7661                                         ea.Expr.Type, "Set",
7662                                         CallingConventions.HasThis |
7663                                         CallingConventions.Standard,
7664                                         TypeManager.void_type, args);
7665                                 
7666                                 ig.Emit (OpCodes.Call, set);
7667                         }
7668                 }
7669
7670                 public void AddressOf (EmitContext ec, AddressOp mode)
7671                 {
7672                         int rank = ea.Expr.Type.GetArrayRank ();
7673                         ILGenerator ig = ec.ig;
7674
7675                         LoadArrayAndArguments (ec);
7676
7677                         if (rank == 1){
7678                                 ig.Emit (OpCodes.Ldelema, type);
7679                         } else {
7680                                 MethodInfo address = FetchAddressMethod ();
7681                                 ig.Emit (OpCodes.Call, address);
7682                         }
7683                 }
7684         }
7685
7686         
7687         class Indexers {
7688                 public ArrayList Properties;
7689                 static Hashtable map;
7690
7691                 public struct Indexer {
7692                         public readonly Type Type;
7693                         public readonly MethodInfo Getter, Setter;
7694
7695                         public Indexer (Type type, MethodInfo get, MethodInfo set)
7696                         {
7697                                 this.Type = type;
7698                                 this.Getter = get;
7699                                 this.Setter = set;
7700                         }
7701                 }
7702
7703                 static Indexers ()
7704                 {
7705                         map = new Hashtable ();
7706                 }
7707
7708                 Indexers ()
7709                 {
7710                         Properties = new ArrayList ();
7711                 }
7712                                 
7713                 void Append (MemberInfo [] mi)
7714                 {
7715                         foreach (PropertyInfo property in mi){
7716                                 MethodInfo get, set;
7717                                 
7718                                 get = property.GetGetMethod (true);
7719                                 set = property.GetSetMethod (true);
7720                                 Properties.Add (new Indexer (property.PropertyType, get, set));
7721                         }
7722                 }
7723
7724                 static private MemberInfo [] GetIndexersForTypeOrInterface (Type caller_type, Type lookup_type)
7725                 {
7726                         string p_name = TypeManager.IndexerPropertyName (lookup_type);
7727
7728                         MemberInfo [] mi = TypeManager.MemberLookup (
7729                                 caller_type, caller_type, lookup_type, MemberTypes.Property,
7730                                 BindingFlags.Public | BindingFlags.Instance |
7731                                 BindingFlags.DeclaredOnly, p_name);
7732
7733                         if (mi == null || mi.Length == 0)
7734                                 return null;
7735
7736                         return mi;
7737                 }
7738                 
7739                 static public Indexers GetIndexersForType (Type caller_type, Type lookup_type, Location loc) 
7740                 {
7741                         Indexers ix = (Indexers) map [lookup_type];
7742
7743                         if (ix != null)
7744                                 return ix;
7745
7746                         Type copy = lookup_type;
7747                         while (copy != TypeManager.object_type && copy != null){
7748                                 MemberInfo [] mi = GetIndexersForTypeOrInterface (caller_type, copy);
7749
7750                                 if (mi != null){
7751                                         if (ix == null)
7752                                                 ix = new Indexers ();
7753
7754                                         ix.Append (mi);
7755                                 }
7756                                         
7757                                 copy = copy.BaseType;
7758                         }
7759
7760                         if (!lookup_type.IsInterface)
7761                                 return ix;
7762
7763                         TypeExpr [] ifaces = TypeManager.GetInterfaces (lookup_type);
7764                         if (ifaces != null) {
7765                                 foreach (TypeExpr iface in ifaces) {
7766                                         Type itype = iface.Type;
7767                                         MemberInfo [] mi = GetIndexersForTypeOrInterface (caller_type, itype);
7768                                         if (mi != null){
7769                                                 if (ix == null)
7770                                                         ix = new Indexers ();
7771                                         
7772                                                 ix.Append (mi);
7773                                         }
7774                                 }
7775                         }
7776
7777                         return ix;
7778                 }
7779         }
7780
7781         /// <summary>
7782         ///   Expressions that represent an indexer call.
7783         /// </summary>
7784         public class IndexerAccess : Expression, IAssignMethod {
7785                 //
7786                 // Points to our "data" repository
7787                 //
7788                 MethodInfo get, set;
7789                 ArrayList set_arguments;
7790                 bool is_base_indexer;
7791
7792                 protected Type indexer_type;
7793                 protected Type current_type;
7794                 protected Expression instance_expr;
7795                 protected ArrayList arguments;
7796                 
7797                 public IndexerAccess (ElementAccess ea, Location loc)
7798                         : this (ea.Expr, false, loc)
7799                 {
7800                         this.arguments = ea.Arguments;
7801                 }
7802
7803                 protected IndexerAccess (Expression instance_expr, bool is_base_indexer,
7804                                          Location loc)
7805                 {
7806                         this.instance_expr = instance_expr;
7807                         this.is_base_indexer = is_base_indexer;
7808                         this.eclass = ExprClass.Value;
7809                         this.loc = loc;
7810                 }
7811
7812                 protected virtual bool CommonResolve (EmitContext ec)
7813                 {
7814                         indexer_type = instance_expr.Type;
7815                         current_type = ec.ContainerType;
7816
7817                         return true;
7818                 }
7819
7820                 public override Expression DoResolve (EmitContext ec)
7821                 {
7822                         ArrayList AllGetters = new ArrayList();
7823                         if (!CommonResolve (ec))
7824                                 return null;
7825
7826                         //
7827                         // Step 1: Query for all `Item' *properties*.  Notice
7828                         // that the actual methods are pointed from here.
7829                         //
7830                         // This is a group of properties, piles of them.  
7831
7832                         bool found_any = false, found_any_getters = false;
7833                         Type lookup_type = indexer_type;
7834
7835                         Indexers ilist;
7836                         ilist = Indexers.GetIndexersForType (current_type, lookup_type, loc);
7837                         if (ilist != null) {
7838                                 found_any = true;
7839                                 if (ilist.Properties != null) {
7840                                         foreach (Indexers.Indexer ix in ilist.Properties) {
7841                                                 if (ix.Getter != null)
7842                                                         AllGetters.Add(ix.Getter);
7843                                         }
7844                                 }
7845                         }
7846
7847                         if (AllGetters.Count > 0) {
7848                                 found_any_getters = true;
7849                                 get = (MethodInfo) Invocation.OverloadResolve (
7850                                         ec, new MethodGroupExpr (AllGetters, loc), arguments, loc);
7851                         }
7852
7853                         if (!found_any) {
7854                                 Report.Error (21, loc,
7855                                               "Type `" + TypeManager.CSharpName (indexer_type) +
7856                                               "' does not have any indexers defined");
7857                                 return null;
7858                         }
7859
7860                         if (!found_any_getters) {
7861                                 Error (154, "indexer can not be used in this context, because " +
7862                                        "it lacks a `get' accessor");
7863                                 return null;
7864                         }
7865
7866                         if (get == null) {
7867                                 Error (1501, "No Overload for method `this' takes `" +
7868                                        arguments.Count + "' arguments");
7869                                 return null;
7870                         }
7871
7872                         //
7873                         // Only base will allow this invocation to happen.
7874                         //
7875                         if (get.IsAbstract && this is BaseIndexerAccess){
7876                                 Report.Error (205, loc, "Cannot call an abstract base indexer: " + Invocation.FullMethodDesc (get));
7877                                 return null;
7878                         }
7879
7880                         type = get.ReturnType;
7881                         if (type.IsPointer && !ec.InUnsafe){
7882                                 UnsafeError (loc);
7883                                 return null;
7884                         }
7885                         
7886                         eclass = ExprClass.IndexerAccess;
7887                         return this;
7888                 }
7889
7890                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
7891                 {
7892                         ArrayList AllSetters = new ArrayList();
7893                         if (!CommonResolve (ec))
7894                                 return null;
7895
7896                         bool found_any = false, found_any_setters = false;
7897
7898                         Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type, loc);
7899                         if (ilist != null) {
7900                                 found_any = true;
7901                                 if (ilist.Properties != null) {
7902                                         foreach (Indexers.Indexer ix in ilist.Properties) {
7903                                                 if (ix.Setter != null)
7904                                                         AllSetters.Add(ix.Setter);
7905                                         }
7906                                 }
7907                         }
7908                         if (AllSetters.Count > 0) {
7909                                 found_any_setters = true;
7910                                 set_arguments = (ArrayList) arguments.Clone ();
7911                                 set_arguments.Add (new Argument (right_side, Argument.AType.Expression));
7912                                 set = (MethodInfo) Invocation.OverloadResolve (
7913                                         ec, new MethodGroupExpr (AllSetters, loc),
7914                                         set_arguments, loc);
7915                         }
7916
7917                         if (!found_any) {
7918                                 Report.Error (21, loc,
7919                                               "Type `" + TypeManager.CSharpName (indexer_type) +
7920                                               "' does not have any indexers defined");
7921                                 return null;
7922                         }
7923
7924                         if (!found_any_setters) {
7925                                 Error (154, "indexer can not be used in this context, because " +
7926                                        "it lacks a `set' accessor");
7927                                 return null;
7928                         }
7929
7930                         if (set == null) {
7931                                 Error (1501, "No Overload for method `this' takes `" +
7932                                        arguments.Count + "' arguments");
7933                                 return null;
7934                         }
7935
7936                         //
7937                         // Only base will allow this invocation to happen.
7938                         //
7939                         if (set.IsAbstract && this is BaseIndexerAccess){
7940                                 Report.Error (205, loc, "Cannot call an abstract base indexer: " + Invocation.FullMethodDesc (set));
7941                                 return null;
7942                         }
7943
7944                         //
7945                         // Now look for the actual match in the list of indexers to set our "return" type
7946                         //
7947                         type = TypeManager.void_type;   // default value
7948                         foreach (Indexers.Indexer ix in ilist.Properties){
7949                                 if (ix.Setter == set){
7950                                         type = ix.Type;
7951                                         break;
7952                                 }
7953                         }
7954                         
7955                         eclass = ExprClass.IndexerAccess;
7956                         return this;
7957                 }
7958                 
7959                 public override void Emit (EmitContext ec)
7960                 {
7961                         Invocation.EmitCall (ec, is_base_indexer, false, instance_expr, get, arguments, loc);
7962                 }
7963
7964                 //
7965                 // source is ignored, because we already have a copy of it from the
7966                 // LValue resolution and we have already constructed a pre-cached
7967                 // version of the arguments (ea.set_arguments);
7968                 //
7969                 public void EmitAssign (EmitContext ec, Expression source)
7970                 {
7971                         Invocation.EmitCall (ec, is_base_indexer, false, instance_expr, set, set_arguments, loc);
7972                 }
7973         }
7974
7975         /// <summary>
7976         ///   The base operator for method names
7977         /// </summary>
7978         public class BaseAccess : Expression {
7979                 string member;
7980                 
7981                 public BaseAccess (string member, Location l)
7982                 {
7983                         this.member = member;
7984                         loc = l;
7985                 }
7986
7987                 public override Expression DoResolve (EmitContext ec)
7988                 {
7989                         Expression c = CommonResolve (ec);
7990
7991                         if (c == null)
7992                                 return null;
7993
7994                         //
7995                         // MethodGroups use this opportunity to flag an error on lacking ()
7996                         //
7997                         if (!(c is MethodGroupExpr))
7998                                 return c.Resolve (ec);
7999                         return c;
8000                 }
8001
8002                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
8003                 {
8004                         Expression c = CommonResolve (ec);
8005
8006                         if (c == null)
8007                                 return null;
8008
8009                         //
8010                         // MethodGroups use this opportunity to flag an error on lacking ()
8011                         //
8012                         if (! (c is MethodGroupExpr))
8013                                 return c.DoResolveLValue (ec, right_side);
8014
8015                         return c;
8016                 }
8017
8018                 Expression CommonResolve (EmitContext ec)
8019                 {
8020                         Expression member_lookup;
8021                         Type current_type = ec.ContainerType;
8022                         Type base_type = current_type.BaseType;
8023                         Expression e;
8024
8025                         if (ec.IsStatic){
8026                                 Error (1511, "Keyword base is not allowed in static method");
8027                                 return null;
8028                         }
8029
8030                         if (ec.IsFieldInitializer){
8031                                 Error (1512, "Keyword base is not available in the current context");
8032                                 return null;
8033                         }
8034                         
8035                         member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type, member,
8036                                                       AllMemberTypes, AllBindingFlags, loc);
8037                         if (member_lookup == null) {
8038                                 MemberLookupFailed (ec, base_type, base_type, member, null, loc);
8039                                 return null;
8040                         }
8041
8042                         Expression left;
8043                         
8044                         if (ec.IsStatic)
8045                                 left = new TypeExpression (base_type, loc);
8046                         else
8047                                 left = ec.GetThis (loc);
8048                         
8049                         e = MemberAccess.ResolveMemberAccess (ec, member_lookup, left, loc, null);
8050
8051                         if (e is PropertyExpr){
8052                                 PropertyExpr pe = (PropertyExpr) e;
8053
8054                                 pe.IsBase = true;
8055                         }
8056
8057                         return e;
8058                 }
8059
8060                 public override void Emit (EmitContext ec)
8061                 {
8062                         throw new Exception ("Should never be called"); 
8063                 }
8064         }
8065
8066         /// <summary>
8067         ///   The base indexer operator
8068         /// </summary>
8069         public class BaseIndexerAccess : IndexerAccess {
8070                 public BaseIndexerAccess (ArrayList args, Location loc)
8071                         : base (null, true, loc)
8072                 {
8073                         arguments = new ArrayList ();
8074                         foreach (Expression tmp in args)
8075                                 arguments.Add (new Argument (tmp, Argument.AType.Expression));
8076                 }
8077
8078                 protected override bool CommonResolve (EmitContext ec)
8079                 {
8080                         instance_expr = ec.GetThis (loc);
8081
8082                         current_type = ec.ContainerType.BaseType;
8083                         indexer_type = current_type;
8084
8085                         foreach (Argument a in arguments){
8086                                 if (!a.Resolve (ec, loc))
8087                                         return false;
8088                         }
8089
8090                         return true;
8091                 }
8092         }
8093         
8094         /// <summary>
8095         ///   This class exists solely to pass the Type around and to be a dummy
8096         ///   that can be passed to the conversion functions (this is used by
8097         ///   foreach implementation to typecast the object return value from
8098         ///   get_Current into the proper type.  All code has been generated and
8099         ///   we only care about the side effect conversions to be performed
8100         ///
8101         ///   This is also now used as a placeholder where a no-action expression
8102         ///   is needed (the `New' class).
8103         /// </summary>
8104         public class EmptyExpression : Expression {
8105                 public EmptyExpression ()
8106                 {
8107                         type = TypeManager.object_type;
8108                         eclass = ExprClass.Value;
8109                         loc = Location.Null;
8110                 }
8111
8112                 public EmptyExpression (Type t)
8113                 {
8114                         type = t;
8115                         eclass = ExprClass.Value;
8116                         loc = Location.Null;
8117                 }
8118                 
8119                 public override Expression DoResolve (EmitContext ec)
8120                 {
8121                         return this;
8122                 }
8123
8124                 public override void Emit (EmitContext ec)
8125                 {
8126                         // nothing, as we only exist to not do anything.
8127                 }
8128
8129                 //
8130                 // This is just because we might want to reuse this bad boy
8131                 // instead of creating gazillions of EmptyExpressions.
8132                 // (CanImplicitConversion uses it)
8133                 //
8134                 public void SetType (Type t)
8135                 {
8136                         type = t;
8137                 }
8138         }
8139
8140         public class UserCast : Expression {
8141                 MethodBase method;
8142                 Expression source;
8143                 
8144                 public UserCast (MethodInfo method, Expression source, Location l)
8145                 {
8146                         this.method = method;
8147                         this.source = source;
8148                         type = method.ReturnType;
8149                         eclass = ExprClass.Value;
8150                         loc = l;
8151                 }
8152
8153                 public override Expression DoResolve (EmitContext ec)
8154                 {
8155                         //
8156                         // We are born fully resolved
8157                         //
8158                         return this;
8159                 }
8160
8161                 public override void Emit (EmitContext ec)
8162                 {
8163                         ILGenerator ig = ec.ig;
8164
8165                         source.Emit (ec);
8166                         
8167                         if (method is MethodInfo)
8168                                 ig.Emit (OpCodes.Call, (MethodInfo) method);
8169                         else
8170                                 ig.Emit (OpCodes.Call, (ConstructorInfo) method);
8171
8172                 }
8173         }
8174
8175         // <summary>
8176         //   This class is used to "construct" the type during a typecast
8177         //   operation.  Since the Type.GetType class in .NET can parse
8178         //   the type specification, we just use this to construct the type
8179         //   one bit at a time.
8180         // </summary>
8181         public class ComposedCast : TypeExpr {
8182                 Expression left;
8183                 string dim;
8184                 
8185                 public ComposedCast (Expression left, string dim, Location l)
8186                 {
8187                         this.left = left;
8188                         this.dim = dim;
8189                         loc = l;
8190                 }
8191
8192                 public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
8193                 {
8194                         Type ltype = ec.DeclSpace.ResolveType (left, false, loc);
8195                         if (ltype == null)
8196                                 return null;
8197
8198                         if ((ltype == TypeManager.void_type) && (dim != "*")) {
8199                                 Report.Error (1547, Location,
8200                                               "Keyword 'void' cannot be used in this context");
8201                                 return null;
8202                         }
8203
8204                         //
8205                         // ltype.Fullname is already fully qualified, so we can skip
8206                         // a lot of probes, and go directly to TypeManager.LookupType
8207                         //
8208                         string cname = ltype.FullName + dim;
8209                         type = TypeManager.LookupTypeDirect (cname);
8210                         if (type == null){
8211                                 //
8212                                 // For arrays of enumerations we are having a problem
8213                                 // with the direct lookup.  Need to investigate.
8214                                 //
8215                                 // For now, fall back to the full lookup in that case.
8216                                 //
8217                                 type = RootContext.LookupType (
8218                                         ec.DeclSpace, cname, false, loc);
8219
8220                                 if (type == null)
8221                                         return null;
8222                         }
8223
8224                         if (!ec.ResolvingTypeTree){
8225                                 //
8226                                 // If the above flag is set, this is being invoked from the ResolveType function.
8227                                 // Upper layers take care of the type validity in this context.
8228                                 //
8229                         if (!ec.InUnsafe && type.IsPointer){
8230                                 UnsafeError (loc);
8231                                 return null;
8232                         }
8233                         }
8234                         
8235                         eclass = ExprClass.Type;
8236                         return this;
8237                 }
8238
8239                 public override string Name {
8240                         get {
8241                                 return left + dim;
8242                         }
8243                 }
8244         }
8245
8246         //
8247         // This class is used to represent the address of an array, used
8248         // only by the Fixed statement, this is like the C "&a [0]" construct.
8249         //
8250         public class ArrayPtr : Expression {
8251                 Expression array;
8252                 
8253                 public ArrayPtr (Expression array, Location l)
8254                 {
8255                         Type array_type = TypeManager.GetElementType (array.Type);
8256
8257                         this.array = array;
8258
8259                         type = TypeManager.GetPointerType (array_type);
8260                         eclass = ExprClass.Value;
8261                         loc = l;
8262                 }
8263
8264                 public override void Emit (EmitContext ec)
8265                 {
8266                         ILGenerator ig = ec.ig;
8267                         
8268                         array.Emit (ec);
8269                         IntLiteral.EmitInt (ig, 0);
8270                         ig.Emit (OpCodes.Ldelema, TypeManager.GetElementType (array.Type));
8271                 }
8272
8273                 public override Expression DoResolve (EmitContext ec)
8274                 {
8275                         //
8276                         // We are born fully resolved
8277                         //
8278                         return this;
8279                 }
8280         }
8281
8282         //
8283         // Used by the fixed statement
8284         //
8285         public class StringPtr : Expression {
8286                 LocalBuilder b;
8287                 
8288                 public StringPtr (LocalBuilder b, Location l)
8289                 {
8290                         this.b = b;
8291                         eclass = ExprClass.Value;
8292                         type = TypeManager.char_ptr_type;
8293                         loc = l;
8294                 }
8295
8296                 public override Expression DoResolve (EmitContext ec)
8297                 {
8298                         // This should never be invoked, we are born in fully
8299                         // initialized state.
8300
8301                         return this;
8302                 }
8303
8304                 public override void Emit (EmitContext ec)
8305                 {
8306                         ILGenerator ig = ec.ig;
8307
8308                         ig.Emit (OpCodes.Ldloc, b);
8309                         ig.Emit (OpCodes.Conv_I);
8310                         ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
8311                         ig.Emit (OpCodes.Add);
8312                 }
8313         }
8314         
8315         //
8316         // Implements the `stackalloc' keyword
8317         //
8318         public class StackAlloc : Expression {
8319                 Type otype;
8320                 Expression t;
8321                 Expression count;
8322                 
8323                 public StackAlloc (Expression type, Expression count, Location l)
8324                 {
8325                         t = type;
8326                         this.count = count;
8327                         loc = l;
8328                 }
8329
8330                 public override Expression DoResolve (EmitContext ec)
8331                 {
8332                         count = count.Resolve (ec);
8333                         if (count == null)
8334                                 return null;
8335                         
8336                         if (count.Type != TypeManager.int32_type){
8337                                 count = Convert.ImplicitConversionRequired (ec, count, TypeManager.int32_type, loc);
8338                                 if (count == null)
8339                                         return null;
8340                         }
8341
8342                         if (ec.CurrentBranching.InCatch () ||
8343                             ec.CurrentBranching.InFinally (true)) {
8344                                 Error (255,
8345                                        "stackalloc can not be used in a catch or finally block");
8346                                 return null;
8347                         }
8348
8349                         otype = ec.DeclSpace.ResolveType (t, false, loc);
8350
8351                         if (otype == null)
8352                                 return null;
8353
8354                         if (!TypeManager.VerifyUnManaged (otype, loc))
8355                                 return null;
8356
8357                         type = TypeManager.GetPointerType (otype);
8358                         eclass = ExprClass.Value;
8359
8360                         return this;
8361                 }
8362
8363                 public override void Emit (EmitContext ec)
8364                 {
8365                         int size = GetTypeSize (otype);
8366                         ILGenerator ig = ec.ig;
8367                                 
8368                         if (size == 0)
8369                                 ig.Emit (OpCodes.Sizeof, otype);
8370                         else
8371                                 IntConstant.EmitInt (ig, size);
8372                         count.Emit (ec);
8373                         ig.Emit (OpCodes.Mul);
8374                         ig.Emit (OpCodes.Localloc);
8375                 }
8376         }
8377 }