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