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