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