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