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