2004-09-07 Miguel de Icaza <miguel@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).Resolve (ec);
2541                                         } else {
2542                                                 Expression t = Make32or64 (ec, right);
2543                                                 if (t != null)
2544                                                         return new PointerArithmetic (oper == Operator.Addition, left, t, l, loc).Resolve (ec);
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).Resolve (ec);
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                         this.loc = loc;
3414                         left = l;
3415                         right = r;
3416                         is_add = is_addition;
3417                 }
3418
3419                 public override Expression DoResolve (EmitContext ec)
3420                 {
3421                         eclass = ExprClass.Variable;
3422                         
3423                         if (left.Type == TypeManager.void_ptr_type) {
3424                                 Error (242, "The operation in question is undefined on void pointers");
3425                                 return null;
3426                         }
3427                         
3428                         return this;
3429                 }
3430
3431                 public override void Emit (EmitContext ec)
3432                 {
3433                         Type op_type = left.Type;
3434                         ILGenerator ig = ec.ig;
3435                         Type element = TypeManager.GetElementType (op_type);
3436                         int size = GetTypeSize (element);
3437                         Type rtype = right.Type;
3438                         
3439                         if (rtype.IsPointer){
3440                                 //
3441                                 // handle (pointer - pointer)
3442                                 //
3443                                 left.Emit (ec);
3444                                 right.Emit (ec);
3445                                 ig.Emit (OpCodes.Sub);
3446
3447                                 if (size != 1){
3448                                         if (size == 0)
3449                                                 ig.Emit (OpCodes.Sizeof, element);
3450                                         else 
3451                                                 IntLiteral.EmitInt (ig, size);
3452                                         ig.Emit (OpCodes.Div);
3453                                 }
3454                                 ig.Emit (OpCodes.Conv_I8);
3455                         } else {
3456                                 //
3457                                 // handle + and - on (pointer op int)
3458                                 //
3459                                 left.Emit (ec);
3460                                 ig.Emit (OpCodes.Conv_I);
3461                                 right.Emit (ec);
3462                                 if (size != 1){
3463                                         if (size == 0)
3464                                                 ig.Emit (OpCodes.Sizeof, element);
3465                                         else 
3466                                                 IntLiteral.EmitInt (ig, size);
3467                                         if (rtype == TypeManager.int64_type)
3468                                                 ig.Emit (OpCodes.Conv_I8);
3469                                         else if (rtype == TypeManager.uint64_type)
3470                                                 ig.Emit (OpCodes.Conv_U8);
3471                                         ig.Emit (OpCodes.Mul);
3472                                 }
3473                                 
3474                                 if (rtype == TypeManager.int64_type || rtype == TypeManager.uint64_type)
3475                                         ig.Emit (OpCodes.Conv_I);
3476                                 
3477                                 if (is_add)
3478                                         ig.Emit (OpCodes.Add);
3479                                 else
3480                                         ig.Emit (OpCodes.Sub);
3481                         }
3482                 }
3483         }
3484         
3485         /// <summary>
3486         ///   Implements the ternary conditional operator (?:)
3487         /// </summary>
3488         public class Conditional : Expression {
3489                 Expression expr, trueExpr, falseExpr;
3490                 
3491                 public Conditional (Expression expr, Expression trueExpr, Expression falseExpr, Location l)
3492                 {
3493                         this.expr = expr;
3494                         this.trueExpr = trueExpr;
3495                         this.falseExpr = falseExpr;
3496                         this.loc = l;
3497                 }
3498
3499                 public Expression Expr {
3500                         get {
3501                                 return expr;
3502                         }
3503                 }
3504
3505                 public Expression TrueExpr {
3506                         get {
3507                                 return trueExpr;
3508                         }
3509                 }
3510
3511                 public Expression FalseExpr {
3512                         get {
3513                                 return falseExpr;
3514                         }
3515                 }
3516
3517                 public override Expression DoResolve (EmitContext ec)
3518                 {
3519                         expr = expr.Resolve (ec);
3520
3521                         if (expr == null)
3522                                 return null;
3523                         
3524                         if (expr.Type != TypeManager.bool_type){
3525                                 expr = Expression.ResolveBoolean (
3526                                         ec, expr, loc);
3527                                 
3528                                 if (expr == null)
3529                                         return null;
3530                         }
3531                         
3532                         trueExpr = trueExpr.Resolve (ec);
3533                         falseExpr = falseExpr.Resolve (ec);
3534
3535                         if (trueExpr == null || falseExpr == null)
3536                                 return null;
3537
3538                         eclass = ExprClass.Value;
3539                         if (trueExpr.Type == falseExpr.Type)
3540                                 type = trueExpr.Type;
3541                         else {
3542                                 Expression conv;
3543                                 Type true_type = trueExpr.Type;
3544                                 Type false_type = falseExpr.Type;
3545
3546                                 if (trueExpr is NullLiteral){
3547                                         type = false_type;
3548                                         return this;
3549                                 } else if (falseExpr is NullLiteral){
3550                                         type = true_type;
3551                                         return this;
3552                                 }
3553                                 
3554                                 //
3555                                 // First, if an implicit conversion exists from trueExpr
3556                                 // to falseExpr, then the result type is of type falseExpr.Type
3557                                 //
3558                                 conv = Convert.ImplicitConversion (ec, trueExpr, false_type, loc);
3559                                 if (conv != null){
3560                                         //
3561                                         // Check if both can convert implicitl to each other's type
3562                                         //
3563                                         if (Convert.ImplicitConversion (ec, falseExpr, true_type, loc) != null){
3564                                                 Error (172,
3565                                                        "Can not compute type of conditional expression " +
3566                                                        "as `" + TypeManager.CSharpName (trueExpr.Type) +
3567                                                        "' and `" + TypeManager.CSharpName (falseExpr.Type) +
3568                                                        "' convert implicitly to each other");
3569                                                 return null;
3570                                         }
3571                                         type = false_type;
3572                                         trueExpr = conv;
3573                                 } else if ((conv = Convert.ImplicitConversion(ec, falseExpr, true_type,loc))!= null){
3574                                         type = true_type;
3575                                         falseExpr = conv;
3576                                 } else {
3577                                         Error (173, "The type of the conditional expression can " +
3578                                                "not be computed because there is no implicit conversion" +
3579                                                " from `" + TypeManager.CSharpName (trueExpr.Type) + "'" +
3580                                                " and `" + TypeManager.CSharpName (falseExpr.Type) + "'");
3581                                         return null;
3582                                 }
3583                         }
3584
3585                         if (expr is BoolConstant){
3586                                 BoolConstant bc = (BoolConstant) expr;
3587
3588                                 if (bc.Value)
3589                                         return trueExpr;
3590                                 else
3591                                         return falseExpr;
3592                         }
3593
3594                         return this;
3595                 }
3596
3597                 public override void Emit (EmitContext ec)
3598                 {
3599                         ILGenerator ig = ec.ig;
3600                         Label false_target = ig.DefineLabel ();
3601                         Label end_target = ig.DefineLabel ();
3602
3603                         expr.EmitBranchable (ec, false_target, false);
3604                         trueExpr.Emit (ec);
3605                         ig.Emit (OpCodes.Br, end_target);
3606                         ig.MarkLabel (false_target);
3607                         falseExpr.Emit (ec);
3608                         ig.MarkLabel (end_target);
3609                 }
3610
3611         }
3612
3613         /// <summary>
3614         ///   Local variables
3615         /// </summary>
3616         public class LocalVariableReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
3617                 public readonly string Name;
3618                 public readonly Block Block;
3619                 LocalInfo local_info;
3620                 bool is_readonly;
3621                 
3622                 public LocalVariableReference (Block block, string name, Location l)
3623                 {
3624                         Block = block;
3625                         Name = name;
3626                         loc = l;
3627                         eclass = ExprClass.Variable;
3628                 }
3629
3630                 // Setting `is_readonly' to false will allow you to create a writable
3631                 // reference to a read-only variable.  This is used by foreach and using.
3632                 public LocalVariableReference (Block block, string name, Location l,
3633                                                LocalInfo local_info, bool is_readonly)
3634                         : this (block, name, l)
3635                 {
3636                         this.local_info = local_info;
3637                         this.is_readonly = is_readonly;
3638                 }
3639
3640                 public VariableInfo VariableInfo {
3641                         get { return local_info.VariableInfo; }
3642                 }
3643
3644                 public bool IsReadOnly {
3645                         get {
3646                                 return is_readonly;
3647                         }
3648                 }
3649
3650                 protected void DoResolveBase (EmitContext ec)
3651                 {
3652                         if (local_info == null) {
3653                                 local_info = Block.GetLocalInfo (Name);
3654                                 is_readonly = local_info.ReadOnly;
3655                         }
3656
3657                         type = local_info.VariableType;
3658 #if false
3659                         if (ec.InAnonymousMethod)
3660                                 Block.LiftVariable (local_info);
3661 #endif
3662                 }
3663
3664                 protected Expression DoResolve (EmitContext ec, bool is_lvalue)
3665                 {
3666                         Expression e = Block.GetConstantExpression (Name);
3667                         if (e != null) {
3668                                 local_info.Used = true;
3669                                 eclass = ExprClass.Value;
3670                                 return e.Resolve (ec);
3671                         }
3672
3673                         VariableInfo variable_info = local_info.VariableInfo; 
3674                         if ((variable_info != null) && !variable_info.IsAssigned (ec, loc))
3675                                 return null;
3676
3677                         if (!is_lvalue)
3678                                 local_info.Used = true;
3679
3680                         if (local_info.LocalBuilder == null)
3681                                 return ec.RemapLocal (local_info);
3682                         
3683                         return this;
3684                 }
3685                 
3686                 public override Expression DoResolve (EmitContext ec)
3687                 {
3688                         DoResolveBase (ec);
3689
3690                         return DoResolve (ec, false);
3691                 }
3692
3693                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3694                 {
3695                         DoResolveBase (ec);
3696
3697                         VariableInfo variable_info = local_info.VariableInfo; 
3698                         if (variable_info != null)
3699                                 variable_info.SetAssigned (ec);
3700
3701                         Expression e = DoResolve (ec, true);
3702
3703                         if (e == null)
3704                                 return null;
3705
3706                         if (is_readonly){
3707                                 Error (1604, "cannot assign to `" + Name + "' because it is readonly");
3708                                 return null;
3709                         }
3710
3711                         CheckObsoleteAttribute (e.Type);
3712
3713                         if (local_info.LocalBuilder == null)
3714                                 return ec.RemapLocalLValue (local_info, right_side);
3715                         
3716                         return this;
3717                 }
3718
3719                 public bool VerifyFixed (bool is_expression)
3720                 {
3721                         return !is_expression || local_info.IsFixed;
3722                 }
3723
3724                 public override void Emit (EmitContext ec)
3725                 {
3726                         ILGenerator ig = ec.ig;
3727
3728                         ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
3729                 }
3730                 
3731                 public void EmitAssign (EmitContext ec, Expression source)
3732                 {
3733                         ILGenerator ig = ec.ig;
3734
3735                         source.Emit (ec);
3736                         ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
3737                 }
3738                 
3739                 public void AddressOf (EmitContext ec, AddressOp mode)
3740                 {
3741                         ILGenerator ig = ec.ig;
3742                         
3743                         ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
3744                 }
3745
3746                 public override string ToString ()
3747                 {
3748                         return String.Format ("{0} ({1}:{2})", GetType (), Name, loc);
3749                 }
3750         }
3751
3752         /// <summary>
3753         ///   This represents a reference to a parameter in the intermediate
3754         ///   representation.
3755         /// </summary>
3756         public class ParameterReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
3757                 Parameters pars;
3758                 String name;
3759                 int idx;
3760                 Block block;
3761                 VariableInfo vi;
3762                 public Parameter.Modifier mod;
3763                 public bool is_ref, is_out;
3764                 
3765                 public ParameterReference (Parameters pars, Block block, int idx, string name, Location loc)
3766                 {
3767                         this.pars = pars;
3768                         this.block = block;
3769                         this.idx  = idx;
3770                         this.name = name;
3771                         this.loc = loc;
3772                         eclass = ExprClass.Variable;
3773                 }
3774
3775                 public VariableInfo VariableInfo {
3776                         get { return vi; }
3777                 }
3778
3779                 public bool VerifyFixed (bool is_expression)
3780                 {
3781                         return !is_expression || TypeManager.IsValueType (type);
3782                 }
3783
3784                 public bool IsAssigned (EmitContext ec, Location loc)
3785                 {
3786                         if (!ec.DoFlowAnalysis || !is_out ||
3787                             ec.CurrentBranching.IsAssigned (vi))
3788                                 return true;
3789
3790                         Report.Error (165, loc,
3791                                       "Use of unassigned parameter `" + name + "'");
3792                         return false;
3793                 }
3794
3795                 public bool IsFieldAssigned (EmitContext ec, string field_name, Location loc)
3796                 {
3797                         if (!ec.DoFlowAnalysis || !is_out ||
3798                             ec.CurrentBranching.IsFieldAssigned (vi, field_name))
3799                                 return true;
3800
3801                         Report.Error (170, loc,
3802                                       "Use of possibly unassigned field `" + field_name + "'");
3803                         return false;
3804                 }
3805
3806                 public void SetAssigned (EmitContext ec)
3807                 {
3808                         if (is_out && ec.DoFlowAnalysis)
3809                                 ec.CurrentBranching.SetAssigned (vi);
3810                 }
3811
3812                 public void SetFieldAssigned (EmitContext ec, string field_name)
3813                 {
3814                         if (is_out && ec.DoFlowAnalysis)
3815                                 ec.CurrentBranching.SetFieldAssigned (vi, field_name);
3816                 }
3817
3818                 protected void DoResolveBase (EmitContext ec)
3819                 {
3820                         type = pars.GetParameterInfo (ec.DeclSpace, idx, out mod);
3821                         is_ref = (mod & Parameter.Modifier.ISBYREF) != 0;
3822                         is_out = (mod & Parameter.Modifier.OUT) != 0;
3823                         eclass = ExprClass.Variable;
3824
3825                         if (is_out)
3826                                 vi = block.ParameterMap [idx];
3827                 }
3828
3829                 //
3830                 // Notice that for ref/out parameters, the type exposed is not the
3831                 // same type exposed externally.
3832                 //
3833                 // for "ref int a":
3834                 //   externally we expose "int&"
3835                 //   here we expose       "int".
3836                 //
3837                 // We record this in "is_ref".  This means that the type system can treat
3838                 // the type as it is expected, but when we generate the code, we generate
3839                 // the alternate kind of code.
3840                 //
3841                 public override Expression DoResolve (EmitContext ec)
3842                 {
3843                         DoResolveBase (ec);
3844
3845                         if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc))
3846                                 return null;
3847
3848                         if (ec.RemapToProxy)
3849                                 return ec.RemapParameter (idx);
3850                         
3851                         return this;
3852                 }
3853
3854                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3855                 {
3856                         DoResolveBase (ec);
3857
3858                         SetAssigned (ec);
3859
3860                         if (ec.RemapToProxy)
3861                                 return ec.RemapParameterLValue (idx, right_side);
3862                         
3863                         return this;
3864                 }
3865
3866                 static public void EmitLdArg (ILGenerator ig, int x)
3867                 {
3868                         if (x <= 255){
3869                                 switch (x){
3870                                 case 0: ig.Emit (OpCodes.Ldarg_0); break;
3871                                 case 1: ig.Emit (OpCodes.Ldarg_1); break;
3872                                 case 2: ig.Emit (OpCodes.Ldarg_2); break;
3873                                 case 3: ig.Emit (OpCodes.Ldarg_3); break;
3874                                 default: ig.Emit (OpCodes.Ldarg_S, (byte) x); break;
3875                                 }
3876                         } else
3877                                 ig.Emit (OpCodes.Ldarg, x);
3878                 }
3879                 
3880                 //
3881                 // This method is used by parameters that are references, that are
3882                 // being passed as references:  we only want to pass the pointer (that
3883                 // is already stored in the parameter, not the address of the pointer,
3884                 // and not the value of the variable).
3885                 //
3886                 public void EmitLoad (EmitContext ec)
3887                 {
3888                         ILGenerator ig = ec.ig;
3889                         int arg_idx = idx;
3890
3891                         if (!ec.IsStatic)
3892                                 arg_idx++;
3893
3894                         EmitLdArg (ig, arg_idx);
3895                 }
3896                 
3897                 public override void Emit (EmitContext ec)
3898                 {
3899                         ILGenerator ig = ec.ig;
3900                         
3901                         int arg_idx = idx;
3902
3903                         if (!ec.IsStatic)
3904                                 arg_idx++;
3905
3906                         EmitLdArg (ig, arg_idx);
3907
3908                         if (!is_ref)
3909                                 return;
3910
3911                         //
3912                         // If we are a reference, we loaded on the stack a pointer
3913                         // Now lets load the real value
3914                         //
3915                         LoadFromPtr (ig, type);
3916                 }
3917
3918                 public void EmitAssign (EmitContext ec, Expression source)
3919                 {
3920                         ILGenerator ig = ec.ig;
3921                         
3922                         int arg_idx = idx;
3923
3924                         if (!ec.IsStatic)
3925                                 arg_idx++;
3926
3927                         if (is_ref)
3928                                 EmitLdArg (ig, arg_idx);
3929                         
3930                         source.Emit (ec);
3931
3932                         if (is_ref)
3933                                 StoreFromPtr (ig, type);
3934                         else {
3935                                 if (arg_idx <= 255)
3936                                         ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
3937                                 else
3938                                         ig.Emit (OpCodes.Starg, arg_idx);
3939                         }
3940                 }
3941
3942                 public void AddressOf (EmitContext ec, AddressOp mode)
3943                 {
3944                         int arg_idx = idx;
3945
3946                         if (!ec.IsStatic)
3947                                 arg_idx++;
3948
3949                         if (is_ref){
3950                                 if (arg_idx <= 255)
3951                                         ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
3952                                 else
3953                                         ec.ig.Emit (OpCodes.Ldarg, arg_idx);
3954                         } else {
3955                                 if (arg_idx <= 255)
3956                                         ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
3957                                 else
3958                                         ec.ig.Emit (OpCodes.Ldarga, arg_idx);
3959                         }
3960                 }
3961
3962         }
3963         
3964         /// <summary>
3965         ///   Used for arguments to New(), Invocation()
3966         /// </summary>
3967         public class Argument {
3968                 public enum AType : byte {
3969                         Expression,
3970                         Ref,
3971                         Out,
3972                         ArgList
3973                 };
3974
3975                 public readonly AType ArgType;
3976                 public Expression Expr;
3977                 
3978                 public Argument (Expression expr, AType type)
3979                 {
3980                         this.Expr = expr;
3981                         this.ArgType = type;
3982                 }
3983
3984                 public Type Type {
3985                         get {
3986                                 if (ArgType == AType.Ref || ArgType == AType.Out)
3987                                         return TypeManager.GetReferenceType (Expr.Type);
3988                                 else
3989                                         return Expr.Type;
3990                         }
3991                 }
3992
3993                 public Parameter.Modifier GetParameterModifier ()
3994                 {
3995                         switch (ArgType) {
3996                         case AType.Out:
3997                                 return Parameter.Modifier.OUT | Parameter.Modifier.ISBYREF;
3998
3999                         case AType.Ref:
4000                                 return Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
4001
4002                         default:
4003                                 return Parameter.Modifier.NONE;
4004                         }
4005                 }
4006
4007                 public static string FullDesc (Argument a)
4008                 {
4009                         if (a.ArgType == AType.ArgList)
4010                                 return "__arglist";
4011
4012                         return (a.ArgType == AType.Ref ? "ref " :
4013                                 (a.ArgType == AType.Out ? "out " : "")) +
4014                                 TypeManager.CSharpName (a.Expr.Type);
4015                 }
4016
4017                 public bool ResolveMethodGroup (EmitContext ec, Location loc)
4018                 {
4019                         // FIXME: csc doesn't report any error if you try to use `ref' or
4020                         //        `out' in a delegate creation expression.
4021                         Expr = Expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
4022                         if (Expr == null)
4023                                 return false;
4024
4025                         return true;
4026                 }
4027                 
4028                 public bool Resolve (EmitContext ec, Location loc)
4029                 {
4030                         if (ArgType == AType.Ref) {
4031                                 Expr = Expr.Resolve (ec);
4032                                 if (Expr == null)
4033                                         return false;
4034
4035                                 Expr = Expr.ResolveLValue (ec, Expr);
4036                         } else if (ArgType == AType.Out)
4037                                 Expr = Expr.ResolveLValue (ec, new EmptyExpression ());
4038                         else
4039                                 Expr = Expr.Resolve (ec);
4040
4041                         if (Expr == null)
4042                                 return false;
4043
4044                         if (ArgType == AType.Expression)
4045                                 return true;
4046                         else {
4047                                 //
4048                                 // Catch errors where fields of a MarshalByRefObject are passed as ref or out
4049                                 // This is only allowed for `this'
4050                                 //
4051                                 FieldExpr fe = Expr as FieldExpr;
4052                                 if (fe != null && !fe.IsStatic){
4053                                         Expression instance = fe.InstanceExpression;
4054
4055                                         if (instance.GetType () != typeof (This)){
4056                                                 if (fe.InstanceExpression.Type.IsSubclassOf (TypeManager.mbr_type)){
4057                                                         Report.Error (197, loc,
4058                                                                       "Can not pass a type that derives from MarshalByRefObject with out or ref");
4059                                                         return false;
4060                                                 }
4061                                         }
4062                                 }
4063                         }
4064
4065                         if (Expr.eclass != ExprClass.Variable){
4066                                 //
4067                                 // We just probe to match the CSC output
4068                                 //
4069                                 if (Expr.eclass == ExprClass.PropertyAccess ||
4070                                     Expr.eclass == ExprClass.IndexerAccess){
4071                                         Report.Error (
4072                                                 206, loc,
4073                                                 "A property or indexer can not be passed as an out or ref " +
4074                                                 "parameter");
4075                                 } else {
4076                                         Report.Error (
4077                                                 1510, loc,
4078                                                 "An lvalue is required as an argument to out or ref");
4079                                 }
4080                                 return false;
4081                         }
4082                                 
4083                         return true;
4084                 }
4085
4086                 public void Emit (EmitContext ec)
4087                 {
4088                         //
4089                         // Ref and Out parameters need to have their addresses taken.
4090                         //
4091                         // ParameterReferences might already be references, so we want
4092                         // to pass just the value
4093                         //
4094                         if (ArgType == AType.Ref || ArgType == AType.Out){
4095                                 AddressOp mode = AddressOp.Store;
4096
4097                                 if (ArgType == AType.Ref)
4098                                         mode |= AddressOp.Load;
4099                                 
4100                                 if (Expr is ParameterReference){
4101                                         ParameterReference pr = (ParameterReference) Expr;
4102
4103                                         if (pr.is_ref)
4104                                                 pr.EmitLoad (ec);
4105                                         else {
4106                                                 
4107                                                 pr.AddressOf (ec, mode);
4108                                         }
4109                                 } else {
4110                                         ((IMemoryLocation)Expr).AddressOf (ec, mode);
4111                                 }
4112                         } else
4113                                 Expr.Emit (ec);
4114                 }
4115         }
4116
4117         /// <summary>
4118         ///   Invocation of methods or delegates.
4119         /// </summary>
4120         public class Invocation : ExpressionStatement {
4121                 public readonly ArrayList Arguments;
4122
4123                 Expression expr;
4124                 MethodBase method = null;
4125                 bool is_base;
4126                 
4127                 static Hashtable method_parameter_cache;
4128
4129                 static Invocation ()
4130                 {
4131                         method_parameter_cache = new PtrHashtable ();
4132                 }
4133                         
4134                 //
4135                 // arguments is an ArrayList, but we do not want to typecast,
4136                 // as it might be null.
4137                 //
4138                 // FIXME: only allow expr to be a method invocation or a
4139                 // delegate invocation (7.5.5)
4140                 //
4141                 public Invocation (Expression expr, ArrayList arguments, Location l)
4142                 {
4143                         this.expr = expr;
4144                         Arguments = arguments;
4145                         loc = l;
4146                 }
4147
4148                 public Expression Expr {
4149                         get {
4150                                 return expr;
4151                         }
4152                 }
4153
4154                 /// <summary>
4155                 ///   Returns the Parameters (a ParameterData interface) for the
4156                 ///   Method `mb'
4157                 /// </summary>
4158                 public static ParameterData GetParameterData (MethodBase mb)
4159                 {
4160                         object pd = method_parameter_cache [mb];
4161                         object ip;
4162                         
4163                         if (pd != null)
4164                                 return (ParameterData) pd;
4165
4166                         
4167                         ip = TypeManager.LookupParametersByBuilder (mb);
4168                         if (ip != null){
4169                                 method_parameter_cache [mb] = ip;
4170
4171                                 return (ParameterData) ip;
4172                         } else {
4173                                 ReflectionParameters rp = new ReflectionParameters (mb);
4174                                 method_parameter_cache [mb] = rp;
4175
4176                                 return (ParameterData) rp;
4177                         }
4178                 }
4179
4180                 /// <summary>
4181                 ///   Determines "better conversion" as specified in 7.4.2.3
4182                 ///
4183                 ///    Returns : 1 if a->p is better
4184                 ///              0 if a->q or neither is better 
4185                 /// </summary>
4186                 static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc)
4187                 {
4188                         Type argument_type = a.Type;
4189                         Expression argument_expr = a.Expr;
4190
4191                         if (argument_type == null)
4192                                 throw new Exception ("Expression of type " + a.Expr +
4193                                                      " does not resolve its type");
4194
4195                         //
4196                         // This is a special case since csc behaves this way.
4197                         //
4198                         if (argument_expr is NullLiteral &&
4199                             p == TypeManager.string_type &&
4200                             q == TypeManager.object_type)
4201                                 return 1;
4202                         else if (argument_expr is NullLiteral &&
4203                                  p == TypeManager.object_type &&
4204                                  q == TypeManager.string_type)
4205                                 return 0;
4206                         
4207                         //
4208                         // csc behaves this way so we emulate it. Basically, if the argument
4209                         // is null and one of the types to compare is 'object' and the other
4210                         // is a reference type, we prefer the other.
4211                         //
4212                         // I can't find this anywhere in the spec but we can interpret this
4213                         // to mean that null can be of any type you wish in such a context
4214                         //
4215                         if (p != null && q != null) {
4216                                 if (argument_expr is NullLiteral &&
4217                                     !p.IsValueType &&
4218                                     q == TypeManager.object_type)
4219                                         return 1;
4220                                 else if (argument_expr is NullLiteral &&
4221                                          !q.IsValueType &&
4222                                          p == TypeManager.object_type)
4223                                         return 0;
4224                         }
4225                                 
4226                         if (p == q)
4227                                 return 0;
4228                         
4229                         if (argument_type == p)
4230                                 return 1;
4231
4232                         if (argument_type == q)
4233                                 return 0;
4234
4235                         if (q == null) {
4236                                 Expression tmp = Convert.ImplicitConversion (ec, argument_expr, p, loc);
4237                                 
4238                                 if (tmp != null)
4239                                         return 1;
4240                                 else
4241                                         return 0;
4242                         }
4243
4244                         Expression p_tmp = new EmptyExpression (p);
4245                         Expression q_tmp = new EmptyExpression (q);
4246                         
4247                         if (Convert.ImplicitConversionExists (ec, p_tmp, q) == true &&
4248                             Convert.ImplicitConversionExists (ec, q_tmp, p) == false)
4249                                 return 1;
4250
4251                         if (p == TypeManager.sbyte_type)
4252                                 if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
4253                                     q == TypeManager.uint32_type || q == TypeManager.uint64_type)
4254                                         return 1;
4255
4256                         if (p == TypeManager.short_type)
4257                                 if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
4258                                     q == TypeManager.uint64_type)
4259                                         return 1;
4260
4261                         if (p == TypeManager.int32_type)
4262                                 if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
4263                                         return 1;
4264
4265                         if (p == TypeManager.int64_type)
4266                                 if (q == TypeManager.uint64_type)
4267                                         return 1;
4268
4269                         return 0;
4270                 }
4271                 
4272                 /// <summary>
4273                 ///   Determines "Better function" between candidate
4274                 ///   and the current best match
4275                 /// </summary>
4276                 /// <remarks>
4277                 ///    Returns an integer indicating :
4278                 ///     0 if candidate ain't better
4279                 ///     1 if candidate is better than the current best match
4280                 /// </remarks>
4281                 static int BetterFunction (EmitContext ec, ArrayList args,
4282                                            MethodBase candidate, bool candidate_params,
4283                                            MethodBase best, bool best_params,
4284                                            Location loc)
4285                 {
4286                         ParameterData candidate_pd = GetParameterData (candidate);
4287                         ParameterData best_pd;
4288                         int argument_count;
4289                 
4290                         if (args == null)
4291                                 argument_count = 0;
4292                         else
4293                                 argument_count = args.Count;
4294
4295                         int cand_count = candidate_pd.Count;
4296                         
4297                         //
4298                         // If there is no best method, than this one
4299                         // is better, however, if we already found a
4300                         // best method, we cant tell. This happens
4301                         // if we have:
4302                         // 
4303                         //      interface IFoo {
4304                         //              void DoIt ();
4305                         //      }
4306                         //      
4307                         //      interface IBar {
4308                         //              void DoIt ();
4309                         //      }
4310                         //      
4311                         //      interface IFooBar : IFoo, IBar {}
4312                         //
4313                         // We cant tell if IFoo.DoIt is better than IBar.DoIt
4314                         //
4315                         // However, we have to consider that
4316                         // Trim (); is better than Trim (params char[] chars);
4317                         //
4318                         if (cand_count == 0 && argument_count == 0)
4319                                 return best == null || best_params ? 1 : 0;
4320
4321                         if ((candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS) &&
4322                             (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.ARGLIST))
4323                                 if (cand_count != argument_count)
4324                                         return 0;
4325
4326                         if (best == null) {
4327                                 int x = 0;
4328
4329                                 if (argument_count == 0 && cand_count == 1 &&
4330                                     candidate_pd.ParameterModifier (cand_count - 1) == Parameter.Modifier.PARAMS)
4331                                         return 1;
4332                                 
4333                                 for (int j = 0; j < argument_count; ++j) {
4334
4335                                         Argument a = (Argument) args [j];
4336                                         Type t = candidate_pd.ParameterType (j);
4337
4338                                         if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
4339                                                 if (candidate_params)
4340                                                         t = TypeManager.GetElementType (t);
4341
4342                                         x = BetterConversion (ec, a, t, null, loc);
4343                                         
4344                                         if (x <= 0)
4345                                                 break;
4346                                 }
4347
4348                                 if (x > 0)
4349                                         return 1;
4350                                 else
4351                                         return 0;
4352                         }
4353
4354                         best_pd = GetParameterData (best);
4355
4356                         int rating1 = 0, rating2 = 0;
4357                         
4358                         for (int j = 0; j < argument_count; ++j) {
4359                                 int x, y;
4360                                 
4361                                 Argument a = (Argument) args [j];
4362
4363                                 Type ct = candidate_pd.ParameterType (j);
4364                                 Type bt = best_pd.ParameterType (j);
4365
4366                                 if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
4367                                         if (candidate_params)
4368                                                 ct = TypeManager.GetElementType (ct);
4369
4370                                 if (best_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
4371                                         if (best_params)
4372                                                 bt = TypeManager.GetElementType (bt);
4373
4374                                 x = BetterConversion (ec, a, ct, bt, loc);
4375                                 y = BetterConversion (ec, a, bt, ct, loc);
4376
4377                                 if (x < y)
4378                                         return 0;
4379                                 
4380                                 rating1 += x;
4381                                 rating2 += y;
4382                         }
4383
4384                         //
4385                         // If a method (in the normal form) with the
4386                         // same signature as the expanded form of the
4387                         // current best params method already exists,
4388                         // the expanded form is not applicable so we
4389                         // force it to select the candidate
4390                         //
4391                         if (!candidate_params && best_params && cand_count == argument_count)
4392                                 return 1;
4393
4394                         if (rating1 > rating2)
4395                                 return 1;
4396                         else
4397                                 return 0;
4398                 }
4399
4400                 public static string FullMethodDesc (MethodBase mb)
4401                 {
4402                         string ret_type = "";
4403
4404                         if (mb == null)
4405                                 return "";
4406
4407                         if (mb is MethodInfo)
4408                                 ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType);
4409                         
4410                         StringBuilder sb = new StringBuilder (ret_type);
4411                         sb.Append (" ");
4412                         sb.Append (mb.ReflectedType.ToString ());
4413                         sb.Append (".");
4414                         sb.Append (mb.Name);
4415                         
4416                         ParameterData pd = GetParameterData (mb);
4417
4418                         int count = pd.Count;
4419                         sb.Append (" (");
4420                         
4421                         for (int i = count; i > 0; ) {
4422                                 i--;
4423
4424                                 sb.Append (pd.ParameterDesc (count - i - 1));
4425                                 if (i != 0)
4426                                         sb.Append (", ");
4427                         }
4428                         
4429                         sb.Append (")");
4430                         return sb.ToString ();
4431                 }
4432
4433                 public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2, Location loc)
4434                 {
4435                         MemberInfo [] miset;
4436                         MethodGroupExpr union;
4437
4438                         if (mg1 == null) {
4439                                 if (mg2 == null)
4440                                         return null;
4441                                 return (MethodGroupExpr) mg2;
4442                         } else {
4443                                 if (mg2 == null)
4444                                         return (MethodGroupExpr) mg1;
4445                         }
4446                         
4447                         MethodGroupExpr left_set = null, right_set = null;
4448                         int length1 = 0, length2 = 0;
4449                         
4450                         left_set = (MethodGroupExpr) mg1;
4451                         length1 = left_set.Methods.Length;
4452                         
4453                         right_set = (MethodGroupExpr) mg2;
4454                         length2 = right_set.Methods.Length;
4455                         
4456                         ArrayList common = new ArrayList ();
4457
4458                         foreach (MethodBase r in right_set.Methods){
4459                                 if (TypeManager.ArrayContainsMethod (left_set.Methods, r))
4460                                         common.Add (r);
4461                         }
4462
4463                         miset = new MemberInfo [length1 + length2 - common.Count];
4464                         left_set.Methods.CopyTo (miset, 0);
4465                         
4466                         int k = length1;
4467
4468                         foreach (MethodBase r in right_set.Methods) {
4469                                 if (!common.Contains (r))
4470                                         miset [k++] = r;
4471                         }
4472
4473                         union = new MethodGroupExpr (miset, loc);
4474                         
4475                         return union;
4476                 }
4477
4478                 /// <summary>
4479                 ///   Determines if the candidate method, if a params method, is applicable
4480                 ///   in its expanded form to the given set of arguments
4481                 /// </summary>
4482                 static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments,
4483                                                       MethodBase candidate, bool do_varargs)
4484                 {
4485                         int arg_count;
4486                         
4487                         if (arguments == null)
4488                                 arg_count = 0;
4489                         else
4490                                 arg_count = arguments.Count;
4491                         
4492                         ParameterData pd = GetParameterData (candidate);
4493
4494                         int pd_count = pd.Count;
4495                         if (pd_count == 0)
4496                                 return false;
4497
4498                         int count = pd_count - 1;
4499                         if (do_varargs) {
4500                                 if (pd.ParameterModifier (count) != Parameter.Modifier.ARGLIST)
4501                                         return false;
4502                                 if (pd_count != arg_count)
4503                                         return false;
4504                         } else {
4505                                 if (pd.ParameterModifier (count) != Parameter.Modifier.PARAMS)
4506                                         return false;
4507                         }
4508                         
4509                         if (count > arg_count)
4510                                 return false;
4511                         
4512                         if (pd_count == 1 && arg_count == 0)
4513                                 return true;
4514
4515                         //
4516                         // If we have come this far, the case which
4517                         // remains is when the number of parameters is
4518                         // less than or equal to the argument count.
4519                         //
4520                         for (int i = 0; i < count; ++i) {
4521
4522                                 Argument a = (Argument) arguments [i];
4523
4524                                 Parameter.Modifier a_mod = a.GetParameterModifier () &
4525                                         ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
4526                                 Parameter.Modifier p_mod = pd.ParameterModifier (i) &
4527                                         ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
4528
4529                                 if (a_mod == p_mod) {
4530
4531                                         if (a_mod == Parameter.Modifier.NONE)
4532                                                 if (!Convert.ImplicitConversionExists (ec,
4533                                                                                        a.Expr,
4534                                                                                        pd.ParameterType (i)))
4535                                                         return false;
4536                                                                                 
4537                                         if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
4538                                                 Type pt = pd.ParameterType (i);
4539
4540                                                 if (!pt.IsByRef)
4541                                                         pt = TypeManager.GetReferenceType (pt);
4542                                                 
4543                                                 if (pt != a.Type)
4544                                                         return false;
4545                                         }
4546                                 } else
4547                                         return false;
4548                                 
4549                         }
4550
4551                         if (do_varargs) {
4552                                 Argument a = (Argument) arguments [count];
4553                                 if (!(a.Expr is Arglist))
4554                                         return false;
4555
4556                                 return true;
4557                         }
4558
4559                         Type element_type = TypeManager.GetElementType (pd.ParameterType (pd_count - 1));
4560
4561                         for (int i = pd_count - 1; i < arg_count; i++) {
4562                                 Argument a = (Argument) arguments [i];
4563
4564                                 if (!Convert.ImplicitConversionExists (ec, a.Expr, element_type))
4565                                         return false;
4566                         }
4567                         
4568                         return true;
4569                 }
4570
4571                 /// <summary>
4572                 ///   Determines if the candidate method is applicable (section 14.4.2.1)
4573                 ///   to the given set of arguments
4574                 /// </summary>
4575                 static bool IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
4576                 {
4577                         int arg_count;
4578
4579                         if (arguments == null)
4580                                 arg_count = 0;
4581                         else
4582                                 arg_count = arguments.Count;
4583
4584
4585                         ParameterData pd = GetParameterData (candidate);
4586
4587                         if (arg_count != pd.Count)
4588                                 return false;
4589
4590                         for (int i = arg_count; i > 0; ) {
4591                                 i--;
4592
4593                                 Argument a = (Argument) arguments [i];
4594
4595                                 Parameter.Modifier a_mod = a.GetParameterModifier () &
4596                                         ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
4597                                 Parameter.Modifier p_mod = pd.ParameterModifier (i) &
4598                                         ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
4599
4600
4601                                 if (a_mod == p_mod ||
4602                                     (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) {
4603                                         if (a_mod == Parameter.Modifier.NONE) {
4604                                                 if (!Convert.ImplicitConversionExists (ec,
4605                                                                                        a.Expr,
4606                                                                                        pd.ParameterType (i)))
4607                                                         return false;
4608                                         }
4609                                         
4610                                         if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
4611                                                 Type pt = pd.ParameterType (i);
4612
4613                                                 if (!pt.IsByRef)
4614                                                         pt = TypeManager.GetReferenceType (pt);
4615                                                 
4616                                                 if (pt != a.Type)
4617                                                         return false;
4618                                         }
4619                                 } else
4620                                         return false;
4621                         }
4622
4623                         return true;
4624                 }
4625                 
4626                 /// <summary>
4627                 ///   Find the Applicable Function Members (7.4.2.1)
4628                 ///
4629                 ///   me: Method Group expression with the members to select.
4630                 ///       it might contain constructors or methods (or anything
4631                 ///       that maps to a method).
4632                 ///
4633                 ///   Arguments: ArrayList containing resolved Argument objects.
4634                 ///
4635                 ///   loc: The location if we want an error to be reported, or a Null
4636                 ///        location for "probing" purposes.
4637                 ///
4638                 ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
4639                 ///            that is the best match of me on Arguments.
4640                 ///
4641                 /// </summary>
4642                 public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
4643                                                           ArrayList Arguments, Location loc)
4644                 {
4645                         MethodBase method = null;
4646                         Type applicable_type = null;
4647                         int argument_count;
4648                         ArrayList candidates = new ArrayList ();
4649
4650                         //
4651                         // Used to keep a map between the candidate
4652                         // and whether it is being considered in its
4653                         // normal or expanded form
4654                         //
4655                         // false is normal form, true is expanded form
4656                         //
4657                         Hashtable candidate_to_form = null;
4658
4659
4660                         //
4661                         // First we construct the set of applicable methods
4662                         //
4663                         // We start at the top of the type hierarchy and
4664                         // go down to find applicable methods
4665                         //
4666                         applicable_type = me.DeclaringType;
4667                         
4668                         if (me.Name == "Invoke" && TypeManager.IsDelegateType (applicable_type)) {
4669                                 Error_InvokeOnDelegate (loc);
4670                                 return null;
4671                         }
4672
4673                         bool found_applicable = false;
4674
4675                         foreach (MethodBase candidate in me.Methods){
4676                                 Type decl_type = candidate.DeclaringType;
4677
4678                                 //
4679                                 // If we have already found an applicable method
4680                                 // we eliminate all base types (Section 14.5.5.1)
4681                                 //
4682                                 if (decl_type != applicable_type &&
4683                                     (applicable_type.IsSubclassOf (decl_type) ||
4684                                      TypeManager.ImplementsInterface (applicable_type, decl_type)) &&
4685                                     found_applicable)
4686                                                 continue;
4687
4688
4689                                 // Check if candidate is applicable (section 14.4.2.1)
4690                                 if (IsApplicable (ec, Arguments, candidate)) {
4691                                         // Candidate is applicable in normal form
4692                                         candidates.Add (candidate);
4693                                         applicable_type = candidate.DeclaringType;
4694                                         found_applicable = true;
4695                                 } else if (IsParamsMethodApplicable (ec, Arguments, candidate, false)) {
4696                                         if (candidate_to_form == null)
4697                                                 candidate_to_form = new PtrHashtable ();
4698                                         
4699                                         // Candidate is applicable in expanded form
4700                                         candidates.Add (candidate);
4701                                         applicable_type = candidate.DeclaringType;
4702                                         found_applicable = true; 
4703                                         candidate_to_form [candidate] = candidate;
4704                                 } else if (IsParamsMethodApplicable (ec, Arguments, candidate, true)) {
4705                                         if (candidate_to_form == null)
4706                                                 candidate_to_form = new PtrHashtable ();
4707                                         
4708                                         // Candidate is applicable in expanded form
4709                                         candidates.Add (candidate);
4710                                         applicable_type = candidate.DeclaringType;
4711                                         found_applicable = true; 
4712                                         candidate_to_form [candidate] = candidate;
4713                                 }
4714                         }
4715                         
4716
4717                         //
4718                         // Now we actually find the best method
4719                         //
4720                         int candidate_top = candidates.Count;
4721                         for (int ix = 0; ix < candidate_top; ix++){
4722                                 MethodBase candidate = (MethodBase) candidates [ix];
4723
4724                                 bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
4725                                 bool method_params = false;
4726
4727                                 if (method != null)
4728                                         method_params = candidate_to_form != null && candidate_to_form.Contains (method);
4729                                 
4730                                 int x = BetterFunction (ec, Arguments,
4731                                                         candidate, cand_params,
4732                                                         method, method_params,
4733                                                         loc);
4734                                 
4735                                 if (x == 0)
4736                                         continue;
4737                                 
4738                                 method = candidate;
4739                         }
4740
4741                         if (Arguments == null)
4742                                 argument_count = 0;
4743                         else
4744                                 argument_count = Arguments.Count;
4745                         
4746
4747                         if (method == null) {
4748                                 //
4749                                 // Okay so we have failed to find anything so we
4750                                 // return by providing info about the closest match
4751                                 //
4752                                 for (int i = 0; i < me.Methods.Length; ++i) {
4753
4754                                         MethodBase c = (MethodBase) me.Methods [i];
4755                                         ParameterData pd = GetParameterData (c);
4756
4757                                         if (pd.Count != argument_count)
4758                                                 continue;
4759
4760                                         VerifyArgumentsCompat (ec, Arguments, argument_count, c, false,
4761                                                                null, loc);
4762                                         break;
4763                                 }
4764
4765                                 if (!Location.IsNull (loc)) {
4766                                         string report_name = me.Name;
4767                                         if (report_name == ".ctor")
4768                                                 report_name = me.DeclaringType.ToString ();
4769                                         
4770                                         Error_WrongNumArguments (loc, report_name, argument_count);
4771                                 }
4772                                 
4773                                 return null;
4774                         }
4775
4776                         //
4777                         // Now check that there are no ambiguities i.e the selected method
4778                         // should be better than all the others
4779                         //
4780                         bool best_params = candidate_to_form != null && candidate_to_form.Contains (method);
4781
4782                         for (int ix = 0; ix < candidate_top; ix++){
4783                                 MethodBase candidate = (MethodBase) candidates [ix];
4784
4785                                 if (candidate == method)
4786                                         continue;
4787                                                
4788                                 //
4789                                 // If a normal method is applicable in
4790                                 // the sense that it has the same
4791                                 // number of arguments, then the
4792                                 // expanded params method is never
4793                                 // applicable so we debar the params
4794                                 // method.
4795                                 //
4796                                 // if ((IsParamsMethodApplicable (ec, Arguments, candidate) &&
4797 //                                      IsApplicable (ec, Arguments, method)))
4798 //                                         continue;
4799                                 
4800                                 bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
4801                                 int x = BetterFunction (ec, Arguments,
4802                                                         method, best_params,
4803                                                         candidate, cand_params,
4804                                                         loc);
4805
4806                                 if (x != 1) {
4807                                         Report.Error (
4808                                                 121, loc,
4809                                                 "Ambiguous call when selecting function due to implicit casts");
4810                                         return null;
4811                                 }
4812                         }
4813
4814                         //
4815                         // And now check if the arguments are all
4816                         // compatible, perform conversions if
4817                         // necessary etc. and return if everything is
4818                         // all right
4819                         //
4820                         if (!VerifyArgumentsCompat (ec, Arguments, argument_count, method,
4821                                                     best_params, null, loc))
4822                                 return null;
4823
4824                         return method;
4825                 }
4826
4827                 static void Error_WrongNumArguments (Location loc, String name, int arg_count)
4828                 {
4829                         Report.Error (1501, loc,
4830                                       "No overload for method `" + name + "' takes `" +
4831                                       arg_count + "' arguments");
4832                 }
4833
4834                 static void Error_InvokeOnDelegate (Location loc)
4835                 {
4836                         Report.Error (1533, loc,
4837                                       "Invoke cannot be called directly on a delegate");
4838                 }
4839                         
4840                 static void Error_InvalidArguments (Location loc, int idx, MethodBase method,
4841                                                     Type delegate_type, string arg_sig, string par_desc)
4842                 {
4843                         if (delegate_type == null) 
4844                                 Report.Error (1502, loc,
4845                                               "The best overloaded match for method '" +
4846                                               FullMethodDesc (method) +
4847                                               "' has some invalid arguments");
4848                         else
4849                                 Report.Error (1594, loc,
4850                                               "Delegate '" + delegate_type.ToString () +
4851                                               "' has some invalid arguments.");
4852                         Report.Error (1503, loc,
4853                                       String.Format ("Argument {0}: Cannot convert from '{1}' to '{2}'",
4854                                                      idx, arg_sig, par_desc));
4855                 }
4856                 
4857                 public static bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments,
4858                                                           int argument_count,
4859                                                           MethodBase method, 
4860                                                           bool chose_params_expanded,
4861                                                           Type delegate_type,
4862                                                           Location loc)
4863                 {
4864                         ParameterData pd = GetParameterData (method);
4865                         int pd_count = pd.Count;
4866
4867                         for (int j = 0; j < argument_count; j++) {
4868                                 Argument a = (Argument) Arguments [j];
4869                                 Expression a_expr = a.Expr;
4870                                 Type parameter_type = pd.ParameterType (j);
4871                                 Parameter.Modifier pm = pd.ParameterModifier (j);
4872                                 
4873                                 if (pm == Parameter.Modifier.PARAMS){
4874                                         if ((pm & ~Parameter.Modifier.PARAMS) != a.GetParameterModifier ()) {
4875                                                 if (!Location.IsNull (loc))
4876                                                         Error_InvalidArguments (
4877                                                                 loc, j, method, delegate_type,
4878                                                                 Argument.FullDesc (a), pd.ParameterDesc (j));
4879                                                 return false;
4880                                         }
4881
4882                                         if (chose_params_expanded)
4883                                                 parameter_type = TypeManager.GetElementType (parameter_type);
4884                                 } else if (pm == Parameter.Modifier.ARGLIST){
4885                                         continue;
4886                                 } else {
4887                                         //
4888                                         // Check modifiers
4889                                         //
4890                                         if (pd.ParameterModifier (j) != a.GetParameterModifier ()){
4891                                                 if (!Location.IsNull (loc))
4892                                                         Error_InvalidArguments (
4893                                                                 loc, j, method, delegate_type,
4894                                                                 Argument.FullDesc (a), pd.ParameterDesc (j));
4895                                                 return false;
4896                                         }
4897                                 }
4898
4899                                 //
4900                                 // Check Type
4901                                 //
4902                                 if (a.Type != parameter_type){
4903                                         Expression conv;
4904                                         
4905                                         conv = Convert.ImplicitConversion (ec, a_expr, parameter_type, loc);
4906
4907                                         if (conv == null) {
4908                                                 if (!Location.IsNull (loc)) 
4909                                                         Error_InvalidArguments (
4910                                                                 loc, j, method, delegate_type,
4911                                                                 Argument.FullDesc (a), pd.ParameterDesc (j));
4912                                                 return false;
4913                                         }
4914                                         
4915                                         //
4916                                         // Update the argument with the implicit conversion
4917                                         //
4918                                         if (a_expr != conv)
4919                                                 a.Expr = conv;
4920                                 }
4921
4922                                 Parameter.Modifier a_mod = a.GetParameterModifier () &
4923                                         ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
4924                                 Parameter.Modifier p_mod = pd.ParameterModifier (j) &
4925                                         ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
4926                                 
4927                                 if (a_mod != p_mod &&
4928                                     pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
4929                                         if (!Location.IsNull (loc)) {
4930                                                 Report.Error (1502, loc,
4931                                                        "The best overloaded match for method '" + FullMethodDesc (method)+
4932                                                        "' has some invalid arguments");
4933                                                 Report.Error (1503, loc,
4934                                                        "Argument " + (j+1) +
4935                                                        ": Cannot convert from '" + Argument.FullDesc (a) 
4936                                                        + "' to '" + pd.ParameterDesc (j) + "'");
4937                                         }
4938                                         
4939                                         return false;
4940                                 }
4941                         }
4942
4943                         return true;
4944                 }
4945
4946                 public override Expression DoResolve (EmitContext ec)
4947                 {
4948                         //
4949                         // First, resolve the expression that is used to
4950                         // trigger the invocation
4951                         //
4952                         if (expr is BaseAccess)
4953                                 is_base = true;
4954
4955                         expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
4956                         if (expr == null)
4957                                 return null;
4958
4959                         if (!(expr is MethodGroupExpr)) {
4960                                 Type expr_type = expr.Type;
4961
4962                                 if (expr_type != null){
4963                                         bool IsDelegate = TypeManager.IsDelegateType (expr_type);
4964                                         if (IsDelegate)
4965                                                 return (new DelegateInvocation (
4966                                                         this.expr, Arguments, loc)).Resolve (ec);
4967                                 }
4968                         }
4969
4970                         if (!(expr is MethodGroupExpr)){
4971                                 expr.Error_UnexpectedKind (ResolveFlags.MethodGroup);
4972                                 return null;
4973                         }
4974
4975                         //
4976                         // Next, evaluate all the expressions in the argument list
4977                         //
4978                         if (Arguments != null){
4979                                 foreach (Argument a in Arguments){
4980                                         if (!a.Resolve (ec, loc))
4981                                                 return null;
4982                                 }
4983                         }
4984
4985                         MethodGroupExpr mg = (MethodGroupExpr) expr;
4986                         method = OverloadResolve (ec, mg, Arguments, loc);
4987
4988                         if (method == null){
4989                                 Error (-6,
4990                                        "Could not find any applicable function for this argument list");
4991                                 return null;
4992                         }
4993                         
4994                         MethodInfo mi = method as MethodInfo;
4995                         if (mi != null) {
4996                                 type = TypeManager.TypeToCoreType (mi.ReturnType);
4997                                 if (!mi.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null)) {
4998                                         SimpleName.Error_ObjectRefRequired (ec, loc, mi.Name);
4999                                         return null;
5000                                 }
5001
5002                                 Expression iexpr = mg.InstanceExpression;
5003                                 if (mi.IsStatic && (iexpr != null) && !(iexpr is This)) {
5004                                         if (mg.IdenticalTypeName)
5005                                                 mg.InstanceExpression = null;
5006                                         else {
5007                                                 MemberAccess.error176 (loc, mi.Name);
5008                                                 return null;
5009                                         }
5010                                 }
5011                         }
5012
5013                         if (type.IsPointer){
5014                                 if (!ec.InUnsafe){
5015                                         UnsafeError (loc);
5016                                         return null;
5017                                 }
5018                         }
5019                         
5020                         //
5021                         // Only base will allow this invocation to happen.
5022                         //
5023                         if (is_base && method.IsAbstract){
5024                                 Report.Error (205, loc, "Cannot call an abstract base member: " +
5025                                               FullMethodDesc (method));
5026                                 return null;
5027                         }
5028
5029                         if ((method.Attributes & MethodAttributes.SpecialName) != 0){
5030                                 if (TypeManager.IsSpecialMethod (method))
5031                                         Report.Error (571, loc, method.Name + ": can not call operator or accessor");
5032                         }
5033
5034                         eclass = ExprClass.Value;
5035                         return this;
5036                 }
5037
5038                 // <summary>
5039                 //   Emits the list of arguments as an array
5040                 // </summary>
5041                 static void EmitParams (EmitContext ec, int idx, ArrayList arguments)
5042                 {
5043                         ILGenerator ig = ec.ig;
5044                         int count = arguments.Count - idx;
5045                         Argument a = (Argument) arguments [idx];
5046                         Type t = a.Expr.Type;
5047                         
5048                         IntConstant.EmitInt (ig, count);
5049                         ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
5050
5051                         int top = arguments.Count;
5052                         for (int j = idx; j < top; j++){
5053                                 a = (Argument) arguments [j];
5054                                 
5055                                 ig.Emit (OpCodes.Dup);
5056                                 IntConstant.EmitInt (ig, j - idx);
5057
5058                                 bool is_stobj;
5059                                 OpCode op = ArrayAccess.GetStoreOpcode (t, out is_stobj);
5060                                 if (is_stobj)
5061                                         ig.Emit (OpCodes.Ldelema, t);
5062
5063                                 a.Emit (ec);
5064
5065                                 if (is_stobj)
5066                                         ig.Emit (OpCodes.Stobj, t);
5067                                 else
5068                                         ig.Emit (op);
5069                         }
5070                 }
5071                 
5072                 /// <summary>
5073                 ///   Emits a list of resolved Arguments that are in the arguments
5074                 ///   ArrayList.
5075                 /// 
5076                 ///   The MethodBase argument might be null if the
5077                 ///   emission of the arguments is known not to contain
5078                 ///   a `params' field (for example in constructors or other routines
5079                 ///   that keep their arguments in this structure)
5080                 /// </summary>
5081                 public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments)
5082                 {
5083                         ParameterData pd;
5084                         if (mb != null)
5085                                 pd = GetParameterData (mb);
5086                         else
5087                                 pd = null;
5088
5089                         //
5090                         // If we are calling a params method with no arguments, special case it
5091                         //
5092                         if (arguments == null){
5093                                 if (pd != null && pd.Count > 0 &&
5094                                     pd.ParameterModifier (0) == Parameter.Modifier.PARAMS){
5095                                         ILGenerator ig = ec.ig;
5096
5097                                         IntConstant.EmitInt (ig, 0);
5098                                         ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (0)));
5099                                 }
5100
5101                                 return;
5102                         }
5103
5104                         int top = arguments.Count;
5105
5106                         for (int i = 0; i < top; i++){
5107                                 Argument a = (Argument) arguments [i];
5108
5109                                 if (pd != null){
5110                                         if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){
5111                                                 //
5112                                                 // Special case if we are passing the same data as the
5113                                                 // params argument, do not put it in an array.
5114                                                 //
5115                                                 if (pd.ParameterType (i) == a.Type)
5116                                                         a.Emit (ec);
5117                                                 else
5118                                                         EmitParams (ec, i, arguments);
5119                                                 return;
5120                                         }
5121                                 }
5122                                             
5123                                 a.Emit (ec);
5124                         }
5125
5126                         if (pd != null && pd.Count > top &&
5127                             pd.ParameterModifier (top) == Parameter.Modifier.PARAMS){
5128                                 ILGenerator ig = ec.ig;
5129
5130                                 IntConstant.EmitInt (ig, 0);
5131                                 ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (top)));
5132                         }
5133                 }
5134
5135                 static Type[] GetVarargsTypes (EmitContext ec, MethodBase mb,
5136                                                ArrayList arguments)
5137                 {
5138                         ParameterData pd = GetParameterData (mb);
5139
5140                         if (arguments == null)
5141                                 return new Type [0];
5142
5143                         Argument a = (Argument) arguments [pd.Count - 1];
5144                         Arglist list = (Arglist) a.Expr;
5145
5146                         return list.ArgumentTypes;
5147                 }
5148
5149                 /// <summary>
5150                 /// This checks the ConditionalAttribute on the method 
5151                 /// </summary>
5152                 static bool IsMethodExcluded (MethodBase method, EmitContext ec)
5153                 {
5154                         if (method.IsConstructor)
5155                                 return false;
5156
5157                         IMethodData md = TypeManager.GetMethod (method);
5158                         if (md != null)
5159                                 return md.IsExcluded (ec);
5160
5161                         // For some methods (generated by delegate class) GetMethod returns null
5162                         // because they are not included in builder_to_method table
5163                         if (method.DeclaringType is TypeBuilder)
5164                                 return false;
5165
5166                         return AttributeTester.IsConditionalMethodExcluded (method);
5167                 }
5168
5169                 /// <remarks>
5170                 ///   is_base tells whether we want to force the use of the `call'
5171                 ///   opcode instead of using callvirt.  Call is required to call
5172                 ///   a specific method, while callvirt will always use the most
5173                 ///   recent method in the vtable.
5174                 ///
5175                 ///   is_static tells whether this is an invocation on a static method
5176                 ///
5177                 ///   instance_expr is an expression that represents the instance
5178                 ///   it must be non-null if is_static is false.
5179                 ///
5180                 ///   method is the method to invoke.
5181                 ///
5182                 ///   Arguments is the list of arguments to pass to the method or constructor.
5183                 /// </remarks>
5184                 public static void EmitCall (EmitContext ec, bool is_base,
5185                                              bool is_static, Expression instance_expr,
5186                                              MethodBase method, ArrayList Arguments, Location loc)
5187                 {
5188                         ILGenerator ig = ec.ig;
5189                         bool struct_call = false;
5190                         bool this_call = false;
5191
5192                         Type decl_type = method.DeclaringType;
5193
5194                         if (!RootContext.StdLib) {
5195                                 // Replace any calls to the system's System.Array type with calls to
5196                                 // the newly created one.
5197                                 if (method == TypeManager.system_int_array_get_length)
5198                                         method = TypeManager.int_array_get_length;
5199                                 else if (method == TypeManager.system_int_array_get_rank)
5200                                         method = TypeManager.int_array_get_rank;
5201                                 else if (method == TypeManager.system_object_array_clone)
5202                                         method = TypeManager.object_array_clone;
5203                                 else if (method == TypeManager.system_int_array_get_length_int)
5204                                         method = TypeManager.int_array_get_length_int;
5205                                 else if (method == TypeManager.system_int_array_get_lower_bound_int)
5206                                         method = TypeManager.int_array_get_lower_bound_int;
5207                                 else if (method == TypeManager.system_int_array_get_upper_bound_int)
5208                                         method = TypeManager.int_array_get_upper_bound_int;
5209                                 else if (method == TypeManager.system_void_array_copyto_array_int)
5210                                         method = TypeManager.void_array_copyto_array_int;
5211                         }
5212
5213                         //
5214                         // This checks ObsoleteAttribute on the method and on the declaring type
5215                         //
5216                         ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (method);
5217                         if (oa != null)
5218                                 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (method), loc);
5219
5220
5221                         oa = AttributeTester.GetObsoleteAttribute (method.DeclaringType);
5222                         if (oa != null) {
5223                                 AttributeTester.Report_ObsoleteMessage (oa, method.DeclaringType.FullName, loc);
5224                         }
5225
5226                         if (IsMethodExcluded (method, ec))
5227                 return; 
5228                         
5229                         if (!is_static){
5230                                 if (decl_type.IsValueType)
5231                                         struct_call = true;
5232                                 //
5233                                 // If this is ourselves, push "this"
5234                                 //
5235                                 if (instance_expr == null) {
5236                                         this_call = true;
5237                                         ig.Emit (OpCodes.Ldarg_0);
5238                                 } else {
5239                                         //
5240                                         // Push the instance expression
5241                                         //
5242                                         if (instance_expr.Type.IsValueType){
5243                                                 //
5244                                                 // Special case: calls to a function declared in a 
5245                                                 // reference-type with a value-type argument need
5246                                                 // to have their value boxed.  
5247
5248                                                 struct_call = true;
5249                                                 if (decl_type.IsValueType){
5250                                                         //
5251                                                         // If the expression implements IMemoryLocation, then
5252                                                         // we can optimize and use AddressOf on the
5253                                                         // return.
5254                                                         //
5255                                                         // If not we have to use some temporary storage for
5256                                                         // it.
5257                                                         if (instance_expr is IMemoryLocation){
5258                                                                 ((IMemoryLocation)instance_expr).
5259                                                                         AddressOf (ec, AddressOp.LoadStore);
5260                                                         }
5261                                                         else {
5262                                                                 Type t = instance_expr.Type;
5263                                                                 
5264                                                                 instance_expr.Emit (ec);
5265                                                                 LocalBuilder temp = ig.DeclareLocal (t);
5266                                                                 ig.Emit (OpCodes.Stloc, temp);
5267                                                                 ig.Emit (OpCodes.Ldloca, temp);
5268                                                         }
5269                                                 } else {
5270                                                         instance_expr.Emit (ec);
5271                                                         ig.Emit (OpCodes.Box, instance_expr.Type);
5272                                                 } 
5273                                         } else
5274                                                 instance_expr.Emit (ec);
5275                                 }
5276                         }
5277
5278                         EmitArguments (ec, method, Arguments);
5279
5280                         OpCode call_op;
5281                         if (is_static || struct_call || is_base || (this_call && !method.IsVirtual))
5282                                 call_op = OpCodes.Call;
5283                         else
5284                                 call_op = OpCodes.Callvirt;
5285
5286                         if ((method.CallingConvention & CallingConventions.VarArgs) != 0) {
5287                                 Type[] varargs_types = GetVarargsTypes (ec, method, Arguments);
5288                                 ig.EmitCall (call_op, (MethodInfo) method, varargs_types);
5289                                 return;
5290                         }
5291
5292                         //
5293                         // If you have:
5294                         // this.DoFoo ();
5295                         // and DoFoo is not virtual, you can omit the callvirt,
5296                         // because you don't need the null checking behavior.
5297                         //
5298                         if (method is MethodInfo)
5299                                 ig.Emit (call_op, (MethodInfo) method);
5300                         else
5301                                 ig.Emit (call_op, (ConstructorInfo) method);
5302                 }
5303                 
5304                 public override void Emit (EmitContext ec)
5305                 {
5306                         MethodGroupExpr mg = (MethodGroupExpr) this.expr;
5307
5308                         EmitCall (ec, is_base, method.IsStatic, mg.InstanceExpression, method, Arguments, loc);
5309                 }
5310                 
5311                 public override void EmitStatement (EmitContext ec)
5312                 {
5313                         Emit (ec);
5314
5315                         // 
5316                         // Pop the return value if there is one
5317                         //
5318                         if (method is MethodInfo){
5319                                 Type ret = ((MethodInfo)method).ReturnType;
5320                                 if (TypeManager.TypeToCoreType (ret) != TypeManager.void_type)
5321                                         ec.ig.Emit (OpCodes.Pop);
5322                         }
5323                 }
5324         }
5325
5326         public class InvocationOrCast : ExpressionStatement
5327         {
5328                 Expression expr;
5329                 Expression argument;
5330
5331                 public InvocationOrCast (Expression expr, Expression argument, Location loc)
5332                 {
5333                         this.expr = expr;
5334                         this.argument = argument;
5335                         this.loc = loc;
5336                 }
5337
5338                 public override Expression DoResolve (EmitContext ec)
5339                 {
5340                         //
5341                         // First try to resolve it as a cast.
5342                         //
5343                         type = ec.DeclSpace.ResolveType (expr, true, loc);
5344                         if (type != null) {
5345                                 Cast cast = new Cast (new TypeExpression (type, loc), argument, loc);
5346                                 return cast.Resolve (ec);
5347                         }
5348
5349                         //
5350                         // This can either be a type or a delegate invocation.
5351                         // Let's just resolve it and see what we'll get.
5352                         //
5353                         expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
5354                         if (expr == null)
5355                                 return null;
5356
5357                         //
5358                         // Ok, so it's a Cast.
5359                         //
5360                         if (expr.eclass == ExprClass.Type) {
5361                                 Cast cast = new Cast (new TypeExpression (expr.Type, loc), argument, loc);
5362                                 return cast.Resolve (ec);
5363                         }
5364
5365                         //
5366                         // It's a delegate invocation.
5367                         //
5368                         if (!TypeManager.IsDelegateType (expr.Type)) {
5369                                 Error (149, "Method name expected");
5370                                 return null;
5371                         }
5372
5373                         ArrayList args = new ArrayList ();
5374                         args.Add (new Argument (argument, Argument.AType.Expression));
5375                         DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
5376                         return invocation.Resolve (ec);
5377                 }
5378
5379                 void error201 ()
5380                 {
5381                         Error (201, "Only assignment, call, increment, decrement and new object " +
5382                                "expressions can be used as a statement");
5383                 }
5384
5385                 public override ExpressionStatement ResolveStatement (EmitContext ec)
5386                 {
5387                         //
5388                         // First try to resolve it as a cast.
5389                         //
5390                         type = ec.DeclSpace.ResolveType (expr, true, loc);
5391                         if (type != null) {
5392                                 error201 ();
5393                                 return null;
5394                         }
5395
5396                         //
5397                         // This can either be a type or a delegate invocation.
5398                         // Let's just resolve it and see what we'll get.
5399                         //
5400                         expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
5401                         if ((expr == null) || (expr.eclass == ExprClass.Type)) {
5402                                 error201 ();
5403                                 return null;
5404                         }
5405
5406                         //
5407                         // It's a delegate invocation.
5408                         //
5409                         if (!TypeManager.IsDelegateType (expr.Type)) {
5410                                 Error (149, "Method name expected");
5411                                 return null;
5412                         }
5413
5414                         ArrayList args = new ArrayList ();
5415                         args.Add (new Argument (argument, Argument.AType.Expression));
5416                         DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
5417                         return invocation.ResolveStatement (ec);
5418                 }
5419
5420                 public override void Emit (EmitContext ec)
5421                 {
5422                         throw new Exception ("Cannot happen");
5423                 }
5424
5425                 public override void EmitStatement (EmitContext ec)
5426                 {
5427                         throw new Exception ("Cannot happen");
5428                 }
5429         }
5430
5431         //
5432         // This class is used to "disable" the code generation for the
5433         // temporary variable when initializing value types.
5434         //
5435         class EmptyAddressOf : EmptyExpression, IMemoryLocation {
5436                 public void AddressOf (EmitContext ec, AddressOp Mode)
5437                 {
5438                         // nothing
5439                 }
5440         }
5441         
5442         /// <summary>
5443         ///    Implements the new expression 
5444         /// </summary>
5445         public class New : ExpressionStatement, IMemoryLocation {
5446                 public readonly ArrayList Arguments;
5447
5448                 //
5449                 // During bootstrap, it contains the RequestedType,
5450                 // but if `type' is not null, it *might* contain a NewDelegate
5451                 // (because of field multi-initialization)
5452                 //
5453                 public Expression RequestedType;
5454
5455                 MethodBase method = null;
5456
5457                 //
5458                 // If set, the new expression is for a value_target, and
5459                 // we will not leave anything on the stack.
5460                 //
5461                 Expression value_target;
5462                 bool value_target_set = false;
5463                 
5464                 public New (Expression requested_type, ArrayList arguments, Location l)
5465                 {
5466                         RequestedType = requested_type;
5467                         Arguments = arguments;
5468                         loc = l;
5469                 }
5470
5471                 public bool SetValueTypeVariable (Expression value)
5472                 {
5473                         value_target = value;
5474                         value_target_set = true;
5475                         if (!(value_target is IMemoryLocation)){
5476                                 Error_UnexpectedKind ("variable");
5477                                 return false;
5478                         }
5479                         return true;
5480                 }
5481
5482                 //
5483                 // This function is used to disable the following code sequence for
5484                 // value type initialization:
5485                 //
5486                 // AddressOf (temporary)
5487                 // Construct/Init
5488                 // LoadTemporary
5489                 //
5490                 // Instead the provide will have provided us with the address on the
5491                 // stack to store the results.
5492                 //
5493                 static Expression MyEmptyExpression;
5494                 
5495                 public void DisableTemporaryValueType ()
5496                 {
5497                         if (MyEmptyExpression == null)
5498                                 MyEmptyExpression = new EmptyAddressOf ();
5499
5500                         //
5501                         // To enable this, look into:
5502                         // test-34 and test-89 and self bootstrapping.
5503                         //
5504                         // For instance, we can avoid a copy by using `newobj'
5505                         // instead of Call + Push-temp on value types.
5506 //                      value_target = MyEmptyExpression;
5507                 }
5508
5509                 public override Expression DoResolve (EmitContext ec)
5510                 {
5511                         //
5512                         // The New DoResolve might be called twice when initializing field
5513                         // expressions (see EmitFieldInitializers, the call to
5514                         // GetInitializerExpression will perform a resolve on the expression,
5515                         // and later the assign will trigger another resolution
5516                         //
5517                         // This leads to bugs (#37014)
5518                         //
5519                         if (type != null){
5520                                 if (RequestedType is NewDelegate)
5521                                         return RequestedType;
5522                                 return this;
5523                         }
5524                         
5525                         type = ec.DeclSpace.ResolveType (RequestedType, false, loc);
5526                         
5527                         if (type == null)
5528                                 return null;
5529                         
5530                         CheckObsoleteAttribute (type);
5531
5532                         bool IsDelegate = TypeManager.IsDelegateType (type);
5533                         
5534                         if (IsDelegate){
5535                                 RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec);
5536                                 if (RequestedType != null)
5537                                         if (!(RequestedType is NewDelegate))
5538                                                 throw new Exception ("NewDelegate.Resolve returned a non NewDelegate: " + RequestedType.GetType ());
5539                                 return RequestedType;
5540                         }
5541
5542                         if (type.IsInterface || type.IsAbstract){
5543                                 Error (144, "It is not possible to create instances of interfaces or abstract classes");
5544                                 return null;
5545                         }
5546                         
5547                         bool is_struct = type.IsValueType;
5548                         eclass = ExprClass.Value;
5549
5550                         //
5551                         // SRE returns a match for .ctor () on structs (the object constructor), 
5552                         // so we have to manually ignore it.
5553                         //
5554                         if (is_struct && Arguments == null)
5555                                 return this;
5556                         
5557                         Expression ml;
5558                         // For member-lookup, treat 'new Foo (bar)' as call to 'foo.ctor (bar)', where 'foo' is of type 'Foo'.
5559                         ml = MemberLookupFinal (ec, type, type, ".ctor",
5560                                                 MemberTypes.Constructor,
5561                                                 AllBindingFlags | BindingFlags.DeclaredOnly, loc);
5562
5563                         if (ml == null)
5564                                 return null;
5565                         
5566                         if (! (ml is MethodGroupExpr)){
5567                                 if (!is_struct){
5568                                         ml.Error_UnexpectedKind ("method group");
5569                                         return null;
5570                                 }
5571                         }
5572
5573                         if (ml != null) {
5574                                 if (Arguments != null){
5575                                         foreach (Argument a in Arguments){
5576                                                 if (!a.Resolve (ec, loc))
5577                                                         return null;
5578                                         }
5579                                 }
5580
5581                                 method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, loc);
5582                                 
5583                         }
5584
5585                         if (method == null) { 
5586                                 if (!is_struct || Arguments.Count > 0) {
5587                                         Error (1501, String.Format (
5588                                             "New invocation: Can not find a constructor in `{0}' for this argument list",
5589                                             TypeManager.CSharpName (type)));
5590                                         return null;
5591                                 }
5592                         }
5593
5594                         return this;
5595                 }
5596
5597                 //
5598                 // This DoEmit can be invoked in two contexts:
5599                 //    * As a mechanism that will leave a value on the stack (new object)
5600                 //    * As one that wont (init struct)
5601                 //
5602                 // You can control whether a value is required on the stack by passing
5603                 // need_value_on_stack.  The code *might* leave a value on the stack
5604                 // so it must be popped manually
5605                 //
5606                 // If we are dealing with a ValueType, we have a few
5607                 // situations to deal with:
5608                 //
5609                 //    * The target is a ValueType, and we have been provided
5610                 //      the instance (this is easy, we are being assigned).
5611                 //
5612                 //    * The target of New is being passed as an argument,
5613                 //      to a boxing operation or a function that takes a
5614                 //      ValueType.
5615                 //
5616                 //      In this case, we need to create a temporary variable
5617                 //      that is the argument of New.
5618                 //
5619                 // Returns whether a value is left on the stack
5620                 //
5621                 bool DoEmit (EmitContext ec, bool need_value_on_stack)
5622                 {
5623                         bool is_value_type = type.IsValueType;
5624                         ILGenerator ig = ec.ig;
5625
5626                         if (is_value_type){
5627                                 IMemoryLocation ml;
5628
5629                                 // Allow DoEmit() to be called multiple times.
5630                                 // We need to create a new LocalTemporary each time since
5631                                 // you can't share LocalBuilders among ILGeneators.
5632                                 if (!value_target_set)
5633                                         value_target = new LocalTemporary (ec, type);
5634
5635                                 ml = (IMemoryLocation) value_target;
5636                                 ml.AddressOf (ec, AddressOp.Store);
5637                         }
5638
5639                         if (method != null)
5640                                 Invocation.EmitArguments (ec, method, Arguments);
5641
5642                         if (is_value_type){
5643                                 if (method == null)
5644                                         ig.Emit (OpCodes.Initobj, type);
5645                                 else 
5646                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
5647                                 if (need_value_on_stack){
5648                                         value_target.Emit (ec);
5649                                         return true;
5650                                 }
5651                                 return false;
5652                         } else {
5653                                 ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
5654                                 return true;
5655                         }
5656                 }
5657
5658                 public override void Emit (EmitContext ec)
5659                 {
5660                         DoEmit (ec, true);
5661                 }
5662                 
5663                 public override void EmitStatement (EmitContext ec)
5664                 {
5665                         if (DoEmit (ec, false))
5666                                 ec.ig.Emit (OpCodes.Pop);
5667                 }
5668
5669                 public void AddressOf (EmitContext ec, AddressOp Mode)
5670                 {
5671                         if (!type.IsValueType){
5672                                 //
5673                                 // We throw an exception.  So far, I believe we only need to support
5674                                 // value types:
5675                                 // foreach (int j in new StructType ())
5676                                 // see bug 42390
5677                                 //
5678                                 throw new Exception ("AddressOf should not be used for classes");
5679                         }
5680
5681                         if (!value_target_set)
5682                                 value_target = new LocalTemporary (ec, type);
5683                                         
5684                         IMemoryLocation ml = (IMemoryLocation) value_target;
5685                         ml.AddressOf (ec, AddressOp.Store);
5686                         if (method != null)
5687                                 Invocation.EmitArguments (ec, method, Arguments);
5688
5689                         if (method == null)
5690                                 ec.ig.Emit (OpCodes.Initobj, type);
5691                         else 
5692                                 ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
5693                         
5694                         ((IMemoryLocation) value_target).AddressOf (ec, Mode);
5695                 }
5696         }
5697
5698         /// <summary>
5699         ///   14.5.10.2: Represents an array creation expression.
5700         /// </summary>
5701         ///
5702         /// <remarks>
5703         ///   There are two possible scenarios here: one is an array creation
5704         ///   expression that specifies the dimensions and optionally the
5705         ///   initialization data and the other which does not need dimensions
5706         ///   specified but where initialization data is mandatory.
5707         /// </remarks>
5708         public class ArrayCreation : Expression {
5709                 Expression requested_base_type;
5710                 ArrayList initializers;
5711
5712                 //
5713                 // The list of Argument types.
5714                 // This is used to construct the `newarray' or constructor signature
5715                 //
5716                 ArrayList arguments;
5717
5718                 //
5719                 // Method used to create the array object.
5720                 //
5721                 MethodBase new_method = null;
5722                 
5723                 Type array_element_type;
5724                 Type underlying_type;
5725                 bool is_one_dimensional = false;
5726                 bool is_builtin_type = false;
5727                 bool expect_initializers = false;
5728                 int num_arguments = 0;
5729                 int dimensions = 0;
5730                 string rank;
5731
5732                 ArrayList array_data;
5733
5734                 Hashtable bounds;
5735
5736                 //
5737                 // The number of array initializers that we can handle
5738                 // via the InitializeArray method - through EmitStaticInitializers
5739                 //
5740                 int num_automatic_initializers;
5741
5742                 const int max_automatic_initializers = 6;
5743                 
5744                 public ArrayCreation (Expression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l)
5745                 {
5746                         this.requested_base_type = requested_base_type;
5747                         this.initializers = initializers;
5748                         this.rank = rank;
5749                         loc = l;
5750
5751                         arguments = new ArrayList ();
5752
5753                         foreach (Expression e in exprs) {
5754                                 arguments.Add (new Argument (e, Argument.AType.Expression));
5755                                 num_arguments++;
5756                         }
5757                 }
5758
5759                 public ArrayCreation (Expression requested_base_type, string rank, ArrayList initializers, Location l)
5760                 {
5761                         this.requested_base_type = requested_base_type;
5762                         this.initializers = initializers;
5763                         this.rank = rank;
5764                         loc = l;
5765
5766                         //this.rank = rank.Substring (0, rank.LastIndexOf ('['));
5767                         //
5768                         //string tmp = rank.Substring (rank.LastIndexOf ('['));
5769                         //
5770                         //dimensions = tmp.Length - 1;
5771                         expect_initializers = true;
5772                 }
5773
5774                 public Expression FormArrayType (Expression base_type, int idx_count, string rank)
5775                 {
5776                         StringBuilder sb = new StringBuilder (rank);
5777                         
5778                         sb.Append ("[");
5779                         for (int i = 1; i < idx_count; i++)
5780                                 sb.Append (",");
5781                         
5782                         sb.Append ("]");
5783
5784                         return new ComposedCast (base_type, sb.ToString (), loc);
5785                 }
5786
5787                 void Error_IncorrectArrayInitializer ()
5788                 {
5789                         Error (178, "Incorrectly structured array initializer");
5790                 }
5791                 
5792                 public bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims)
5793                 {
5794                         if (specified_dims) { 
5795                                 Argument a = (Argument) arguments [idx];
5796                                 
5797                                 if (!a.Resolve (ec, loc))
5798                                         return false;
5799                                 
5800                                 if (!(a.Expr is Constant)) {
5801                                         Error (150, "A constant value is expected");
5802                                         return false;
5803                                 }
5804                                 
5805                                 int value = (int) ((Constant) a.Expr).GetValue ();
5806                                 
5807                                 if (value != probe.Count) {
5808                                         Error_IncorrectArrayInitializer ();
5809                                         return false;
5810                                 }
5811                                 
5812                                 bounds [idx] = value;
5813                         }
5814
5815                         int child_bounds = -1;
5816                         foreach (object o in probe) {
5817                                 if (o is ArrayList) {
5818                                         int current_bounds = ((ArrayList) o).Count;
5819                                         
5820                                         if (child_bounds == -1) 
5821                                                 child_bounds = current_bounds;
5822
5823                                         else if (child_bounds != current_bounds){
5824                                                 Error_IncorrectArrayInitializer ();
5825                                                 return false;
5826                                         }
5827                                         if (specified_dims && (idx + 1 >= arguments.Count)){
5828                                                 Error (623, "Array initializers can only be used in a variable or field initializer, try using the new expression");
5829                                                 return false;
5830                                         }
5831                                         
5832                                         bool ret = CheckIndices (ec, (ArrayList) o, idx + 1, specified_dims);
5833                                         if (!ret)
5834                                                 return false;
5835                                 } else {
5836                                         if (child_bounds != -1){
5837                                                 Error_IncorrectArrayInitializer ();
5838                                                 return false;
5839                                         }
5840                                         
5841                                         Expression tmp = (Expression) o;
5842                                         tmp = tmp.Resolve (ec);
5843                                         if (tmp == null)
5844                                                 return false;
5845
5846                                         // Console.WriteLine ("I got: " + tmp);
5847                                         // Handle initialization from vars, fields etc.
5848
5849                                         Expression conv = Convert.ImplicitConversionRequired (
5850                                                 ec, tmp, underlying_type, loc);
5851                                         
5852                                         if (conv == null) 
5853                                                 return false;
5854                                         
5855                                         if (conv is StringConstant || conv is DecimalConstant || conv is NullCast) {
5856                                                 // These are subclasses of Constant that can appear as elements of an
5857                                                 // array that cannot be statically initialized (with num_automatic_initializers
5858                                                 // > max_automatic_initializers), so num_automatic_initializers should be left as zero.
5859                                                 array_data.Add (conv);
5860                                         } else if (conv is Constant) {
5861                                                 // These are the types of Constant that can appear in arrays that can be
5862                                                 // statically allocated.
5863                                                 array_data.Add (conv);
5864                                                 num_automatic_initializers++;
5865                                         } else
5866                                                 array_data.Add (conv);
5867                                 }
5868                         }
5869
5870                         return true;
5871                 }
5872                 
5873                 public void UpdateIndices (EmitContext ec)
5874                 {
5875                         int i = 0;
5876                         for (ArrayList probe = initializers; probe != null;) {
5877                                 if (probe.Count > 0 && probe [0] is ArrayList) {
5878                                         Expression e = new IntConstant (probe.Count);
5879                                         arguments.Add (new Argument (e, Argument.AType.Expression));
5880
5881                                         bounds [i++] =  probe.Count;
5882                                         
5883                                         probe = (ArrayList) probe [0];
5884                                         
5885                                 } else {
5886                                         Expression e = new IntConstant (probe.Count);
5887                                         arguments.Add (new Argument (e, Argument.AType.Expression));
5888
5889                                         bounds [i++] = probe.Count;
5890                                         probe = null;
5891                                 }
5892                         }
5893
5894                 }
5895                 
5896                 public bool ValidateInitializers (EmitContext ec, Type array_type)
5897                 {
5898                         if (initializers == null) {
5899                                 if (expect_initializers)
5900                                         return false;
5901                                 else
5902                                         return true;
5903                         }
5904                         
5905                         if (underlying_type == null)
5906                                 return false;
5907                         
5908                         //
5909                         // We use this to store all the date values in the order in which we
5910                         // will need to store them in the byte blob later
5911                         //
5912                         array_data = new ArrayList ();
5913                         bounds = new Hashtable ();
5914                         
5915                         bool ret;
5916
5917                         if (arguments != null) {
5918                                 ret = CheckIndices (ec, initializers, 0, true);
5919                                 return ret;
5920                         } else {
5921                                 arguments = new ArrayList ();
5922
5923                                 ret = CheckIndices (ec, initializers, 0, false);
5924                                 
5925                                 if (!ret)
5926                                         return false;
5927                                 
5928                                 UpdateIndices (ec);
5929                                 
5930                                 if (arguments.Count != dimensions) {
5931                                         Error_IncorrectArrayInitializer ();
5932                                         return false;
5933                                 }
5934
5935                                 return ret;
5936                         }
5937                 }
5938
5939                 void Error_NegativeArrayIndex ()
5940                 {
5941                         Error (284, "Can not create array with a negative size");
5942                 }
5943                 
5944                 //
5945                 // Converts `source' to an int, uint, long or ulong.
5946                 //
5947                 Expression ExpressionToArrayArgument (EmitContext ec, Expression source)
5948                 {
5949                         Expression target;
5950                         
5951                         bool old_checked = ec.CheckState;
5952                         ec.CheckState = true;
5953                         
5954                         target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
5955                         if (target == null){
5956                                 target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
5957                                 if (target == null){
5958                                         target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
5959                                         if (target == null){
5960                                                 target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
5961                                                 if (target == null)
5962                                                         Convert.Error_CannotImplicitConversion (loc, source.Type, TypeManager.int32_type);
5963                                         }
5964                                 }
5965                         } 
5966                         ec.CheckState = old_checked;
5967
5968                         //
5969                         // Only positive constants are allowed at compile time
5970                         //
5971                         if (target is Constant){
5972                                 if (target is IntConstant){
5973                                         if (((IntConstant) target).Value < 0){
5974                                                 Error_NegativeArrayIndex ();
5975                                                 return null;
5976                                         }
5977                                 }
5978
5979                                 if (target is LongConstant){
5980                                         if (((LongConstant) target).Value < 0){
5981                                                 Error_NegativeArrayIndex ();
5982                                                 return null;
5983                                         }
5984                                 }
5985                                 
5986                         }
5987
5988                         return target;
5989                 }
5990
5991                 //
5992                 // Creates the type of the array
5993                 //
5994                 bool LookupType (EmitContext ec)
5995                 {
5996                         StringBuilder array_qualifier = new StringBuilder (rank);
5997
5998                         //
5999                         // `In the first form allocates an array instace of the type that results
6000                         // from deleting each of the individual expression from the expression list'
6001                         //
6002                         if (num_arguments > 0) {
6003                                 array_qualifier.Append ("[");
6004                                 for (int i = num_arguments-1; i > 0; i--)
6005                                         array_qualifier.Append (",");
6006                                 array_qualifier.Append ("]");                           
6007                         }
6008
6009                         //
6010                         // Lookup the type
6011                         //
6012                         Expression array_type_expr;
6013                         array_type_expr = new ComposedCast (requested_base_type, array_qualifier.ToString (), loc);
6014                         type = ec.DeclSpace.ResolveType (array_type_expr, false, loc);
6015
6016                         if (type == null)
6017                                 return false;
6018                         
6019                         if (!type.IsArray) {
6020                                 Error (622, "Can only use array initializer expressions to assign to array types. Try using a new expression instead.");
6021                                 return false;
6022                         }
6023                         underlying_type = TypeManager.GetElementType (type);
6024                         dimensions = type.GetArrayRank ();
6025
6026                         return true;
6027                 }
6028                 
6029                 public override Expression DoResolve (EmitContext ec)
6030                 {
6031                         int arg_count;
6032
6033                         if (!LookupType (ec))
6034                                 return null;
6035                         
6036                         //
6037                         // First step is to validate the initializers and fill
6038                         // in any missing bits
6039                         //
6040                         if (!ValidateInitializers (ec, type))
6041                                 return null;
6042
6043                         if (arguments == null)
6044                                 arg_count = 0;
6045                         else {
6046                                 arg_count = arguments.Count;
6047                                 foreach (Argument a in arguments){
6048                                         if (!a.Resolve (ec, loc))
6049                                                 return null;
6050
6051                                         Expression real_arg = ExpressionToArrayArgument (ec, a.Expr, loc);
6052                                         if (real_arg == null)
6053                                                 return null;
6054
6055                                         a.Expr = real_arg;
6056                                 }
6057                         }
6058                         
6059                         array_element_type = TypeManager.GetElementType (type);
6060
6061                         if (arg_count == 1) {
6062                                 is_one_dimensional = true;
6063                                 eclass = ExprClass.Value;
6064                                 return this;
6065                         }
6066
6067                         is_builtin_type = TypeManager.IsBuiltinType (type);
6068
6069                         if (is_builtin_type) {
6070                                 Expression ml;
6071                                 
6072                                 ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor,
6073                                                    AllBindingFlags, loc);
6074                                 
6075                                 if (!(ml is MethodGroupExpr)) {
6076                                         ml.Error_UnexpectedKind ("method group");
6077                                         return null;
6078                                 }
6079                                 
6080                                 if (ml == null) {
6081                                         Error (-6, "New invocation: Can not find a constructor for " +
6082                                                       "this argument list");
6083                                         return null;
6084                                 }
6085                                 
6086                                 new_method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, arguments, loc);
6087
6088                                 if (new_method == null) {
6089                                         Error (-6, "New invocation: Can not find a constructor for " +
6090                                                       "this argument list");
6091                                         return null;
6092                                 }
6093                                 
6094                                 eclass = ExprClass.Value;
6095                                 return this;
6096                         } else {
6097                                 ModuleBuilder mb = CodeGen.Module.Builder;
6098                                 ArrayList args = new ArrayList ();
6099                                 
6100                                 if (arguments != null) {
6101                                         for (int i = 0; i < arg_count; i++)
6102                                                 args.Add (TypeManager.int32_type);
6103                                 }
6104                                 
6105                                 Type [] arg_types = null;
6106
6107                                 if (args.Count > 0)
6108                                         arg_types = new Type [args.Count];
6109                                 
6110                                 args.CopyTo (arg_types, 0);
6111                                 
6112                                 new_method = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,
6113                                                             arg_types);
6114
6115                                 if (new_method == null) {
6116                                         Error (-6, "New invocation: Can not find a constructor for " +
6117                                                       "this argument list");
6118                                         return null;
6119                                 }
6120                                 
6121                                 eclass = ExprClass.Value;
6122                                 return this;
6123                         }
6124                 }
6125
6126                 public static byte [] MakeByteBlob (ArrayList array_data, Type underlying_type, Location loc)
6127                 {
6128                         int factor;
6129                         byte [] data;
6130                         byte [] element;
6131                         int count = array_data.Count;
6132
6133                         if (underlying_type.IsEnum)
6134                                 underlying_type = TypeManager.EnumToUnderlying (underlying_type);
6135                         
6136                         factor = GetTypeSize (underlying_type);
6137                         if (factor == 0)
6138                                 throw new Exception ("unrecognized type in MakeByteBlob: " + underlying_type);
6139
6140                         data = new byte [(count * factor + 4) & ~3];
6141                         int idx = 0;
6142                         
6143                         for (int i = 0; i < count; ++i) {
6144                                 object v = array_data [i];
6145
6146                                 if (v is EnumConstant)
6147                                         v = ((EnumConstant) v).Child;
6148                                 
6149                                 if (v is Constant && !(v is StringConstant))
6150                                         v = ((Constant) v).GetValue ();
6151                                 else {
6152                                         idx += factor;
6153                                         continue;
6154                                 }
6155                                 
6156                                 if (underlying_type == TypeManager.int64_type){
6157                                         if (!(v is Expression)){
6158                                                 long val = (long) 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.uint64_type){
6166                                         if (!(v is Expression)){
6167                                                 ulong val = (ulong) v;
6168
6169                                                 for (int j = 0; j < factor; ++j) {
6170                                                         data [idx + j] = (byte) (val & 0xFF);
6171                                                         val = (val >> 8);
6172                                                 }
6173                                         }
6174                                 } else if (underlying_type == TypeManager.float_type) {
6175                                         if (!(v is Expression)){
6176                                                 element = BitConverter.GetBytes ((float) v);
6177                                                         
6178                                                 for (int j = 0; j < factor; ++j)
6179                                                         data [idx + j] = element [j];
6180                                         }
6181                                 } else if (underlying_type == TypeManager.double_type) {
6182                                         if (!(v is Expression)){
6183                                                 element = BitConverter.GetBytes ((double) v);
6184
6185                                                 for (int j = 0; j < factor; ++j)
6186                                                         data [idx + j] = element [j];
6187                                         }
6188                                 } else if (underlying_type == TypeManager.char_type){
6189                                         if (!(v is Expression)){
6190                                                 int val = (int) ((char) v);
6191                                                 
6192                                                 data [idx] = (byte) (val & 0xff);
6193                                                 data [idx+1] = (byte) (val >> 8);
6194                                         }
6195                                 } else if (underlying_type == TypeManager.short_type){
6196                                         if (!(v is Expression)){
6197                                                 int val = (int) ((short) v);
6198                                         
6199                                                 data [idx] = (byte) (val & 0xff);
6200                                                 data [idx+1] = (byte) (val >> 8);
6201                                         }
6202                                 } else if (underlying_type == TypeManager.ushort_type){
6203                                         if (!(v is Expression)){
6204                                                 int val = (int) ((ushort) v);
6205                                         
6206                                                 data [idx] = (byte) (val & 0xff);
6207                                                 data [idx+1] = (byte) (val >> 8);
6208                                         }
6209                                 } else if (underlying_type == TypeManager.int32_type) {
6210                                         if (!(v is Expression)){
6211                                                 int val = (int) 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.uint32_type) {
6219                                         if (!(v is Expression)){
6220                                                 uint val = (uint) v;
6221                                         
6222                                                 data [idx]   = (byte) (val & 0xff);
6223                                                 data [idx+1] = (byte) ((val >> 8) & 0xff);
6224                                                 data [idx+2] = (byte) ((val >> 16) & 0xff);
6225                                                 data [idx+3] = (byte) (val >> 24);
6226                                         }
6227                                 } else if (underlying_type == TypeManager.sbyte_type) {
6228                                         if (!(v is Expression)){
6229                                                 sbyte val = (sbyte) v;
6230                                                 data [idx] = (byte) val;
6231                                         }
6232                                 } else if (underlying_type == TypeManager.byte_type) {
6233                                         if (!(v is Expression)){
6234                                                 byte val = (byte) v;
6235                                                 data [idx] = (byte) val;
6236                                         }
6237                                 } else if (underlying_type == TypeManager.bool_type) {
6238                                         if (!(v is Expression)){
6239                                                 bool val = (bool) v;
6240                                                 data [idx] = (byte) (val ? 1 : 0);
6241                                         }
6242                                 } else if (underlying_type == TypeManager.decimal_type){
6243                                         if (!(v is Expression)){
6244                                                 int [] bits = Decimal.GetBits ((decimal) v);
6245                                                 int p = idx;
6246
6247                                                 // FIXME: For some reason, this doesn't work on the MS runtime.
6248                                                 int [] nbits = new int [4];
6249                                                 nbits [0] = bits [3];
6250                                                 nbits [1] = bits [2];
6251                                                 nbits [2] = bits [0];
6252                                                 nbits [3] = bits [1];
6253                                                 
6254                                                 for (int j = 0; j < 4; j++){
6255                                                         data [p++] = (byte) (nbits [j] & 0xff);
6256                                                         data [p++] = (byte) ((nbits [j] >> 8) & 0xff);
6257                                                         data [p++] = (byte) ((nbits [j] >> 16) & 0xff);
6258                                                         data [p++] = (byte) (nbits [j] >> 24);
6259                                                 }
6260                                         }
6261                                 } else
6262                                         throw new Exception ("Unrecognized type in MakeByteBlob: " + underlying_type);
6263
6264                                 idx += factor;
6265                         }
6266
6267                         return data;
6268                 }
6269
6270                 //
6271                 // Emits the initializers for the array
6272                 //
6273                 void EmitStaticInitializers (EmitContext ec)
6274                 {
6275                         //
6276                         // First, the static data
6277                         //
6278                         FieldBuilder fb;
6279                         ILGenerator ig = ec.ig;
6280                         
6281                         byte [] data = MakeByteBlob (array_data, underlying_type, loc);
6282
6283                         fb = RootContext.MakeStaticData (data);
6284
6285                         ig.Emit (OpCodes.Dup);
6286                         ig.Emit (OpCodes.Ldtoken, fb);
6287                         ig.Emit (OpCodes.Call,
6288                                  TypeManager.void_initializearray_array_fieldhandle);
6289                 }
6290
6291                 //
6292                 // Emits pieces of the array that can not be computed at compile
6293                 // time (variables and string locations).
6294                 //
6295                 // This always expect the top value on the stack to be the array
6296                 //
6297                 void EmitDynamicInitializers (EmitContext ec)
6298                 {
6299                         ILGenerator ig = ec.ig;
6300                         int dims = bounds.Count;
6301                         int [] current_pos = new int [dims];
6302                         int top = array_data.Count;
6303
6304                         MethodInfo set = null;
6305
6306                         if (dims != 1){
6307                                 Type [] args;
6308                                 ModuleBuilder mb = null;
6309                                 mb = CodeGen.Module.Builder;
6310                                 args = new Type [dims + 1];
6311
6312                                 int j;
6313                                 for (j = 0; j < dims; j++)
6314                                         args [j] = TypeManager.int32_type;
6315
6316                                 args [j] = array_element_type;
6317                                 
6318                                 set = mb.GetArrayMethod (
6319                                         type, "Set",
6320                                         CallingConventions.HasThis | CallingConventions.Standard,
6321                                         TypeManager.void_type, args);
6322                         }
6323                         
6324                         for (int i = 0; i < top; i++){
6325
6326                                 Expression e = null;
6327
6328                                 if (array_data [i] is Expression)
6329                                         e = (Expression) array_data [i];
6330
6331                                 if (e != null) {
6332                                         //
6333                                         // Basically we do this for string literals and
6334                                         // other non-literal expressions
6335                                         //
6336                                         if (e is EnumConstant){
6337                                                 e = ((EnumConstant) e).Child;
6338                                         }
6339                                         
6340                                         if (e is StringConstant || e is DecimalConstant || !(e is Constant) ||
6341                                             num_automatic_initializers <= max_automatic_initializers) {
6342                                                 Type etype = e.Type;
6343                                                 
6344                                                 ig.Emit (OpCodes.Dup);
6345
6346                                                 for (int idx = 0; idx < dims; idx++) 
6347                                                         IntConstant.EmitInt (ig, current_pos [idx]);
6348
6349                                                 //
6350                                                 // If we are dealing with a struct, get the
6351                                                 // address of it, so we can store it.
6352                                                 //
6353                                                 if ((dims == 1) && 
6354                                                     etype.IsSubclassOf (TypeManager.value_type) &&
6355                                                     (!TypeManager.IsBuiltinOrEnum (etype) ||
6356                                                      etype == TypeManager.decimal_type)) {
6357                                                         if (e is New){
6358                                                                 New n = (New) e;
6359
6360                                                                 //
6361                                                                 // Let new know that we are providing
6362                                                                 // the address where to store the results
6363                                                                 //
6364                                                                 n.DisableTemporaryValueType ();
6365                                                         }
6366
6367                                                         ig.Emit (OpCodes.Ldelema, etype);
6368                                                 }
6369
6370                                                 e.Emit (ec);
6371
6372                                                 if (dims == 1)
6373                                                         ArrayAccess.EmitStoreOpcode (ig, array_element_type);
6374                                                 else 
6375                                                         ig.Emit (OpCodes.Call, set);
6376
6377                                         }
6378                                 }
6379                                 
6380                                 //
6381                                 // Advance counter
6382                                 //
6383                                 for (int j = dims - 1; j >= 0; j--){
6384                                         current_pos [j]++;
6385                                         if (current_pos [j] < (int) bounds [j])
6386                                                 break;
6387                                         current_pos [j] = 0;
6388                                 }
6389                         }
6390                 }
6391
6392                 void EmitArrayArguments (EmitContext ec)
6393                 {
6394                         ILGenerator ig = ec.ig;
6395                         
6396                         foreach (Argument a in arguments) {
6397                                 Type atype = a.Type;
6398                                 a.Emit (ec);
6399
6400                                 if (atype == TypeManager.uint64_type)
6401                                         ig.Emit (OpCodes.Conv_Ovf_U4);
6402                                 else if (atype == TypeManager.int64_type)
6403                                         ig.Emit (OpCodes.Conv_Ovf_I4);
6404                         }
6405                 }
6406                 
6407                 public override void Emit (EmitContext ec)
6408                 {
6409                         ILGenerator ig = ec.ig;
6410                         
6411                         EmitArrayArguments (ec);
6412                         if (is_one_dimensional)
6413                                 ig.Emit (OpCodes.Newarr, array_element_type);
6414                         else {
6415                                 if (is_builtin_type) 
6416                                         ig.Emit (OpCodes.Newobj, (ConstructorInfo) new_method);
6417                                 else 
6418                                         ig.Emit (OpCodes.Newobj, (MethodInfo) new_method);
6419                         }
6420                         
6421                         if (initializers != null){
6422                                 //
6423                                 // FIXME: Set this variable correctly.
6424                                 // 
6425                                 bool dynamic_initializers = true;
6426
6427                                 // This will never be true for array types that cannot be statically
6428                                 // initialized. num_automatic_initializers will always be zero.  See
6429                                 // CheckIndices.
6430                                 if (num_automatic_initializers > max_automatic_initializers)
6431                                         EmitStaticInitializers (ec);
6432                                 
6433                                 if (dynamic_initializers)
6434                                         EmitDynamicInitializers (ec);
6435                         }
6436                 }
6437
6438                 public object EncodeAsAttribute ()
6439                 {
6440                         if (!is_one_dimensional){
6441                                 Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays");
6442                                 return null;
6443                         }
6444
6445                         if (array_data == null){
6446                                 Report.Error (-212, Location, "array should be initialized when passing it to an attribute");
6447                                 return null;
6448                         }
6449                         
6450                         object [] ret = new object [array_data.Count];
6451                         int i = 0;
6452                         foreach (Expression e in array_data){
6453                                 object v;
6454                                 
6455                                 if (e is NullLiteral)
6456                                         v = null;
6457                                 else {
6458                                         if (!Attribute.GetAttributeArgumentExpression (e, Location, out v))
6459                                                 return null;
6460                                 }
6461                                 ret [i++] = v;
6462                         }
6463                         return ret;
6464                 }
6465
6466                 public Expression TurnIntoConstant ()
6467                 {
6468                         //
6469                         // Should use something like the above attribute thing.
6470                         // It should return a subclass of Constant that just returns
6471                         // the computed value of the array
6472                         //
6473                         throw new Exception ("Does not support yet Turning array into a Constant");
6474                 }
6475         }
6476         
6477         /// <summary>
6478         ///   Represents the `this' construct
6479         /// </summary>
6480         public class This : Expression, IAssignMethod, IMemoryLocation, IVariable {
6481
6482                 Block block;
6483                 VariableInfo variable_info;
6484                 
6485                 public This (Block block, Location loc)
6486                 {
6487                         this.loc = loc;
6488                         this.block = block;
6489                 }
6490
6491                 public This (Location loc)
6492                 {
6493                         this.loc = loc;
6494                 }
6495
6496                 public VariableInfo VariableInfo {
6497                         get { return variable_info; }
6498                 }
6499
6500                 public bool VerifyFixed (bool is_expression)
6501                 {
6502                         if ((variable_info == null) || (variable_info.LocalInfo == null))
6503                                 return false;
6504                         else
6505                                 return variable_info.LocalInfo.IsFixed;
6506                 }
6507
6508                 public bool ResolveBase (EmitContext ec)
6509                 {
6510                         eclass = ExprClass.Variable;
6511                         type = ec.ContainerType;
6512
6513                         if (ec.IsStatic) {
6514                                 Error (26, "Keyword this not valid in static code");
6515                                 return false;
6516                         }
6517
6518                         if ((block != null) && (block.ThisVariable != null))
6519                                 variable_info = block.ThisVariable.VariableInfo;
6520
6521                         return true;
6522                 }
6523
6524                 public override Expression DoResolve (EmitContext ec)
6525                 {
6526                         if (!ResolveBase (ec))
6527                                 return null;
6528
6529                         if ((variable_info != null) && !variable_info.IsAssigned (ec)) {
6530                                 Error (188, "The this object cannot be used before all " +
6531                                        "of its fields are assigned to");
6532                                 variable_info.SetAssigned (ec);
6533                                 return this;
6534                         }
6535
6536                         if (ec.IsFieldInitializer) {
6537                                 Error (27, "Keyword `this' can't be used outside a constructor, " +
6538                                        "a method or a property.");
6539                                 return null;
6540                         }
6541
6542                         return this;
6543                 }
6544
6545                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
6546                 {
6547                         if (!ResolveBase (ec))
6548                                 return null;
6549
6550                         if (variable_info != null)
6551                                 variable_info.SetAssigned (ec);
6552                         
6553                         if (ec.TypeContainer is Class){
6554                                 Error (1604, "Cannot assign to `this'");
6555                                 return null;
6556                         }
6557
6558                         return this;
6559                 }
6560
6561                 public override void Emit (EmitContext ec)
6562                 {
6563                         ILGenerator ig = ec.ig;
6564
6565                         ec.EmitThis ();
6566                         if (ec.TypeContainer is Struct)
6567                                 ig.Emit (OpCodes.Ldobj, type);
6568                 }
6569
6570                 public void EmitAssign (EmitContext ec, Expression source)
6571                 {
6572                         ILGenerator ig = ec.ig;
6573                         
6574                         if (ec.TypeContainer is Struct){
6575                                 ec.EmitThis ();
6576                                 source.Emit (ec);
6577                                 ig.Emit (OpCodes.Stobj, type);
6578                         } else {
6579                                 source.Emit (ec);
6580                                 ig.Emit (OpCodes.Starg, 0);
6581                         }
6582                 }
6583
6584                 public void AddressOf (EmitContext ec, AddressOp mode)
6585                 {
6586                         ec.EmitThis ();
6587
6588                         // FIMXE
6589                         // FIGURE OUT WHY LDARG_S does not work
6590                         //
6591                         // consider: struct X { int val; int P { set { val = value; }}}
6592                         //
6593                         // Yes, this looks very bad. Look at `NOTAS' for
6594                         // an explanation.
6595                         // ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);
6596                 }
6597         }
6598
6599         /// <summary>
6600         ///   Represents the `__arglist' construct
6601         /// </summary>
6602         public class ArglistAccess : Expression
6603         {
6604                 public ArglistAccess (Location loc)
6605                 {
6606                         this.loc = loc;
6607                 }
6608
6609                 public bool ResolveBase (EmitContext ec)
6610                 {
6611                         eclass = ExprClass.Variable;
6612                         type = TypeManager.runtime_argument_handle_type;
6613                         return true;
6614                 }
6615
6616                 public override Expression DoResolve (EmitContext ec)
6617                 {
6618                         if (!ResolveBase (ec))
6619                                 return null;
6620
6621                         if (ec.IsFieldInitializer || !ec.CurrentBlock.HasVarargs) {
6622                                 Error (190, "The __arglist construct is valid only within " +
6623                                        "a variable argument method.");
6624                                 return null;
6625                         }
6626
6627                         return this;
6628                 }
6629
6630                 public override void Emit (EmitContext ec)
6631                 {
6632                         ec.ig.Emit (OpCodes.Arglist);
6633                 }
6634         }
6635
6636         /// <summary>
6637         ///   Represents the `__arglist (....)' construct
6638         /// </summary>
6639         public class Arglist : Expression
6640         {
6641                 public readonly Argument[] Arguments;
6642
6643                 public Arglist (Argument[] args, Location l)
6644                 {
6645                         Arguments = args;
6646                         loc = l;
6647                 }
6648
6649                 public Type[] ArgumentTypes {
6650                         get {
6651                                 Type[] retval = new Type [Arguments.Length];
6652                                 for (int i = 0; i < Arguments.Length; i++)
6653                                         retval [i] = Arguments [i].Type;
6654                                 return retval;
6655                         }
6656                 }
6657
6658                 public override Expression DoResolve (EmitContext ec)
6659                 {
6660                         eclass = ExprClass.Variable;
6661                         type = TypeManager.runtime_argument_handle_type;
6662
6663                         foreach (Argument arg in Arguments) {
6664                                 if (!arg.Resolve (ec, loc))
6665                                         return null;
6666                         }
6667
6668                         return this;
6669                 }
6670
6671                 public override void Emit (EmitContext ec)
6672                 {
6673                         foreach (Argument arg in Arguments)
6674                                 arg.Emit (ec);
6675                 }
6676         }
6677
6678         //
6679         // This produces the value that renders an instance, used by the iterators code
6680         //
6681         public class ProxyInstance : Expression, IMemoryLocation  {
6682                 public override Expression DoResolve (EmitContext ec)
6683                 {
6684                         eclass = ExprClass.Variable;
6685                         type = ec.ContainerType;
6686                         return this;
6687                 }
6688                 
6689                 public override void Emit (EmitContext ec)
6690                 {
6691                         ec.ig.Emit (OpCodes.Ldarg_0);
6692
6693                 }
6694                 
6695                 public void AddressOf (EmitContext ec, AddressOp mode)
6696                 {
6697                         ec.ig.Emit (OpCodes.Ldarg_0);
6698                 }
6699         }
6700
6701         /// <summary>
6702         ///   Implements the typeof operator
6703         /// </summary>
6704         public class TypeOf : Expression {
6705                 public readonly Expression QueriedType;
6706                 protected Type typearg;
6707                 
6708                 public TypeOf (Expression queried_type, Location l)
6709                 {
6710                         QueriedType = queried_type;
6711                         loc = l;
6712                 }
6713
6714                 public override Expression DoResolve (EmitContext ec)
6715                 {
6716                         typearg = ec.DeclSpace.ResolveType (QueriedType, false, loc);
6717
6718                         if (typearg == null)
6719                                 return null;
6720
6721                         if (typearg == TypeManager.void_type) {
6722                                 Error (673, "System.Void cannot be used from C# - " +
6723                                        "use typeof (void) to get the void type object");
6724                                 return null;
6725                         }
6726
6727                         if (typearg.IsPointer && !ec.InUnsafe){
6728                                 UnsafeError (loc);
6729                                 return null;
6730                         }
6731                         CheckObsoleteAttribute (typearg);
6732
6733                         type = TypeManager.type_type;
6734                         eclass = ExprClass.Type;
6735                         return this;
6736                 }
6737
6738                 public override void Emit (EmitContext ec)
6739                 {
6740                         ec.ig.Emit (OpCodes.Ldtoken, typearg);
6741                         ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
6742                 }
6743
6744                 public Type TypeArg { 
6745                         get { return typearg; }
6746                 }
6747         }
6748
6749         /// <summary>
6750         ///   Implements the `typeof (void)' operator
6751         /// </summary>
6752         public class TypeOfVoid : TypeOf {
6753                 public TypeOfVoid (Location l) : base (null, l)
6754                 {
6755                         loc = l;
6756                 }
6757
6758                 public override Expression DoResolve (EmitContext ec)
6759                 {
6760                         type = TypeManager.type_type;
6761                         typearg = TypeManager.void_type;
6762                         eclass = ExprClass.Type;
6763                         return this;
6764                 }
6765         }
6766
6767         /// <summary>
6768         ///   Implements the sizeof expression
6769         /// </summary>
6770         public class SizeOf : Expression {
6771                 public readonly Expression QueriedType;
6772                 Type type_queried;
6773                 
6774                 public SizeOf (Expression queried_type, Location l)
6775                 {
6776                         this.QueriedType = queried_type;
6777                         loc = l;
6778                 }
6779
6780                 public override Expression DoResolve (EmitContext ec)
6781                 {
6782                         if (!ec.InUnsafe) {
6783                                 Report.Error (
6784                                         233, loc, "Sizeof may only be used in an unsafe context " +
6785                                         "(consider using System.Runtime.InteropServices.Marshal.Sizeof");
6786                                 return null;
6787                         }
6788                                 
6789                         type_queried = ec.DeclSpace.ResolveType (QueriedType, false, loc);
6790                         if (type_queried == null)
6791                                 return null;
6792
6793                         CheckObsoleteAttribute (type_queried);
6794
6795                         if (!TypeManager.IsUnmanagedType (type_queried)){
6796                                 Report.Error (208, loc, "Cannot take the size of an unmanaged type (" + TypeManager.CSharpName (type_queried) + ")");
6797                                 return null;
6798                         }
6799                         
6800                         type = TypeManager.int32_type;
6801                         eclass = ExprClass.Value;
6802                         return this;
6803                 }
6804
6805                 public override void Emit (EmitContext ec)
6806                 {
6807                         int size = GetTypeSize (type_queried);
6808
6809                         if (size == 0)
6810                                 ec.ig.Emit (OpCodes.Sizeof, type_queried);
6811                         else
6812                                 IntConstant.EmitInt (ec.ig, size);
6813                 }
6814         }
6815
6816         /// <summary>
6817         ///   Implements the member access expression
6818         /// </summary>
6819         public class MemberAccess : Expression {
6820                 public readonly string Identifier;
6821                 Expression expr;
6822                 
6823                 public MemberAccess (Expression expr, string id, Location l)
6824                 {
6825                         this.expr = expr;
6826                         Identifier = id;
6827                         loc = l;
6828                 }
6829
6830                 public Expression Expr {
6831                         get {
6832                                 return expr;
6833                         }
6834                 }
6835
6836                 public static void error176 (Location loc, string name)
6837                 {
6838                         Report.Error (176, loc, "Static member `" +
6839                                       name + "' cannot be accessed " +
6840                                       "with an instance reference, qualify with a " +
6841                                       "type name instead");
6842                 }
6843
6844                 public static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Expression left, Location loc)
6845                 {
6846                         SimpleName sn = left_original as SimpleName;
6847                         if (sn == null || left == null || left.Type.Name != sn.Name)
6848                                 return false;
6849
6850                         return RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc) != null;
6851                 }
6852                 
6853                 public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup,
6854                                                               Expression left, Location loc,
6855                                                               Expression left_original)
6856                 {
6857                         bool left_is_type, left_is_explicit;
6858
6859                         // If `left' is null, then we're called from SimpleNameResolve and this is
6860                         // a member in the currently defining class.
6861                         if (left == null) {
6862                                 left_is_type = ec.IsStatic || ec.IsFieldInitializer;
6863                                 left_is_explicit = false;
6864
6865                                 // Implicitly default to `this' unless we're static.
6866                                 if (!ec.IsStatic && !ec.IsFieldInitializer && !ec.InEnumContext)
6867                                         left = ec.GetThis (loc);
6868                         } else {
6869                                 left_is_type = left is TypeExpr;
6870                                 left_is_explicit = true;
6871                         }
6872
6873                         if (member_lookup is FieldExpr){
6874                                 FieldExpr fe = (FieldExpr) member_lookup;
6875                                 FieldInfo fi = fe.FieldInfo;
6876                                 Type decl_type = fi.DeclaringType;
6877
6878                                 if (fi is FieldBuilder) {
6879                                         Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
6880                                         
6881                                         if (c != null) {
6882                                                 object o;
6883                                                 if (!c.LookupConstantValue (out o))
6884                                                         return null;
6885
6886                                                 object real_value = ((Constant) c.Expr).GetValue ();
6887
6888                                                 return Constantify (real_value, fi.FieldType);
6889                                         }
6890                                 }
6891
6892                                 if (fi.IsLiteral) {
6893                                         Type t = fi.FieldType;
6894                                         
6895                                         object o;
6896
6897                                         if (fi is FieldBuilder)
6898                                                 o = TypeManager.GetValue ((FieldBuilder) fi);
6899                                         else
6900                                                 o = fi.GetValue (fi);
6901                                         
6902                                         if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
6903                                                 if (left_is_explicit && !left_is_type &&
6904                                                     !IdenticalNameAndTypeName (ec, left_original, member_lookup, loc)) {
6905                                                         error176 (loc, fe.FieldInfo.Name);
6906                                                         return null;
6907                                                 }                                       
6908                                                 
6909                                                 Expression enum_member = MemberLookup (
6910                                                         ec, decl_type, "value__", MemberTypes.Field,
6911                                                         AllBindingFlags, loc); 
6912
6913                                                 Enum en = TypeManager.LookupEnum (decl_type);
6914
6915                                                 Constant c;
6916                                                 if (en != null)
6917                                                         c = Constantify (o, en.UnderlyingType);
6918                                                 else 
6919                                                         c = Constantify (o, enum_member.Type);
6920                                                 
6921                                                 return new EnumConstant (c, decl_type);
6922                                         }
6923                                         
6924                                         Expression exp = Constantify (o, t);
6925
6926                                         if (left_is_explicit && !left_is_type) {
6927                                                 error176 (loc, fe.FieldInfo.Name);
6928                                                 return null;
6929                                         }
6930                                         
6931                                         return exp;
6932                                 }
6933
6934                                 if (fi.FieldType.IsPointer && !ec.InUnsafe){
6935                                         UnsafeError (loc);
6936                                         return null;
6937                                 }
6938                         }
6939
6940                         if (member_lookup is EventExpr) {
6941                                 EventExpr ee = (EventExpr) member_lookup;
6942                                 
6943                                 //
6944                                 // If the event is local to this class, we transform ourselves into
6945                                 // a FieldExpr
6946                                 //
6947
6948                                 if (ee.EventInfo.DeclaringType == ec.ContainerType ||
6949                                     TypeManager.IsNestedChildOf(ec.ContainerType, ee.EventInfo.DeclaringType)) {
6950                                         MemberInfo mi = GetFieldFromEvent (ee);
6951
6952                                         if (mi == null) {
6953                                                 //
6954                                                 // If this happens, then we have an event with its own
6955                                                 // accessors and private field etc so there's no need
6956                                                 // to transform ourselves.
6957                                                 //
6958                                                 ee.InstanceExpression = left;
6959                                                 return ee;
6960                                         }
6961
6962                                         Expression ml = ExprClassFromMemberInfo (ec, mi, loc);
6963                                         
6964                                         if (ml == null) {
6965                                                 Report.Error (-200, loc, "Internal error!!");
6966                                                 return null;
6967                                         }
6968
6969                                         if (!left_is_explicit)
6970                                                 left = null;
6971
6972                                         ee.InstanceExpression = left;
6973
6974                                         return ResolveMemberAccess (ec, ml, left, loc, left_original);
6975                                 }
6976                         }
6977
6978                         if (member_lookup is IMemberExpr) {
6979                                 IMemberExpr me = (IMemberExpr) member_lookup;
6980                                 MethodGroupExpr mg = me as MethodGroupExpr;
6981
6982                                 if (left_is_type){
6983                                         if ((mg != null) && left_is_explicit && left.Type.IsInterface)
6984                                                 mg.IsExplicitImpl = left_is_explicit;
6985
6986                                         if (!me.IsStatic){
6987                                                 if ((ec.IsFieldInitializer || ec.IsStatic) &&
6988                                                     IdenticalNameAndTypeName (ec, left_original, member_lookup, loc))
6989                                                         return member_lookup;
6990                                                 
6991                                                 SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
6992                                                 return null;
6993                                         }
6994
6995                                 } else {
6996                                         if (!me.IsInstance) {
6997                                                 if (IdenticalNameAndTypeName (ec, left_original, left, loc))
6998                                                         return member_lookup;
6999
7000                                                 if (left_is_explicit) {
7001                                                         error176 (loc, me.Name);
7002                                                         return null;
7003                                                 }
7004                                         }                       
7005
7006                                         //
7007                                         // Since we can not check for instance objects in SimpleName,
7008                                         // becaue of the rule that allows types and variables to share
7009                                         // the name (as long as they can be de-ambiguated later, see 
7010                                         // IdenticalNameAndTypeName), we have to check whether left 
7011                                         // is an instance variable in a static context
7012                                         //
7013                                         // However, if the left-hand value is explicitly given, then
7014                                         // it is already our instance expression, so we aren't in
7015                                         // static context.
7016                                         //
7017
7018                                         if (ec.IsStatic && !left_is_explicit && left is IMemberExpr){
7019                                                 IMemberExpr mexp = (IMemberExpr) left;
7020
7021                                                 if (!mexp.IsStatic){
7022                                                         SimpleName.Error_ObjectRefRequired (ec, loc, mexp.Name);
7023                                                         return null;
7024                                                 }
7025                                         }
7026
7027                                         if ((mg != null) && IdenticalNameAndTypeName (ec, left_original, left, loc))
7028                                                 mg.IdenticalTypeName = true;
7029
7030                                         me.InstanceExpression = left;
7031                                 }
7032
7033                                 return member_lookup;
7034                         }
7035
7036                         Console.WriteLine ("Left is: " + left);
7037                         Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet");
7038                         Environment.Exit (1);
7039                         return null;
7040                 }
7041                 
7042                 public Expression DoResolve (EmitContext ec, Expression right_side, ResolveFlags flags)
7043                 {
7044                         if (type != null)
7045                                 throw new Exception ();
7046
7047                         //
7048                         // Resolve the expression with flow analysis turned off, we'll do the definite
7049                         // assignment checks later.  This is because we don't know yet what the expression
7050                         // will resolve to - it may resolve to a FieldExpr and in this case we must do the
7051                         // definite assignment check on the actual field and not on the whole struct.
7052                         //
7053
7054                         Expression original = expr;
7055                         expr = expr.Resolve (ec, flags | ResolveFlags.Intermediate | ResolveFlags.DisableFlowAnalysis);
7056                         if (expr == null)
7057                                 return null;
7058
7059                         if (expr is SimpleName){
7060                                 SimpleName child_expr = (SimpleName) expr;
7061
7062                                 Expression new_expr = new SimpleName (child_expr.Name, Identifier, loc);
7063
7064                                 return new_expr.Resolve (ec, flags);
7065                         }
7066                                         
7067                         //
7068                         // TODO: I mailed Ravi about this, and apparently we can get rid
7069                         // of this and put it in the right place.
7070                         // 
7071                         // Handle enums here when they are in transit.
7072                         // Note that we cannot afford to hit MemberLookup in this case because
7073                         // it will fail to find any members at all
7074                         //
7075
7076                         Type expr_type = expr.Type;
7077                         if (expr is TypeExpr){
7078                                 if (!ec.DeclSpace.CheckAccessLevel (expr_type)){
7079                                         Report.Error_T (122, loc, expr_type);
7080                                         return null;
7081                                 }
7082
7083                                 if (expr_type == TypeManager.enum_type || expr_type.IsSubclassOf (TypeManager.enum_type)){
7084                                         Enum en = TypeManager.LookupEnum (expr_type);
7085
7086                                         if (en != null) {
7087                                                 object value = en.LookupEnumValue (ec, Identifier, loc);
7088                                                 
7089                                                 if (value != null){
7090                                                         ObsoleteAttribute oa = en.GetObsoleteAttribute (ec, Identifier);
7091                                                         if (oa != null) {
7092                                                                 AttributeTester.Report_ObsoleteMessage (oa, en.GetSignatureForError (), Location);
7093                                                         }
7094
7095                                                         Constant c = Constantify (value, en.UnderlyingType);
7096                                                         return new EnumConstant (c, expr_type);
7097                                                 }
7098                                         } else {
7099                                                 CheckObsoleteAttribute (expr_type);
7100
7101                                                 FieldInfo fi = expr_type.GetField (Identifier);
7102                                                 if (fi != null) {
7103                                                         ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (fi);
7104                                                         if (oa != null)
7105                                                                 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (fi), Location);
7106                                                 }
7107                                         }
7108                                 }
7109                         }
7110                         
7111                         if (expr_type.IsPointer){
7112                                 Error (23, "The `.' operator can not be applied to pointer operands (" +
7113                                        TypeManager.CSharpName (expr_type) + ")");
7114                                 return null;
7115                         }
7116
7117                         Expression member_lookup;
7118                         member_lookup = MemberLookupFinal (ec, expr_type, expr_type, Identifier, loc);
7119                         if (member_lookup == null)
7120                                 return null;
7121
7122                         if (member_lookup is TypeExpr) {
7123                                 if (!(expr is TypeExpr) && !(expr is SimpleName)) {
7124                                         Error (572, "Can't reference type `" + Identifier + "' through an expression; try `" +
7125                                                member_lookup.Type + "' instead");
7126                                         return null;
7127                                 }
7128
7129                                 return member_lookup;
7130                         }
7131                         
7132                         member_lookup = ResolveMemberAccess (ec, member_lookup, expr, loc, original);
7133                         if (member_lookup == null)
7134                                 return null;
7135
7136                         // The following DoResolve/DoResolveLValue will do the definite assignment
7137                         // check.
7138
7139                         if (right_side != null)
7140                                 member_lookup = member_lookup.DoResolveLValue (ec, right_side);
7141                         else
7142                                 member_lookup = member_lookup.DoResolve (ec);
7143
7144                         return member_lookup;
7145                 }
7146
7147                 public override Expression DoResolve (EmitContext ec)
7148                 {
7149                         return DoResolve (ec, null, ResolveFlags.VariableOrValue |
7150                                           ResolveFlags.SimpleName | ResolveFlags.Type);
7151                 }
7152
7153                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
7154                 {
7155                         return DoResolve (ec, right_side, ResolveFlags.VariableOrValue |
7156                                           ResolveFlags.SimpleName | ResolveFlags.Type);
7157                 }
7158
7159                 public override Expression ResolveAsTypeStep (EmitContext ec)
7160                 {
7161                         string fname = null;
7162                         MemberAccess full_expr = this;
7163                         while (full_expr != null) {
7164                                 if (fname != null)
7165                                         fname = String.Concat (full_expr.Identifier, ".", fname);
7166                                 else
7167                                         fname = full_expr.Identifier;
7168
7169                                 if (full_expr.Expr is SimpleName) {
7170                                         string full_name = String.Concat (((SimpleName) full_expr.Expr).Name, ".", fname);
7171                                         Type fully_qualified = ec.DeclSpace.FindType (loc, full_name);
7172                                         if (fully_qualified != null)
7173                                                 return new TypeExpression (fully_qualified, loc);
7174                                 }
7175
7176                                 full_expr = full_expr.Expr as MemberAccess;
7177                         }
7178
7179                         Expression new_expr = expr.ResolveAsTypeStep (ec);
7180
7181                         if (new_expr == null)
7182                                 return null;
7183
7184                         if (new_expr is SimpleName){
7185                                 SimpleName child_expr = (SimpleName) new_expr;
7186                                 
7187                                 new_expr = new SimpleName (child_expr.Name, Identifier, loc);
7188
7189                                 return new_expr.ResolveAsTypeStep (ec);
7190                         }
7191
7192                         Type expr_type = new_expr.Type;
7193                       
7194                         if (expr_type.IsPointer){
7195                                 Error (23, "The `.' operator can not be applied to pointer operands (" +
7196                                        TypeManager.CSharpName (expr_type) + ")");
7197                                 return null;
7198                         }
7199                         
7200                         Expression member_lookup;
7201                         member_lookup = MemberLookupFinal (ec, expr_type, expr_type, Identifier, loc);
7202                         if (member_lookup == null)
7203                                 return null;
7204
7205                         if (member_lookup is TypeExpr){
7206                                 member_lookup.Resolve (ec, ResolveFlags.Type);
7207                                 return member_lookup;
7208                         } 
7209
7210                         return null;                    
7211                 }
7212
7213                 public override void Emit (EmitContext ec)
7214                 {
7215                         throw new Exception ("Should not happen");
7216                 }
7217
7218                 public override string ToString ()
7219                 {
7220                         return expr + "." + Identifier;
7221                 }
7222         }
7223
7224         /// <summary>
7225         ///   Implements checked expressions
7226         /// </summary>
7227         public class CheckedExpr : Expression {
7228
7229                 public Expression Expr;
7230
7231                 public CheckedExpr (Expression e, Location l)
7232                 {
7233                         Expr = e;
7234                         loc = l;
7235                 }
7236
7237                 public override Expression DoResolve (EmitContext ec)
7238                 {
7239                         bool last_check = ec.CheckState;
7240                         bool last_const_check = ec.ConstantCheckState;
7241
7242                         ec.CheckState = true;
7243                         ec.ConstantCheckState = true;
7244                         Expr = Expr.Resolve (ec);
7245                         ec.CheckState = last_check;
7246                         ec.ConstantCheckState = last_const_check;
7247                         
7248                         if (Expr == null)
7249                                 return null;
7250
7251                         if (Expr is Constant)
7252                                 return Expr;
7253                         
7254                         eclass = Expr.eclass;
7255                         type = Expr.Type;
7256                         return this;
7257                 }
7258
7259                 public override void Emit (EmitContext ec)
7260                 {
7261                         bool last_check = ec.CheckState;
7262                         bool last_const_check = ec.ConstantCheckState;
7263                         
7264                         ec.CheckState = true;
7265                         ec.ConstantCheckState = true;
7266                         Expr.Emit (ec);
7267                         ec.CheckState = last_check;
7268                         ec.ConstantCheckState = last_const_check;
7269                 }
7270                 
7271         }
7272
7273         /// <summary>
7274         ///   Implements the unchecked expression
7275         /// </summary>
7276         public class UnCheckedExpr : Expression {
7277
7278                 public Expression Expr;
7279
7280                 public UnCheckedExpr (Expression e, Location l)
7281                 {
7282                         Expr = e;
7283                         loc = l;
7284                 }
7285
7286                 public override Expression DoResolve (EmitContext ec)
7287                 {
7288                         bool last_check = ec.CheckState;
7289                         bool last_const_check = ec.ConstantCheckState;
7290
7291                         ec.CheckState = false;
7292                         ec.ConstantCheckState = false;
7293                         Expr = Expr.Resolve (ec);
7294                         ec.CheckState = last_check;
7295                         ec.ConstantCheckState = last_const_check;
7296
7297                         if (Expr == null)
7298                                 return null;
7299
7300                         if (Expr is Constant)
7301                                 return Expr;
7302                         
7303                         eclass = Expr.eclass;
7304                         type = Expr.Type;
7305                         return this;
7306                 }
7307
7308                 public override void Emit (EmitContext ec)
7309                 {
7310                         bool last_check = ec.CheckState;
7311                         bool last_const_check = ec.ConstantCheckState;
7312                         
7313                         ec.CheckState = false;
7314                         ec.ConstantCheckState = false;
7315                         Expr.Emit (ec);
7316                         ec.CheckState = last_check;
7317                         ec.ConstantCheckState = last_const_check;
7318                 }
7319                 
7320         }
7321
7322         /// <summary>
7323         ///   An Element Access expression.
7324         ///
7325         ///   During semantic analysis these are transformed into 
7326         ///   IndexerAccess, ArrayAccess or a PointerArithmetic.
7327         /// </summary>
7328         public class ElementAccess : Expression {
7329                 public ArrayList  Arguments;
7330                 public Expression Expr;
7331                 
7332                 public ElementAccess (Expression e, ArrayList e_list, Location l)
7333                 {
7334                         Expr = e;
7335
7336                         loc  = l;
7337                         
7338                         if (e_list == null)
7339                                 return;
7340                         
7341                         Arguments = new ArrayList ();
7342                         foreach (Expression tmp in e_list)
7343                                 Arguments.Add (new Argument (tmp, Argument.AType.Expression));
7344                         
7345                 }
7346
7347                 bool CommonResolve (EmitContext ec)
7348                 {
7349                         Expr = Expr.Resolve (ec);
7350
7351                         if (Expr == null) 
7352                                 return false;
7353
7354                         if (Arguments == null)
7355                                 return false;
7356
7357                         foreach (Argument a in Arguments){
7358                                 if (!a.Resolve (ec, loc))
7359                                         return false;
7360                         }
7361
7362                         return true;
7363                 }
7364
7365                 Expression MakePointerAccess (EmitContext ec)
7366                 {
7367                         Type t = Expr.Type;
7368
7369                         if (t == TypeManager.void_ptr_type){
7370                                 Error (242, "The array index operation is not valid for void pointers");
7371                                 return null;
7372                         }
7373                         if (Arguments.Count != 1){
7374                                 Error (196, "A pointer must be indexed by a single value");
7375                                 return null;
7376                         }
7377                         Expression p;
7378
7379                         p = new PointerArithmetic (true, Expr, ((Argument)Arguments [0]).Expr, t, loc).Resolve (ec);
7380                         if (p == null)
7381                                 return null;
7382                         return new Indirection (p, loc).Resolve (ec);
7383                 }
7384                 
7385                 public override Expression DoResolve (EmitContext ec)
7386                 {
7387                         if (!CommonResolve (ec))
7388                                 return null;
7389
7390                         //
7391                         // We perform some simple tests, and then to "split" the emit and store
7392                         // code we create an instance of a different class, and return that.
7393                         //
7394                         // I am experimenting with this pattern.
7395                         //
7396                         Type t = Expr.Type;
7397
7398                         if (t == TypeManager.array_type){
7399                                 Report.Error (21, loc, "Cannot use indexer on System.Array");
7400                                 return null;
7401                         }
7402                         
7403                         if (t.IsArray)
7404                                 return (new ArrayAccess (this, loc)).Resolve (ec);
7405                         else if (t.IsPointer)
7406                                 return MakePointerAccess (ec);
7407                         else
7408                                 return (new IndexerAccess (this, loc)).Resolve (ec);
7409                 }
7410
7411                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
7412                 {
7413                         if (!CommonResolve (ec))
7414                                 return null;
7415
7416                         Type t = Expr.Type;
7417                         if (t.IsArray)
7418                                 return (new ArrayAccess (this, loc)).ResolveLValue (ec, right_side);
7419                         else if (t.IsPointer)
7420                                 return MakePointerAccess (ec);
7421                         else
7422                                 return (new IndexerAccess (this, loc)).ResolveLValue (ec, right_side);
7423                 }
7424                 
7425                 public override void Emit (EmitContext ec)
7426                 {
7427                         throw new Exception ("Should never be reached");
7428                 }
7429         }
7430
7431         /// <summary>
7432         ///   Implements array access 
7433         /// </summary>
7434         public class ArrayAccess : Expression, IAssignMethod, IMemoryLocation {
7435                 //
7436                 // Points to our "data" repository
7437                 //
7438                 ElementAccess ea;
7439
7440                 LocalTemporary [] cached_locations;
7441                 
7442                 public ArrayAccess (ElementAccess ea_data, Location l)
7443                 {
7444                         ea = ea_data;
7445                         eclass = ExprClass.Variable;
7446                         loc = l;
7447                 }
7448
7449                 public override Expression DoResolve (EmitContext ec)
7450                 {
7451 #if false
7452                         ExprClass eclass = ea.Expr.eclass;
7453
7454                         // As long as the type is valid
7455                         if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
7456                               eclass == ExprClass.Value)) {
7457                                 ea.Expr.Error_UnexpectedKind ("variable or value");
7458                                 return null;
7459                         }
7460 #endif
7461
7462                         Type t = ea.Expr.Type;
7463                         if (t.GetArrayRank () != ea.Arguments.Count){
7464                                 ea.Error (22,
7465                                           "Incorrect number of indexes for array " +
7466                                           " expected: " + t.GetArrayRank () + " got: " +
7467                                           ea.Arguments.Count);
7468                                 return null;
7469                         }
7470
7471                         type = TypeManager.GetElementType (t);
7472                         if (type.IsPointer && !ec.InUnsafe){
7473                                 UnsafeError (ea.Location);
7474                                 return null;
7475                         }
7476
7477                         foreach (Argument a in ea.Arguments){
7478                                 Type argtype = a.Type;
7479
7480                                 if (argtype == TypeManager.int32_type ||
7481                                     argtype == TypeManager.uint32_type ||
7482                                     argtype == TypeManager.int64_type ||
7483                                     argtype == TypeManager.uint64_type)
7484                                         continue;
7485
7486                                 //
7487                                 // Mhm.  This is strage, because the Argument.Type is not the same as
7488                                 // Argument.Expr.Type: the value changes depending on the ref/out setting.
7489                                 //
7490                                 // Wonder if I will run into trouble for this.
7491                                 //
7492                                 a.Expr = ExpressionToArrayArgument (ec, a.Expr, ea.Location);
7493                                 if (a.Expr == null)
7494                                         return null;
7495                         }
7496                         
7497                         eclass = ExprClass.Variable;
7498
7499                         return this;
7500                 }
7501
7502                 /// <summary>
7503                 ///    Emits the right opcode to load an object of Type `t'
7504                 ///    from an array of T
7505                 /// </summary>
7506                 static public void EmitLoadOpcode (ILGenerator ig, Type type)
7507                 {
7508                         if (type == TypeManager.byte_type || type == TypeManager.bool_type)
7509                                 ig.Emit (OpCodes.Ldelem_U1);
7510                         else if (type == TypeManager.sbyte_type)
7511                                 ig.Emit (OpCodes.Ldelem_I1);
7512                         else if (type == TypeManager.short_type)
7513                                 ig.Emit (OpCodes.Ldelem_I2);
7514                         else if (type == TypeManager.ushort_type || type == TypeManager.char_type)
7515                                 ig.Emit (OpCodes.Ldelem_U2);
7516                         else if (type == TypeManager.int32_type)
7517                                 ig.Emit (OpCodes.Ldelem_I4);
7518                         else if (type == TypeManager.uint32_type)
7519                                 ig.Emit (OpCodes.Ldelem_U4);
7520                         else if (type == TypeManager.uint64_type)
7521                                 ig.Emit (OpCodes.Ldelem_I8);
7522                         else if (type == TypeManager.int64_type)
7523                                 ig.Emit (OpCodes.Ldelem_I8);
7524                         else if (type == TypeManager.float_type)
7525                                 ig.Emit (OpCodes.Ldelem_R4);
7526                         else if (type == TypeManager.double_type)
7527                                 ig.Emit (OpCodes.Ldelem_R8);
7528                         else if (type == TypeManager.intptr_type)
7529                                 ig.Emit (OpCodes.Ldelem_I);
7530                         else if (TypeManager.IsEnumType (type)){
7531                                 EmitLoadOpcode (ig, TypeManager.EnumToUnderlying (type));
7532                         } else if (type.IsValueType){
7533                                 ig.Emit (OpCodes.Ldelema, type);
7534                                 ig.Emit (OpCodes.Ldobj, type);
7535                         } else 
7536                                 ig.Emit (OpCodes.Ldelem_Ref);
7537                 }
7538
7539                 /// <summary>
7540                 ///    Emits the right opcode to store an object of Type `t'
7541                 ///    from an array of T.  
7542                 /// </summary>
7543                 static public void EmitStoreOpcode (ILGenerator ig, Type t)
7544                 {
7545                         bool is_stobj;
7546                         OpCode op = GetStoreOpcode (t, out is_stobj);
7547                         if (is_stobj)
7548                                 ig.Emit (OpCodes.Stobj, t);
7549                         else
7550                                 ig.Emit (op);
7551                 }
7552
7553                 /// <summary>
7554                 ///    Returns the right opcode to store an object of Type `t'
7555                 ///    from an array of T.  
7556                 /// </summary>
7557                 static public OpCode GetStoreOpcode (Type t, out bool is_stobj)
7558                 {
7559                         //Console.WriteLine (new System.Diagnostics.StackTrace ());
7560                         is_stobj = false;
7561                         t = TypeManager.TypeToCoreType (t);
7562                         if (TypeManager.IsEnumType (t))
7563                                 t = TypeManager.EnumToUnderlying (t);
7564                         if (t == TypeManager.byte_type || t == TypeManager.sbyte_type ||
7565                             t == TypeManager.bool_type)
7566                                 return OpCodes.Stelem_I1;
7567                         else if (t == TypeManager.short_type || t == TypeManager.ushort_type ||
7568                                  t == TypeManager.char_type)
7569                                 return OpCodes.Stelem_I2;
7570                         else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
7571                                 return OpCodes.Stelem_I4;
7572                         else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
7573                                 return OpCodes.Stelem_I8;
7574                         else if (t == TypeManager.float_type)
7575                                 return OpCodes.Stelem_R4;
7576                         else if (t == TypeManager.double_type)
7577                                 return OpCodes.Stelem_R8;
7578                         else if (t == TypeManager.intptr_type) {
7579                                 is_stobj = true;
7580                                 return OpCodes.Stobj;
7581                         } else if (t.IsValueType) {
7582                                 is_stobj = true;
7583                                 return OpCodes.Stobj;
7584                         } else
7585                                 return OpCodes.Stelem_Ref;
7586                 }
7587
7588                 MethodInfo FetchGetMethod ()
7589                 {
7590                         ModuleBuilder mb = CodeGen.Module.Builder;
7591                         int arg_count = ea.Arguments.Count;
7592                         Type [] args = new Type [arg_count];
7593                         MethodInfo get;
7594                         
7595                         for (int i = 0; i < arg_count; i++){
7596                                 //args [i++] = a.Type;
7597                                 args [i] = TypeManager.int32_type;
7598                         }
7599                         
7600                         get = mb.GetArrayMethod (
7601                                 ea.Expr.Type, "Get",
7602                                 CallingConventions.HasThis |
7603                                 CallingConventions.Standard,
7604                                 type, args);
7605                         return get;
7606                 }
7607                                 
7608
7609                 MethodInfo FetchAddressMethod ()
7610                 {
7611                         ModuleBuilder mb = CodeGen.Module.Builder;
7612                         int arg_count = ea.Arguments.Count;
7613                         Type [] args = new Type [arg_count];
7614                         MethodInfo address;
7615                         Type ret_type;
7616                         
7617                         ret_type = TypeManager.GetReferenceType (type);
7618                         
7619                         for (int i = 0; i < arg_count; i++){
7620                                 //args [i++] = a.Type;
7621                                 args [i] = TypeManager.int32_type;
7622                         }
7623                         
7624                         address = mb.GetArrayMethod (
7625                                 ea.Expr.Type, "Address",
7626                                 CallingConventions.HasThis |
7627                                 CallingConventions.Standard,
7628                                 ret_type, args);
7629
7630                         return address;
7631                 }
7632
7633                 //
7634                 // Load the array arguments into the stack.
7635                 //
7636                 // If we have been requested to cache the values (cached_locations array
7637                 // initialized), then load the arguments the first time and store them
7638                 // in locals.  otherwise load from local variables.
7639                 //
7640                 void LoadArrayAndArguments (EmitContext ec)
7641                 {
7642                         ILGenerator ig = ec.ig;
7643                         
7644                         if (cached_locations == null){
7645                                 ea.Expr.Emit (ec);
7646                                 foreach (Argument a in ea.Arguments){
7647                                         Type argtype = a.Expr.Type;
7648                                         
7649                                         a.Expr.Emit (ec);
7650                                         
7651                                         if (argtype == TypeManager.int64_type)
7652                                                 ig.Emit (OpCodes.Conv_Ovf_I);
7653                                         else if (argtype == TypeManager.uint64_type)
7654                                                 ig.Emit (OpCodes.Conv_Ovf_I_Un);
7655                                 }
7656                                 return;
7657                         }
7658
7659                         if (cached_locations [0] == null){
7660                                 cached_locations [0] = new LocalTemporary (ec, ea.Expr.Type);
7661                                 ea.Expr.Emit (ec);
7662                                 ig.Emit (OpCodes.Dup);
7663                                 cached_locations [0].Store (ec);
7664                                 
7665                                 int j = 1;
7666                                 
7667                                 foreach (Argument a in ea.Arguments){
7668                                         Type argtype = a.Expr.Type;
7669                                         
7670                                         cached_locations [j] = new LocalTemporary (ec, TypeManager.intptr_type /* a.Expr.Type */);
7671                                         a.Expr.Emit (ec);
7672                                         if (argtype == TypeManager.int64_type)
7673                                                 ig.Emit (OpCodes.Conv_Ovf_I);
7674                                         else if (argtype == TypeManager.uint64_type)
7675                                                 ig.Emit (OpCodes.Conv_Ovf_I_Un);
7676
7677                                         ig.Emit (OpCodes.Dup);
7678                                         cached_locations [j].Store (ec);
7679                                         j++;
7680                                 }
7681                                 return;
7682                         }
7683
7684                         foreach (LocalTemporary lt in cached_locations)
7685                                 lt.Emit (ec);
7686                 }
7687
7688                 public new void CacheTemporaries (EmitContext ec)
7689                 {
7690                         cached_locations = new LocalTemporary [ea.Arguments.Count + 1];
7691                 }
7692                 
7693                 public override void Emit (EmitContext ec)
7694                 {
7695                         int rank = ea.Expr.Type.GetArrayRank ();
7696                         ILGenerator ig = ec.ig;
7697
7698                         LoadArrayAndArguments (ec);
7699                         
7700                         if (rank == 1)
7701                                 EmitLoadOpcode (ig, type);
7702                         else {
7703                                 MethodInfo method;
7704                                 
7705                                 method = FetchGetMethod ();
7706                                 ig.Emit (OpCodes.Call, method);
7707                         }
7708                 }
7709
7710                 public void EmitAssign (EmitContext ec, Expression source)
7711                 {
7712                         int rank = ea.Expr.Type.GetArrayRank ();
7713                         ILGenerator ig = ec.ig;
7714                         Type t = source.Type;
7715
7716                         LoadArrayAndArguments (ec);
7717
7718                         //
7719                         // The stobj opcode used by value types will need
7720                         // an address on the stack, not really an array/array
7721                         // pair
7722                         //
7723                         if (rank == 1){
7724                                 if (t == TypeManager.enum_type || t == TypeManager.decimal_type ||
7725                                     (t.IsSubclassOf (TypeManager.value_type) && !TypeManager.IsEnumType (t) && !TypeManager.IsBuiltinType (t)))
7726                                         ig.Emit (OpCodes.Ldelema, t);
7727                         }
7728                         
7729                         source.Emit (ec);
7730
7731                         if (rank == 1)
7732                                 EmitStoreOpcode (ig, t);
7733                         else {
7734                                 ModuleBuilder mb = CodeGen.Module.Builder;
7735                                 int arg_count = ea.Arguments.Count;
7736                                 Type [] args = new Type [arg_count + 1];
7737                                 MethodInfo set;
7738                                 
7739                                 for (int i = 0; i < arg_count; i++){
7740                                         //args [i++] = a.Type;
7741                                         args [i] = TypeManager.int32_type;
7742                                 }
7743
7744                                 args [arg_count] = type;
7745                                 
7746                                 set = mb.GetArrayMethod (
7747                                         ea.Expr.Type, "Set",
7748                                         CallingConventions.HasThis |
7749                                         CallingConventions.Standard,
7750                                         TypeManager.void_type, args);
7751                                 
7752                                 ig.Emit (OpCodes.Call, set);
7753                         }
7754                 }
7755
7756                 public void AddressOf (EmitContext ec, AddressOp mode)
7757                 {
7758                         int rank = ea.Expr.Type.GetArrayRank ();
7759                         ILGenerator ig = ec.ig;
7760
7761                         LoadArrayAndArguments (ec);
7762
7763                         if (rank == 1){
7764                                 ig.Emit (OpCodes.Ldelema, type);
7765                         } else {
7766                                 MethodInfo address = FetchAddressMethod ();
7767                                 ig.Emit (OpCodes.Call, address);
7768                         }
7769                 }
7770         }
7771
7772         
7773         class Indexers {
7774                 public ArrayList Properties;
7775                 static Hashtable map;
7776
7777                 public struct Indexer {
7778                         public readonly Type Type;
7779                         public readonly MethodInfo Getter, Setter;
7780
7781                         public Indexer (Type type, MethodInfo get, MethodInfo set)
7782                         {
7783                                 this.Type = type;
7784                                 this.Getter = get;
7785                                 this.Setter = set;
7786                         }
7787                 }
7788
7789                 static Indexers ()
7790                 {
7791                         map = new Hashtable ();
7792                 }
7793
7794                 Indexers ()
7795                 {
7796                         Properties = new ArrayList ();
7797                 }
7798                                 
7799                 void Append (MemberInfo [] mi)
7800                 {
7801                         foreach (PropertyInfo property in mi){
7802                                 MethodInfo get, set;
7803                                 
7804                                 get = property.GetGetMethod (true);
7805                                 set = property.GetSetMethod (true);
7806                                 Properties.Add (new Indexer (property.PropertyType, get, set));
7807                         }
7808                 }
7809
7810                 static private MemberInfo [] GetIndexersForTypeOrInterface (Type caller_type, Type lookup_type)
7811                 {
7812                         string p_name = TypeManager.IndexerPropertyName (lookup_type);
7813
7814                         MemberInfo [] mi = TypeManager.MemberLookup (
7815                                 caller_type, caller_type, lookup_type, MemberTypes.Property,
7816                                 BindingFlags.Public | BindingFlags.Instance |
7817                                 BindingFlags.DeclaredOnly, p_name, null);
7818
7819                         if (mi == null || mi.Length == 0)
7820                                 return null;
7821
7822                         return mi;
7823                 }
7824                 
7825                 static public Indexers GetIndexersForType (Type caller_type, Type lookup_type, Location loc) 
7826                 {
7827                         Indexers ix = (Indexers) map [lookup_type];
7828
7829                         if (ix != null)
7830                                 return ix;
7831
7832                         Type copy = lookup_type;
7833                         while (copy != TypeManager.object_type && copy != null){
7834                                 MemberInfo [] mi = GetIndexersForTypeOrInterface (caller_type, copy);
7835
7836                                 if (mi != null){
7837                                         if (ix == null)
7838                                                 ix = new Indexers ();
7839
7840                                         ix.Append (mi);
7841                                 }
7842                                         
7843                                 copy = copy.BaseType;
7844                         }
7845
7846                         if (!lookup_type.IsInterface)
7847                                 return ix;
7848
7849                         TypeExpr [] ifaces = TypeManager.GetInterfaces (lookup_type);
7850                         if (ifaces != null) {
7851                                 foreach (TypeExpr iface in ifaces) {
7852                                         Type itype = iface.Type;
7853                                         MemberInfo [] mi = GetIndexersForTypeOrInterface (caller_type, itype);
7854                                         if (mi != null){
7855                                                 if (ix == null)
7856                                                         ix = new Indexers ();
7857                                         
7858                                                 ix.Append (mi);
7859                                         }
7860                                 }
7861                         }
7862
7863                         return ix;
7864                 }
7865         }
7866
7867         /// <summary>
7868         ///   Expressions that represent an indexer call.
7869         /// </summary>
7870         public class IndexerAccess : Expression, IAssignMethod {
7871                 //
7872                 // Points to our "data" repository
7873                 //
7874                 MethodInfo get, set;
7875                 ArrayList set_arguments;
7876                 bool is_base_indexer;
7877
7878                 protected Type indexer_type;
7879                 protected Type current_type;
7880                 protected Expression instance_expr;
7881                 protected ArrayList arguments;
7882                 
7883                 public IndexerAccess (ElementAccess ea, Location loc)
7884                         : this (ea.Expr, false, loc)
7885                 {
7886                         this.arguments = ea.Arguments;
7887                 }
7888
7889                 protected IndexerAccess (Expression instance_expr, bool is_base_indexer,
7890                                          Location loc)
7891                 {
7892                         this.instance_expr = instance_expr;
7893                         this.is_base_indexer = is_base_indexer;
7894                         this.eclass = ExprClass.Value;
7895                         this.loc = loc;
7896                 }
7897
7898                 protected virtual bool CommonResolve (EmitContext ec)
7899                 {
7900                         indexer_type = instance_expr.Type;
7901                         current_type = ec.ContainerType;
7902
7903                         return true;
7904                 }
7905
7906                 public override Expression DoResolve (EmitContext ec)
7907                 {
7908                         ArrayList AllGetters = new ArrayList();
7909                         if (!CommonResolve (ec))
7910                                 return null;
7911
7912                         //
7913                         // Step 1: Query for all `Item' *properties*.  Notice
7914                         // that the actual methods are pointed from here.
7915                         //
7916                         // This is a group of properties, piles of them.  
7917
7918                         bool found_any = false, found_any_getters = false;
7919                         Type lookup_type = indexer_type;
7920
7921                         Indexers ilist;
7922                         ilist = Indexers.GetIndexersForType (current_type, lookup_type, loc);
7923                         if (ilist != null) {
7924                                 found_any = true;
7925                                 if (ilist.Properties != null) {
7926                                         foreach (Indexers.Indexer ix in ilist.Properties) {
7927                                                 if (ix.Getter != null)
7928                                                         AllGetters.Add(ix.Getter);
7929                                         }
7930                                 }
7931                         }
7932
7933                         if (AllGetters.Count > 0) {
7934                                 found_any_getters = true;
7935                                 get = (MethodInfo) Invocation.OverloadResolve (
7936                                         ec, new MethodGroupExpr (AllGetters, loc), arguments, loc);
7937                         }
7938
7939                         if (!found_any) {
7940                                 Report.Error (21, loc,
7941                                               "Type `" + TypeManager.CSharpName (indexer_type) +
7942                                               "' does not have any indexers defined");
7943                                 return null;
7944                         }
7945
7946                         if (!found_any_getters) {
7947                                 Error (154, "indexer can not be used in this context, because " +
7948                                        "it lacks a `get' accessor");
7949                                 return null;
7950                         }
7951
7952                         if (get == null) {
7953                                 Error (1501, "No Overload for method `this' takes `" +
7954                                        arguments.Count + "' arguments");
7955                                 return null;
7956                         }
7957
7958                         //
7959                         // Only base will allow this invocation to happen.
7960                         //
7961                         if (get.IsAbstract && this is BaseIndexerAccess){
7962                                 Report.Error (205, loc, "Cannot call an abstract base indexer: " + Invocation.FullMethodDesc (get));
7963                                 return null;
7964                         }
7965
7966                         type = get.ReturnType;
7967                         if (type.IsPointer && !ec.InUnsafe){
7968                                 UnsafeError (loc);
7969                                 return null;
7970                         }
7971                         
7972                         eclass = ExprClass.IndexerAccess;
7973                         return this;
7974                 }
7975
7976                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
7977                 {
7978                         ArrayList AllSetters = new ArrayList();
7979                         if (!CommonResolve (ec))
7980                                 return null;
7981
7982                         bool found_any = false, found_any_setters = false;
7983
7984                         Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type, loc);
7985                         if (ilist != null) {
7986                                 found_any = true;
7987                                 if (ilist.Properties != null) {
7988                                         foreach (Indexers.Indexer ix in ilist.Properties) {
7989                                                 if (ix.Setter != null)
7990                                                         AllSetters.Add(ix.Setter);
7991                                         }
7992                                 }
7993                         }
7994                         if (AllSetters.Count > 0) {
7995                                 found_any_setters = true;
7996                                 set_arguments = (ArrayList) arguments.Clone ();
7997                                 set_arguments.Add (new Argument (right_side, Argument.AType.Expression));
7998                                 set = (MethodInfo) Invocation.OverloadResolve (
7999                                         ec, new MethodGroupExpr (AllSetters, loc),
8000                                         set_arguments, loc);
8001                         }
8002
8003                         if (!found_any) {
8004                                 Report.Error (21, loc,
8005                                               "Type `" + TypeManager.CSharpName (indexer_type) +
8006                                               "' does not have any indexers defined");
8007                                 return null;
8008                         }
8009
8010                         if (!found_any_setters) {
8011                                 Error (154, "indexer can not be used in this context, because " +
8012                                        "it lacks a `set' accessor");
8013                                 return null;
8014                         }
8015
8016                         if (set == null) {
8017                                 Error (1501, "No Overload for method `this' takes `" +
8018                                        arguments.Count + "' arguments");
8019                                 return null;
8020                         }
8021
8022                         //
8023                         // Only base will allow this invocation to happen.
8024                         //
8025                         if (set.IsAbstract && this is BaseIndexerAccess){
8026                                 Report.Error (205, loc, "Cannot call an abstract base indexer: " + Invocation.FullMethodDesc (set));
8027                                 return null;
8028                         }
8029
8030                         //
8031                         // Now look for the actual match in the list of indexers to set our "return" type
8032                         //
8033                         type = TypeManager.void_type;   // default value
8034                         foreach (Indexers.Indexer ix in ilist.Properties){
8035                                 if (ix.Setter == set){
8036                                         type = ix.Type;
8037                                         break;
8038                                 }
8039                         }
8040                         
8041                         eclass = ExprClass.IndexerAccess;
8042                         return this;
8043                 }
8044                 
8045                 public override void Emit (EmitContext ec)
8046                 {
8047                         Invocation.EmitCall (ec, is_base_indexer, false, instance_expr, get, arguments, loc);
8048                 }
8049
8050                 //
8051                 // source is ignored, because we already have a copy of it from the
8052                 // LValue resolution and we have already constructed a pre-cached
8053                 // version of the arguments (ea.set_arguments);
8054                 //
8055                 public void EmitAssign (EmitContext ec, Expression source)
8056                 {
8057                         Invocation.EmitCall (ec, is_base_indexer, false, instance_expr, set, set_arguments, loc);
8058                 }
8059         }
8060
8061         /// <summary>
8062         ///   The base operator for method names
8063         /// </summary>
8064         public class BaseAccess : Expression {
8065                 string member;
8066                 
8067                 public BaseAccess (string member, Location l)
8068                 {
8069                         this.member = member;
8070                         loc = l;
8071                 }
8072
8073                 public override Expression DoResolve (EmitContext ec)
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.Resolve (ec);
8085                         return c;
8086                 }
8087
8088                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
8089                 {
8090                         Expression c = CommonResolve (ec);
8091
8092                         if (c == null)
8093                                 return null;
8094
8095                         //
8096                         // MethodGroups use this opportunity to flag an error on lacking ()
8097                         //
8098                         if (! (c is MethodGroupExpr))
8099                                 return c.DoResolveLValue (ec, right_side);
8100
8101                         return c;
8102                 }
8103
8104                 Expression CommonResolve (EmitContext ec)
8105                 {
8106                         Expression member_lookup;
8107                         Type current_type = ec.ContainerType;
8108                         Type base_type = current_type.BaseType;
8109                         Expression e;
8110
8111                         if (ec.IsStatic){
8112                                 Error (1511, "Keyword base is not allowed in static method");
8113                                 return null;
8114                         }
8115
8116                         if (ec.IsFieldInitializer){
8117                                 Error (1512, "Keyword base is not available in the current context");
8118                                 return null;
8119                         }
8120                         
8121                         member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type, member,
8122                                                       AllMemberTypes, AllBindingFlags, loc);
8123                         if (member_lookup == null) {
8124                                 MemberLookupFailed (ec, base_type, base_type, member, null, loc);
8125                                 return null;
8126                         }
8127
8128                         Expression left;
8129                         
8130                         if (ec.IsStatic)
8131                                 left = new TypeExpression (base_type, loc);
8132                         else
8133                                 left = ec.GetThis (loc);
8134                         
8135                         e = MemberAccess.ResolveMemberAccess (ec, member_lookup, left, loc, null);
8136
8137                         if (e is PropertyExpr){
8138                                 PropertyExpr pe = (PropertyExpr) e;
8139
8140                                 pe.IsBase = true;
8141                         }
8142                         
8143                         if (e is MethodGroupExpr)
8144                                 ((MethodGroupExpr) e).IsBase = true;
8145
8146                         return e;
8147                 }
8148
8149                 public override void Emit (EmitContext ec)
8150                 {
8151                         throw new Exception ("Should never be called"); 
8152                 }
8153         }
8154
8155         /// <summary>
8156         ///   The base indexer operator
8157         /// </summary>
8158         public class BaseIndexerAccess : IndexerAccess {
8159                 public BaseIndexerAccess (ArrayList args, Location loc)
8160                         : base (null, true, loc)
8161                 {
8162                         arguments = new ArrayList ();
8163                         foreach (Expression tmp in args)
8164                                 arguments.Add (new Argument (tmp, Argument.AType.Expression));
8165                 }
8166
8167                 protected override bool CommonResolve (EmitContext ec)
8168                 {
8169                         instance_expr = ec.GetThis (loc);
8170
8171                         current_type = ec.ContainerType.BaseType;
8172                         indexer_type = current_type;
8173
8174                         foreach (Argument a in arguments){
8175                                 if (!a.Resolve (ec, loc))
8176                                         return false;
8177                         }
8178
8179                         return true;
8180                 }
8181         }
8182         
8183         /// <summary>
8184         ///   This class exists solely to pass the Type around and to be a dummy
8185         ///   that can be passed to the conversion functions (this is used by
8186         ///   foreach implementation to typecast the object return value from
8187         ///   get_Current into the proper type.  All code has been generated and
8188         ///   we only care about the side effect conversions to be performed
8189         ///
8190         ///   This is also now used as a placeholder where a no-action expression
8191         ///   is needed (the `New' class).
8192         /// </summary>
8193         public class EmptyExpression : Expression {
8194                 public EmptyExpression ()
8195                 {
8196                         type = TypeManager.object_type;
8197                         eclass = ExprClass.Value;
8198                         loc = Location.Null;
8199                 }
8200
8201                 public EmptyExpression (Type t)
8202                 {
8203                         type = t;
8204                         eclass = ExprClass.Value;
8205                         loc = Location.Null;
8206                 }
8207                 
8208                 public override Expression DoResolve (EmitContext ec)
8209                 {
8210                         return this;
8211                 }
8212
8213                 public override void Emit (EmitContext ec)
8214                 {
8215                         // nothing, as we only exist to not do anything.
8216                 }
8217
8218                 //
8219                 // This is just because we might want to reuse this bad boy
8220                 // instead of creating gazillions of EmptyExpressions.
8221                 // (CanImplicitConversion uses it)
8222                 //
8223                 public void SetType (Type t)
8224                 {
8225                         type = t;
8226                 }
8227         }
8228
8229         public class UserCast : Expression {
8230                 MethodBase method;
8231                 Expression source;
8232                 
8233                 public UserCast (MethodInfo method, Expression source, Location l)
8234                 {
8235                         this.method = method;
8236                         this.source = source;
8237                         type = method.ReturnType;
8238                         eclass = ExprClass.Value;
8239                         loc = l;
8240                 }
8241
8242                 public override Expression DoResolve (EmitContext ec)
8243                 {
8244                         //
8245                         // We are born fully resolved
8246                         //
8247                         return this;
8248                 }
8249
8250                 public override void Emit (EmitContext ec)
8251                 {
8252                         ILGenerator ig = ec.ig;
8253
8254                         source.Emit (ec);
8255                         
8256                         if (method is MethodInfo)
8257                                 ig.Emit (OpCodes.Call, (MethodInfo) method);
8258                         else
8259                                 ig.Emit (OpCodes.Call, (ConstructorInfo) method);
8260
8261                 }
8262         }
8263
8264         // <summary>
8265         //   This class is used to "construct" the type during a typecast
8266         //   operation.  Since the Type.GetType class in .NET can parse
8267         //   the type specification, we just use this to construct the type
8268         //   one bit at a time.
8269         // </summary>
8270         public class ComposedCast : TypeExpr {
8271                 Expression left;
8272                 string dim;
8273                 
8274                 public ComposedCast (Expression left, string dim, Location l)
8275                 {
8276                         this.left = left;
8277                         this.dim = dim;
8278                         loc = l;
8279                 }
8280
8281                 public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
8282                 {
8283                         Type ltype = ec.DeclSpace.ResolveType (left, false, loc);
8284                         if (ltype == null)
8285                                 return null;
8286
8287                         if ((ltype == TypeManager.void_type) && (dim != "*")) {
8288                                 Report.Error (1547, Location,
8289                                               "Keyword 'void' cannot be used in this context");
8290                                 return null;
8291                         }
8292
8293                         //
8294                         // ltype.Fullname is already fully qualified, so we can skip
8295                         // a lot of probes, and go directly to TypeManager.LookupType
8296                         //
8297                         string cname = ltype.FullName + dim;
8298                         type = TypeManager.LookupTypeDirect (cname);
8299                         if (type == null){
8300                                 //
8301                                 // For arrays of enumerations we are having a problem
8302                                 // with the direct lookup.  Need to investigate.
8303                                 //
8304                                 // For now, fall back to the full lookup in that case.
8305                                 //
8306                                 type = RootContext.LookupType (
8307                                         ec.DeclSpace, cname, false, loc);
8308
8309                                 if (type == null)
8310                                         return null;
8311                         }
8312
8313                         if (!ec.ResolvingTypeTree){
8314                                 //
8315                                 // If the above flag is set, this is being invoked from the ResolveType function.
8316                                 // Upper layers take care of the type validity in this context.
8317                                 //
8318                         if (!ec.InUnsafe && type.IsPointer){
8319                                 UnsafeError (loc);
8320                                 return null;
8321                         }
8322                         }
8323                         
8324                         eclass = ExprClass.Type;
8325                         return this;
8326                 }
8327
8328                 public override string Name {
8329                         get {
8330                                 return left + dim;
8331                         }
8332                 }
8333         }
8334
8335         //
8336         // This class is used to represent the address of an array, used
8337         // only by the Fixed statement, this is like the C "&a [0]" construct.
8338         //
8339         public class ArrayPtr : Expression {
8340                 Expression array;
8341                 
8342                 public ArrayPtr (Expression array, Location l)
8343                 {
8344                         Type array_type = TypeManager.GetElementType (array.Type);
8345
8346                         this.array = array;
8347
8348                         type = TypeManager.GetPointerType (array_type);
8349                         eclass = ExprClass.Value;
8350                         loc = l;
8351                 }
8352
8353                 public override void Emit (EmitContext ec)
8354                 {
8355                         ILGenerator ig = ec.ig;
8356                         
8357                         array.Emit (ec);
8358                         IntLiteral.EmitInt (ig, 0);
8359                         ig.Emit (OpCodes.Ldelema, TypeManager.GetElementType (array.Type));
8360                 }
8361
8362                 public override Expression DoResolve (EmitContext ec)
8363                 {
8364                         //
8365                         // We are born fully resolved
8366                         //
8367                         return this;
8368                 }
8369         }
8370
8371         //
8372         // Used by the fixed statement
8373         //
8374         public class StringPtr : Expression {
8375                 LocalBuilder b;
8376                 
8377                 public StringPtr (LocalBuilder b, Location l)
8378                 {
8379                         this.b = b;
8380                         eclass = ExprClass.Value;
8381                         type = TypeManager.char_ptr_type;
8382                         loc = l;
8383                 }
8384
8385                 public override Expression DoResolve (EmitContext ec)
8386                 {
8387                         // This should never be invoked, we are born in fully
8388                         // initialized state.
8389
8390                         return this;
8391                 }
8392
8393                 public override void Emit (EmitContext ec)
8394                 {
8395                         ILGenerator ig = ec.ig;
8396
8397                         ig.Emit (OpCodes.Ldloc, b);
8398                         ig.Emit (OpCodes.Conv_I);
8399                         ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
8400                         ig.Emit (OpCodes.Add);
8401                 }
8402         }
8403         
8404         //
8405         // Implements the `stackalloc' keyword
8406         //
8407         public class StackAlloc : Expression {
8408                 Type otype;
8409                 Expression t;
8410                 Expression count;
8411                 
8412                 public StackAlloc (Expression type, Expression count, Location l)
8413                 {
8414                         t = type;
8415                         this.count = count;
8416                         loc = l;
8417                 }
8418
8419                 public override Expression DoResolve (EmitContext ec)
8420                 {
8421                         count = count.Resolve (ec);
8422                         if (count == null)
8423                                 return null;
8424                         
8425                         if (count.Type != TypeManager.int32_type){
8426                                 count = Convert.ImplicitConversionRequired (ec, count, TypeManager.int32_type, loc);
8427                                 if (count == null)
8428                                         return null;
8429                         }
8430
8431                         Constant c = count as Constant;
8432                         // TODO: because we don't have property IsNegative
8433                         if (c != null && c.ConvertToUInt () == null) {
8434                                 // "Cannot use a negative size with stackalloc"
8435                                 Report.Error_T (247, loc);
8436                                 return null;
8437                         }
8438
8439                         if (ec.CurrentBranching.InCatch () ||
8440                             ec.CurrentBranching.InFinally (true)) {
8441                                 Error (255,
8442                                        "stackalloc can not be used in a catch or finally block");
8443                                 return null;
8444                         }
8445
8446                         otype = ec.DeclSpace.ResolveType (t, false, loc);
8447
8448                         if (otype == null)
8449                                 return null;
8450
8451                         if (!TypeManager.VerifyUnManaged (otype, loc))
8452                                 return null;
8453
8454                         type = TypeManager.GetPointerType (otype);
8455                         eclass = ExprClass.Value;
8456
8457                         return this;
8458                 }
8459
8460                 public override void Emit (EmitContext ec)
8461                 {
8462                         int size = GetTypeSize (otype);
8463                         ILGenerator ig = ec.ig;
8464                                 
8465                         if (size == 0)
8466                                 ig.Emit (OpCodes.Sizeof, otype);
8467                         else
8468                                 IntConstant.EmitInt (ig, size);
8469                         count.Emit (ec);
8470                         ig.Emit (OpCodes.Mul);
8471                         ig.Emit (OpCodes.Localloc);
8472                 }
8473         }
8474 }