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