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