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