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