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