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