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