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