2008-04-07 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / expression.cs
1 //
2 // expression.cs: Expression representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Marek Safar (marek.safar@seznam.cz)
7 //
8 // (C) 2001, 2002, 2003 Ximian, Inc.
9 // (C) 2003, 2004 Novell, Inc.
10 //
11 #define USE_OLD
12
13 namespace Mono.CSharp {
14         using System;
15         using System.Collections;
16         using System.Reflection;
17         using System.Reflection.Emit;
18         using System.Text;
19
20         //
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                 protected readonly ArrayList arguments;
28                 protected 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)
1598                         {
1599                                 if (TypeManager.IsEqual (left, lexpr.Type) &&
1600                                         TypeManager.IsEqual (right, rexpr.Type))
1601                                         return true;
1602
1603                                 return Convert.ImplicitConversionExists (ec, lexpr, left) &&
1604                                         Convert.ImplicitConversionExists (ec, rexpr, right);
1605                         }
1606
1607                         public PredefinedOperator ResolveBetterOperator (EmitContext ec, Expression lexpr, Expression rexpr, PredefinedOperator best_operator)
1608                         {
1609                                 int result = 0;
1610                                 if (left != null && best_operator.left != null) {
1611                                         result = MethodGroupExpr.BetterTypeConversion (ec, best_operator.left, left);
1612                                 }
1613
1614                                 //
1615                                 // When second arguments are same as the first one, the result is same
1616                                 //
1617                                 if (left != right || best_operator.left != best_operator.right) {
1618                                         result |= MethodGroupExpr.BetterTypeConversion (ec, best_operator.right, right);
1619                                 }
1620
1621                                 if (result == 0 || result > 2)
1622                                         return null;
1623
1624                                 return result == 1 ? best_operator : this;
1625                         }
1626                 }
1627
1628                 class PredefinedStringOperator : PredefinedOperator {
1629                         public PredefinedStringOperator (Type type, Operator op_mask)
1630                                 : base (type, op_mask, type)
1631                         {
1632                                 ReturnType = TypeManager.string_type;
1633                         }
1634
1635                         public PredefinedStringOperator (Type ltype, Type rtype, Operator op_mask)
1636                                 : base (ltype, rtype, op_mask)
1637                         {
1638                                 ReturnType = TypeManager.string_type;
1639                         }
1640
1641                         public override Expression ConvertResult (EmitContext ec, Binary b)
1642                         {
1643                                 //
1644                                 // Use original expression for nullable arguments
1645                                 //
1646                                 Nullable.Unwrap unwrap = b.left as Nullable.Unwrap;
1647                                 if (unwrap != null)
1648                                         b.left = unwrap.Original;
1649
1650                                 unwrap = b.right as Nullable.Unwrap;
1651                                 if (unwrap != null)
1652                                         b.right = unwrap.Original;
1653
1654                                 b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location);
1655                                 b.right = Convert.ImplicitConversion (ec, b.right, right, b.right.Location);
1656
1657                                 //
1658                                 // Start a new concat expression using converted expression
1659                                 //
1660                                 return new StringConcat (ec, b.loc, b.left, b.right).Resolve (ec);
1661                         }
1662                 }
1663
1664                 class PredefinedShiftOperator : PredefinedOperator {
1665                         public PredefinedShiftOperator (Type ltype, Operator op_mask) :
1666                                 base (ltype, TypeManager.int32_type, op_mask)
1667                         {
1668                         }
1669
1670                         public override Expression ConvertResult (EmitContext ec, Binary b)
1671                         {
1672                                 b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location);
1673
1674                                 Expression expr_tree_expr = EmptyCast.Create (b.right, TypeManager.int32_type);
1675
1676                                 int right_mask = left == TypeManager.int32_type || left == TypeManager.uint32_type ? 0x1f : 0x3f;
1677
1678                                 //
1679                                 // b = b.left >> b.right & (0x1f|0x3f)
1680                                 //
1681                                 b.right = new Binary (Operator.BitwiseAnd,
1682                                         b.right, new IntConstant (right_mask, b.right.Location)).Resolve (ec);
1683
1684                                 //
1685                                 // Expression tree representation does not use & mask
1686                                 //
1687                                 b.right = ReducedExpression.Create (b.right, expr_tree_expr).Resolve (ec);
1688                                 b.type = ReturnType;
1689                                 return b;
1690                         }
1691                 }
1692
1693                 class PredefinedPointerOperator : PredefinedOperator {
1694                         public PredefinedPointerOperator (Type ltype, Type rtype, Operator op_mask)
1695                                 : base (ltype, rtype, op_mask)
1696                         {
1697                         }
1698
1699                         public PredefinedPointerOperator (Type type, Operator op_mask, Type return_type)
1700                                 : base (type, op_mask, return_type)
1701                         {
1702                         }
1703
1704                         public override bool IsApplicable (EmitContext ec, Expression lexpr, Expression rexpr)
1705                         {
1706                                 if (left == null) {
1707                                         if (!lexpr.Type.IsPointer)
1708                                                 return false;
1709                                 } else {
1710                                         if (!Convert.ImplicitConversionExists (ec, lexpr, left))
1711                                                 return false;
1712                                 }
1713
1714                                 if (right == null) {
1715                                         if (!rexpr.Type.IsPointer)
1716                                                 return false;
1717                                 } else {
1718                                         if (!Convert.ImplicitConversionExists (ec, rexpr, right))
1719                                                 return false;
1720                                 }
1721
1722                                 return true;
1723                         }
1724
1725                         public override Expression ConvertResult (EmitContext ec, Binary b)
1726                         {
1727                                 base.ConvertResult (ec, b);
1728
1729                                 Type r_type = ReturnType;
1730                                 if (r_type == null) {
1731                                         r_type = b.left.Type;
1732                                         if (r_type == null)
1733                                                 r_type = b.right.Type;
1734                                 }
1735
1736                                 return new PointerArithmetic (b.oper == Operator.Addition,
1737                                         b.left, b.right, r_type, b.loc).Resolve (ec);
1738                         }
1739                 }
1740
1741                 [Flags]
1742                 public enum Operator {
1743                         Multiply        = 0 | ArithmeticMask,
1744                         Division        = 1 | ArithmeticMask,
1745                         Modulus         = 2 | ArithmeticMask,
1746                         Addition        = 3 | ArithmeticMask | AdditionMask,
1747                         Subtraction = 4 | ArithmeticMask | SubtractionMask,
1748
1749                         LeftShift       = 5 | ShiftMask,
1750                         RightShift      = 6 | ShiftMask,
1751
1752                         LessThan        = 7 | ComparisonMask | RelationalMask,
1753                         GreaterThan     = 8 | ComparisonMask | RelationalMask,
1754                         LessThanOrEqual         = 9 | ComparisonMask | RelationalMask,
1755                         GreaterThanOrEqual      = 10 | ComparisonMask | RelationalMask,
1756                         Equality        = 11 | ComparisonMask | EqualityMask,
1757                         Inequality      = 12 | ComparisonMask | EqualityMask,
1758
1759                         BitwiseAnd      = 13 | BitwiseMask,
1760                         ExclusiveOr     = 14 | BitwiseMask,
1761                         BitwiseOr       = 15 | BitwiseMask,
1762
1763                         LogicalAnd      = 16 | LogicalMask,
1764                         LogicalOr       = 17 | LogicalMask,
1765
1766                         //
1767                         // Operator masks
1768                         //
1769                         ValuesOnlyMask  = ArithmeticMask - 1,
1770                         ArithmeticMask  = 1 << 5,
1771                         ShiftMask               = 1 << 6,
1772                         ComparisonMask  = 1 << 7,
1773                         EqualityMask    = 1 << 8,
1774                         BitwiseMask             = 1 << 9,
1775                         LogicalMask             = 1 << 10,
1776                         AdditionMask    = 1 << 11,
1777                         SubtractionMask = 1 << 12,
1778                         RelationalMask  = 1 << 13
1779                 }
1780
1781                 readonly Operator oper;
1782                 protected Expression left, right;
1783                 readonly bool is_compound;
1784
1785                 // This must be kept in sync with Operator!!!
1786                 public static readonly string [] oper_names;
1787
1788                 static PredefinedOperator [] standard_operators;
1789                 static PredefinedOperator [] pointer_operators;
1790                 
1791                 static Binary ()
1792                 {
1793                         oper_names = new string [18];
1794
1795                         oper_names [(int) (Operator.Multiply & Operator.ValuesOnlyMask)] = "op_Multiply";
1796                         oper_names [(int) (Operator.Division & Operator.ValuesOnlyMask)] = "op_Division";
1797                         oper_names [(int) (Operator.Modulus & Operator.ValuesOnlyMask)] = "op_Modulus";
1798                         oper_names [(int) (Operator.Addition & Operator.ValuesOnlyMask)] = "op_Addition";
1799                         oper_names [(int) (Operator.Subtraction & Operator.ValuesOnlyMask)] = "op_Subtraction";
1800                         oper_names [(int) (Operator.LeftShift & Operator.ValuesOnlyMask)] = "op_LeftShift";
1801                         oper_names [(int) (Operator.RightShift & Operator.ValuesOnlyMask)] = "op_RightShift";
1802                         oper_names [(int) (Operator.LessThan & Operator.ValuesOnlyMask)] = "op_LessThan";
1803                         oper_names [(int) (Operator.GreaterThan & Operator.ValuesOnlyMask)] = "op_GreaterThan";
1804                         oper_names [(int) (Operator.LessThanOrEqual & Operator.ValuesOnlyMask)] = "op_LessThanOrEqual";
1805                         oper_names [(int) (Operator.GreaterThanOrEqual & Operator.ValuesOnlyMask)] = "op_GreaterThanOrEqual";
1806                         oper_names [(int) (Operator.Equality & Operator.ValuesOnlyMask)] = "op_Equality";
1807                         oper_names [(int) (Operator.Inequality & Operator.ValuesOnlyMask)] = "op_Inequality";
1808                         oper_names [(int) (Operator.BitwiseAnd & Operator.ValuesOnlyMask)] = "op_BitwiseAnd";
1809                         oper_names [(int) (Operator.BitwiseOr & Operator.ValuesOnlyMask)] = "op_BitwiseOr";
1810                         oper_names [(int) (Operator.ExclusiveOr & Operator.ValuesOnlyMask)] = "op_ExclusiveOr";
1811                         oper_names [(int) (Operator.LogicalOr & Operator.ValuesOnlyMask)] = "op_LogicalOr";
1812                         oper_names [(int) (Operator.LogicalAnd & Operator.ValuesOnlyMask)] = "op_LogicalAnd";
1813                 }
1814
1815                 public Binary (Operator oper, Expression left, Expression right, bool isCompound)
1816                         : this (oper, left, right)
1817                 {
1818                         this.is_compound = isCompound;
1819                 }
1820
1821                 public Binary (Operator oper, Expression left, Expression right)
1822                 {
1823                         this.oper = oper;
1824                         this.left = left;
1825                         this.right = right;
1826                         this.loc = left.Location;
1827                 }
1828
1829                 public Operator Oper {
1830                         get {
1831                                 return oper;
1832                         }
1833                 }
1834                 
1835                 /// <summary>
1836                 ///   Returns a stringified representation of the Operator
1837                 /// </summary>
1838                 string OperName (Operator oper)
1839                 {
1840                         string s;
1841                         switch (oper){
1842                         case Operator.Multiply:
1843                                 s = "*";
1844                                 break;
1845                         case Operator.Division:
1846                                 s = "/";
1847                                 break;
1848                         case Operator.Modulus:
1849                                 s = "%";
1850                                 break;
1851                         case Operator.Addition:
1852                                 s = "+";
1853                                 break;
1854                         case Operator.Subtraction:
1855                                 s = "-";
1856                                 break;
1857                         case Operator.LeftShift:
1858                                 s = "<<";
1859                                 break;
1860                         case Operator.RightShift:
1861                                 s = ">>";
1862                                 break;
1863                         case Operator.LessThan:
1864                                 s = "<";
1865                                 break;
1866                         case Operator.GreaterThan:
1867                                 s = ">";
1868                                 break;
1869                         case Operator.LessThanOrEqual:
1870                                 s = "<=";
1871                                 break;
1872                         case Operator.GreaterThanOrEqual:
1873                                 s = ">=";
1874                                 break;
1875                         case Operator.Equality:
1876                                 s = "==";
1877                                 break;
1878                         case Operator.Inequality:
1879                                 s = "!=";
1880                                 break;
1881                         case Operator.BitwiseAnd:
1882                                 s = "&";
1883                                 break;
1884                         case Operator.BitwiseOr:
1885                                 s = "|";
1886                                 break;
1887                         case Operator.ExclusiveOr:
1888                                 s = "^";
1889                                 break;
1890                         case Operator.LogicalOr:
1891                                 s = "||";
1892                                 break;
1893                         case Operator.LogicalAnd:
1894                                 s = "&&";
1895                                 break;
1896                         default:
1897                                 s = oper.ToString ();
1898                                 break;
1899                         }
1900
1901                         if (is_compound)
1902                                 return s + "=";
1903
1904                         return s;
1905                 }
1906
1907                 static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)
1908                 {
1909                         Error_OperatorCannotBeApplied (loc, name, TypeManager.CSharpName (l), TypeManager.CSharpName (r));
1910                 }
1911
1912                 public static void Error_OperatorCannotBeApplied (Location loc, string name, string left, string right)
1913                 {
1914                         Report.Error (19, loc, "Operator `{0}' cannot be applied to operands of type `{1}' and `{2}'",
1915                                 name, left, right);
1916                 }
1917                 
1918                 protected void Error_OperatorCannotBeApplied (Expression left, Expression right)
1919                 {
1920                         string l, r;
1921                         // TODO: This should be handled as Type of method group in CSharpName
1922                         if (left.eclass == ExprClass.MethodGroup)
1923                                 l = left.ExprClassName;
1924                         else
1925                                 l = TypeManager.CSharpName (left.Type);
1926
1927                         if (right.eclass == ExprClass.MethodGroup)
1928                                 r = right.ExprClassName;
1929                         else
1930                                 r = TypeManager.CSharpName (right.Type);
1931
1932                         Error_OperatorCannotBeApplied (Location, OperName (oper), l, r);
1933                 }
1934
1935                 public static string GetOperatorMetadataName (Operator op)
1936                 {
1937                         return oper_names [(int)(op & Operator.ValuesOnlyMask)];
1938                 }
1939
1940                 static bool IsUnsigned (Type t)
1941                 {
1942                         while (t.IsPointer)
1943                                 t = TypeManager.GetElementType (t);
1944
1945                         return (t == TypeManager.uint32_type || t == TypeManager.uint64_type ||
1946                                 t == TypeManager.ushort_type || t == TypeManager.byte_type);
1947                 }
1948
1949                 static bool IsFloat (Type t)
1950                 {
1951                         return t == TypeManager.float_type || t == TypeManager.double_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                                 return new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
2337
2338                         return DoResolveCore (ec, left, right);
2339                 }
2340
2341                 protected Expression DoResolveCore (EmitContext ec, Expression left_orig, Expression right_orig)
2342                 {
2343                         Expression expr = ResolveOperator (ec);
2344                         if (expr == null)
2345                                 Error_OperatorCannotBeApplied (left_orig, right_orig);
2346
2347                         if (left == null || right == null)
2348                                 throw new InternalErrorException ("Invalid conversion");
2349
2350                         if (oper == Operator.BitwiseOr)
2351                                 CheckBitwiseOrOnSignExtended ();
2352
2353                         return expr;
2354                 }
2355
2356                 //
2357                 // D operator + (D x, D y)
2358                 // D operator - (D x, D y)
2359                 //
2360                 Expression ResolveOperatorDelegateBinary (EmitContext ec, Type l, Type r)
2361                 {
2362                         if (((right.eclass == ExprClass.MethodGroup) || (r == TypeManager.anonymous_method_type))) {
2363                                 if ((RootContext.Version != LanguageVersion.ISO_1)) {
2364                                         Expression tmp = Convert.ImplicitConversionRequired (ec, right, l, loc);
2365                                         if (tmp == null)
2366                                                 return null;
2367                                         right = tmp;
2368                                         r = right.Type;
2369                                 }
2370                         } else {
2371                                 if (!TypeManager.IsEqual (l, r) && !(right is NullLiteral))
2372                                         return null;
2373                         }
2374
2375                         MethodInfo method;
2376                         ArrayList args = new ArrayList (2);
2377
2378                         args = new ArrayList (2);
2379                         args.Add (new Argument (left, Argument.AType.Expression));
2380                         args.Add (new Argument (right, Argument.AType.Expression));
2381
2382                         if (oper == Operator.Addition) {
2383                                 if (TypeManager.delegate_combine_delegate_delegate == null) {
2384                                         TypeManager.delegate_combine_delegate_delegate = TypeManager.GetPredefinedMethod (
2385                                                 TypeManager.delegate_type, "Combine", loc, TypeManager.delegate_type, TypeManager.delegate_type);
2386                                 }
2387
2388                                 method = TypeManager.delegate_combine_delegate_delegate;
2389                         } else {
2390                                 if (TypeManager.delegate_remove_delegate_delegate == null) {
2391                                         TypeManager.delegate_remove_delegate_delegate = TypeManager.GetPredefinedMethod (
2392                                                 TypeManager.delegate_type, "Remove", loc, TypeManager.delegate_type, TypeManager.delegate_type);
2393                                 }
2394
2395                                 method = TypeManager.delegate_remove_delegate_delegate;
2396                         }
2397
2398                         return new BinaryDelegate (l, method, args);
2399                 }
2400
2401                 //
2402                 // Enumeration operators
2403                 //
2404                 Binary ResolveOperatorEnum (EmitContext ec, bool lenum, bool renum, Type ltype, Type rtype)
2405                 {
2406                         Expression temp;
2407
2408                         if (lenum || renum) {
2409                                 //
2410                                 // bool operator == (E x, E y);
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                                 //
2417                                 if ((oper & Operator.ComparisonMask) != 0) {
2418                                         type = TypeManager.bool_type;
2419                                 } else if ((oper & Operator.BitwiseMask) != 0) {
2420                                         type = ltype;
2421                                 }
2422
2423                                 if (type != null) {
2424                                         if (!TypeManager.IsEqual (ltype, rtype)) {
2425                                                 if (!lenum) {
2426                                                         temp = Convert.ImplicitConversion (ec, left, rtype, loc);
2427                                                         if (temp == null)
2428                                                                 return null;
2429                                                         left = temp;
2430                                                 } else {
2431                                                         temp = Convert.ImplicitConversion (ec, right, ltype, loc);
2432                                                         if (temp == null)
2433                                                                 return null;
2434                                                         right = temp;
2435                                                 }
2436                                         }
2437
2438                                         return this;
2439                                 }
2440                         }
2441
2442                         Type underlying_type;
2443                         if (lenum && !renum) {
2444                                 //
2445                                 // E operator + (E e, U x)
2446                                 // E operator - (E e, U x)
2447                                 //
2448                                 if (oper == Operator.Addition || oper == Operator.Subtraction) {
2449                                         underlying_type = TypeManager.GetEnumUnderlyingType (ltype);
2450                                         temp = Convert.ImplicitConversion (ec, right, underlying_type, loc);
2451                                         if (temp == null)
2452                                                 return null;
2453
2454                                         right = temp;
2455                                         type = ltype;
2456                                         return this;
2457                                 }
2458
2459                                 return null;
2460                         }
2461
2462                         if (renum) {
2463                                 //
2464                                 // E operator + (U x, E e)
2465                                 //
2466                                 if (oper == Operator.Addition) {
2467                                         underlying_type = TypeManager.GetEnumUnderlyingType (rtype);
2468                                         temp = Convert.ImplicitConversion (ec, left, underlying_type, loc);
2469                                         if (temp == null)
2470                                                 return null;
2471
2472                                         left = temp;
2473                                         type = rtype;
2474                                         return this;
2475                                 }
2476                         }
2477
2478                         //
2479                         // U operator - (E e, E f)
2480                         //
2481                         if (oper == Operator.Subtraction) {
2482                                 if (!TypeManager.IsEqual (ltype, rtype))
2483                                         return null;
2484
2485                                 type = TypeManager.GetEnumUnderlyingType (ltype);
2486                                 return this;
2487                         }
2488
2489                         return null;
2490                 }
2491
2492                 //
2493                 // 7.9.6 Reference type equality operators
2494                 //
2495                 Binary ResolveOperatorEqualityRerefence (EmitContext ec, Type l, Type r)
2496                 {
2497                         //
2498                         // operator != (object a, object b)
2499                         // operator == (object a, object b)
2500                         //
2501
2502                         // TODO: this method is almost equivalent to Convert.ImplicitReferenceConversion
2503
2504                         if (left.eclass == ExprClass.MethodGroup || right.eclass == ExprClass.MethodGroup)
2505                                 return null;
2506
2507                         type = TypeManager.bool_type;
2508                         GenericConstraints constraints;
2509
2510                         bool lgen = TypeManager.IsGenericParameter (l);
2511
2512                         if (TypeManager.IsEqual (l, r)) {
2513                                 if (lgen) {
2514                                         //
2515                                         // Only allow to compare same reference type parameter
2516                                         //
2517                                         constraints = TypeManager.GetTypeParameterConstraints (l);
2518                                         if (constraints != null && constraints.IsReferenceType)
2519                                                 return this;
2520
2521                                         return null;
2522                                 }
2523
2524                                 if (l == TypeManager.anonymous_method_type)
2525                                         return null;
2526
2527                                 if (TypeManager.IsValueType (l))
2528                                         return null;
2529
2530                                 return this;
2531                         }
2532
2533                         bool rgen = TypeManager.IsGenericParameter (r);
2534
2535                         //
2536                         // a, Both operands are reference-type values or the value null
2537                         // b, One operand is a value of type T where T is a type-parameter and
2538                         // the other operand is the value null. Furthermore T does not have the
2539                         // value type constrain
2540                         //
2541                         if (left is NullLiteral || right is NullLiteral) {
2542                                 if (lgen) {
2543                                         constraints = TypeManager.GetTypeParameterConstraints (l);
2544                                         if (constraints != null && constraints.HasValueTypeConstraint)
2545                                                 return null;
2546
2547                                         left = new BoxedCast (left, TypeManager.object_type);
2548                                         return this;
2549                                 }
2550
2551                                 if (rgen) {
2552                                         constraints = TypeManager.GetTypeParameterConstraints (r);
2553                                         if (constraints != null && constraints.HasValueTypeConstraint)
2554                                                 return null;
2555
2556                                         right = new BoxedCast (right, TypeManager.object_type);
2557                                         return this;
2558                                 }
2559                         }
2560
2561                         //
2562                         // An interface is converted to the object before the
2563                         // standard conversion is applied. It's not clear from the
2564                         // standard but it looks like it works like that.
2565                         //
2566                         if (lgen) {
2567                                 constraints = TypeManager.GetTypeParameterConstraints (l);
2568                                 if (constraints == null || constraints.IsReferenceType)
2569                                         return null;
2570                         } else if (l.IsInterface) {
2571                                 l = TypeManager.object_type;
2572                         }
2573
2574                         if (rgen) {
2575                                 constraints = TypeManager.GetTypeParameterConstraints (r);
2576                                 if (constraints == null || constraints.IsReferenceType)
2577                                         return null;
2578                         } else if (r.IsInterface) {
2579                                 r = TypeManager.object_type;
2580                         }
2581
2582                         const string ref_comparison = "Possible unintended reference comparison. " +
2583                                 "Consider casting the {0} side of the expression to `string' to compare the values";
2584
2585                         //
2586                         // A standard implicit conversion exists from the type of either
2587                         // operand to the type of the other operand
2588                         //
2589                         if (Convert.ImplicitReferenceConversionExists (left, r)) {
2590                                 if (l == TypeManager.string_type)
2591                                         Report.Warning (253, 2, loc, ref_comparison, "right");
2592
2593                                 return this;
2594                         }
2595
2596                         if (Convert.ImplicitReferenceConversionExists (right, l)) {
2597                                 if (r == TypeManager.string_type)
2598                                         Report.Warning (252, 2, loc, ref_comparison, "left");
2599
2600                                 return this;
2601                         }
2602
2603                         return null;
2604                 }
2605
2606
2607                 Expression ResolveOperatorPointer (EmitContext ec, Type l, Type r)
2608                 {
2609                         //
2610                         // bool operator == (void* x, void* y);
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                         //
2617                         if ((oper & Operator.ComparisonMask) != 0) {
2618                                 Expression temp;
2619                                 if (!l.IsPointer) {
2620                                         temp = Convert.ImplicitConversion (ec, left, r, left.Location);
2621                                         if (temp == null)
2622                                                 return null;
2623                                         left = temp;
2624                                 }
2625
2626                                 if (!r.IsPointer) {
2627                                         temp = Convert.ImplicitConversion (ec, right, l, right.Location);
2628                                         if (temp == null)
2629                                                 return null;
2630                                         right = temp;
2631                                 }
2632
2633                                 type = TypeManager.bool_type;
2634                                 return this;
2635                         }
2636
2637                         if (pointer_operators == null)
2638                                 CreatePointerOperatorsTable ();
2639
2640                         return ResolveOperatorPredefined (ec, pointer_operators, false);
2641                 }
2642
2643                 //
2644                 // Build-in operators method overloading
2645                 //
2646                 protected virtual Expression ResolveOperatorPredefined (EmitContext ec, PredefinedOperator [] operators, bool primitives_only)
2647                 {
2648                         PredefinedOperator best_operator = null;
2649                         Type l = left.Type;
2650                         Operator oper_mask = oper & ~Operator.ValuesOnlyMask;
2651
2652                         foreach (PredefinedOperator po in operators) {
2653                                 if ((po.OperatorsMask & oper_mask) == 0)
2654                                         continue;
2655
2656                                 if (primitives_only) {
2657                                         if (!po.IsPrimitiveApplicable (l))
2658                                                 continue;
2659                                 } else {
2660                                         if (!po.IsApplicable (ec, left, right))
2661                                                 continue;
2662                                 }
2663
2664                                 if (best_operator == null) {
2665                                         best_operator = po;
2666                                         if (primitives_only)
2667                                                 break;
2668
2669                                         continue;
2670                                 }
2671
2672                                 best_operator = po.ResolveBetterOperator (ec, left, right, best_operator);
2673
2674                                 if (best_operator == null) {
2675                                         Report.Error (34, loc, "Operator `{0}' is ambiguous on operands of type `{1}' and `{2}'",
2676                                                 OperName (oper), left.GetSignatureForError (), right.GetSignatureForError ());
2677
2678                                         best_operator = po;
2679                                         break;
2680                                 }
2681                         }
2682
2683                         if (best_operator == null)
2684                                 return null;
2685
2686                         return best_operator.ConvertResult (ec, this);
2687                 }
2688
2689                 //
2690                 // Performs user-operator overloading
2691                 //
2692                 protected virtual Expression ResolveUserOperator (EmitContext ec, Type l, Type r)
2693                 {
2694                         Operator user_oper;
2695                         if (oper == Operator.LogicalAnd)
2696                                 user_oper = Operator.BitwiseAnd;
2697                         else if (oper == Operator.LogicalOr)
2698                                 user_oper = Operator.BitwiseOr;
2699                         else
2700                                 user_oper = oper;
2701
2702                         string op = GetOperatorMetadataName (user_oper);
2703
2704                         MethodGroupExpr union;
2705                         MethodGroupExpr left_operators = MemberLookup (ec.ContainerType, l, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
2706                         if (!TypeManager.IsEqual (r, l)) {
2707                                 MethodGroupExpr right_operators = MemberLookup (
2708                                         ec.ContainerType, r, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
2709                                 union = MethodGroupExpr.MakeUnionSet (left_operators, right_operators, loc);
2710                         } else
2711                                 union = left_operators;
2712
2713                         if (union == null)
2714                                 return null;
2715
2716                         ArrayList args = new ArrayList (2);
2717                         Argument larg = new Argument (left);
2718                         args.Add (larg);
2719                         Argument rarg = new Argument (right);
2720                         args.Add (rarg);
2721
2722                         union = union.OverloadResolve (ec, ref args, true, loc);
2723                         if (union == null)
2724                                 return null;
2725
2726                         Expression oper_expr;
2727
2728                         // TODO: CreateExpressionTree is allocated every time
2729                         if (user_oper != oper) {
2730                                 oper_expr = new ConditionalLogicalOperator (union, args, CreateExpressionTree,
2731                                         oper == Operator.LogicalAnd, loc).Resolve (ec);
2732                         } else {
2733                                 oper_expr = new UserOperatorCall (union, args, CreateExpressionTree, loc);
2734
2735                                 //
2736                                 // This is used to check if a test 'x == null' can be optimized to a reference equals,
2737                                 // and not invoke user operator
2738                                 //
2739                                 if ((oper & Operator.EqualityMask) != 0) {
2740                                         if ((left is NullLiteral && IsBuildInEqualityOperator (r)) ||
2741                                                 (right is NullLiteral && IsBuildInEqualityOperator (l))) {
2742                                                 type = TypeManager.bool_type;
2743                                                 if (left is NullLiteral || right is NullLiteral)
2744                                                         oper_expr = ReducedExpression.Create (this, oper_expr).Resolve (ec);
2745                                         } else if (union.DeclaringType == TypeManager.delegate_type && l != r) {
2746                                                 //
2747                                                 // Two System.Delegate(s) are never equal
2748                                                 //
2749                                                 return null;
2750                                         }
2751                                 }
2752                         }
2753
2754                         left = larg.Expr;
2755                         right = rarg.Expr;
2756                         return oper_expr;
2757                 }
2758
2759                 public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
2760                 {
2761                         return null;
2762                 }
2763
2764                 private void CheckUselessComparison (Constant c, Type type)
2765                 {
2766                         if (c == null || !IsTypeIntegral (type)
2767                                 || c is StringConstant
2768                                 || c is BoolConstant
2769                                 || c is FloatConstant
2770                                 || c is DoubleConstant
2771                                 || c is DecimalConstant
2772                                 )
2773                                 return;
2774
2775                         long value = 0;
2776
2777                         if (c is ULongConstant) {
2778                                 ulong uvalue = ((ULongConstant) c).Value;
2779                                 if (uvalue > long.MaxValue) {
2780                                         if (type == TypeManager.byte_type ||
2781                                             type == TypeManager.sbyte_type ||
2782                                             type == TypeManager.short_type ||
2783                                             type == TypeManager.ushort_type ||
2784                                             type == TypeManager.int32_type ||
2785                                             type == TypeManager.uint32_type ||
2786                                             type == TypeManager.int64_type ||
2787                                                 type == TypeManager.char_type)
2788                                                 WarnUselessComparison (type);
2789                                         return;
2790                                 }
2791                                 value = (long) uvalue;
2792                         }
2793                         else if (c is ByteConstant)
2794                                 value = ((ByteConstant) c).Value;
2795                         else if (c is SByteConstant)
2796                                 value = ((SByteConstant) c).Value;
2797                         else if (c is ShortConstant)
2798                                 value = ((ShortConstant) c).Value;
2799                         else if (c is UShortConstant)
2800                                 value = ((UShortConstant) c).Value;
2801                         else if (c is IntConstant)
2802                                 value = ((IntConstant) c).Value;
2803                         else if (c is UIntConstant)
2804                                 value = ((UIntConstant) c).Value;
2805                         else if (c is LongConstant)
2806                                 value = ((LongConstant) c).Value;
2807                         else if (c is CharConstant)
2808                                 value = ((CharConstant)c).Value;
2809
2810                         if (value == 0)
2811                                 return;
2812
2813                         if (IsValueOutOfRange (value, type))
2814                                 WarnUselessComparison (type);
2815                 }
2816
2817                 private bool IsValueOutOfRange (long value, Type type)
2818                 {
2819                         if (IsTypeUnsigned (type) && value < 0)
2820                                 return true;
2821                         return type == TypeManager.sbyte_type && (value >= 0x80 || value < -0x80) ||
2822                                 type == TypeManager.byte_type && value >= 0x100 ||
2823                                 type == TypeManager.short_type && (value >= 0x8000 || value < -0x8000) ||
2824                                 type == TypeManager.ushort_type && value >= 0x10000 ||
2825                                 type == TypeManager.int32_type && (value >= 0x80000000 || value < -0x80000000) ||
2826                                 type == TypeManager.uint32_type && value >= 0x100000000;
2827                 }
2828
2829                 static bool IsBuildInEqualityOperator (Type t)
2830                 {
2831                         return t == TypeManager.object_type || t == TypeManager.string_type ||
2832                                 t == TypeManager.delegate_type || TypeManager.IsDelegateType (t);
2833                 }
2834
2835                 private static bool IsTypeIntegral (Type type)
2836                 {
2837                         return type == TypeManager.uint64_type ||
2838                                 type == TypeManager.int64_type ||
2839                                 type == TypeManager.uint32_type ||
2840                                 type == TypeManager.int32_type ||
2841                                 type == TypeManager.ushort_type ||
2842                                 type == TypeManager.short_type ||
2843                                 type == TypeManager.sbyte_type ||
2844                                 type == TypeManager.byte_type ||
2845                                 type == TypeManager.char_type;
2846                 }
2847
2848                 private static bool IsTypeUnsigned (Type type)
2849                 {
2850                         return type == TypeManager.uint64_type ||
2851                                 type == TypeManager.uint32_type ||
2852                                 type == TypeManager.ushort_type ||
2853                                 type == TypeManager.byte_type ||
2854                                 type == TypeManager.char_type;
2855                 }
2856
2857                 private void WarnUselessComparison (Type type)
2858                 {
2859                         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}'",
2860                                 TypeManager.CSharpName (type));
2861                 }
2862
2863                 /// <remarks>
2864                 ///   EmitBranchable is called from Statement.EmitBoolExpression in the
2865                 ///   context of a conditional bool expression.  This function will return
2866                 ///   false if it is was possible to use EmitBranchable, or true if it was.
2867                 ///
2868                 ///   The expression's code is generated, and we will generate a branch to `target'
2869                 ///   if the resulting expression value is equal to isTrue
2870                 /// </remarks>
2871                 public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
2872                 {
2873                         ILGenerator ig = ec.ig;
2874
2875                         //
2876                         // This is more complicated than it looks, but its just to avoid
2877                         // duplicated tests: basically, we allow ==, !=, >, <, >= and <=
2878                         // but on top of that we want for == and != to use a special path
2879                         // if we are comparing against null
2880                         //
2881                         if ((oper == Operator.Equality || oper == Operator.Inequality) && (left is Constant || right is Constant)) {
2882                                 bool my_on_true = oper == Operator.Inequality ? on_true : !on_true;
2883                                 
2884                                 //
2885                                 // put the constant on the rhs, for simplicity
2886                                 //
2887                                 if (left is Constant) {
2888                                         Expression swap = right;
2889                                         right = left;
2890                                         left = swap;
2891                                 }
2892                                 
2893                                 if (((Constant) right).IsZeroInteger) {
2894                                         left.Emit (ec);
2895                                         if (my_on_true)
2896                                                 ig.Emit (OpCodes.Brtrue, target);
2897                                         else
2898                                                 ig.Emit (OpCodes.Brfalse, target);
2899                                         
2900                                         return;
2901                                 } else if (right is BoolConstant) {
2902                                         left.Emit (ec);
2903                                         if (my_on_true != ((BoolConstant) right).Value)
2904                                                 ig.Emit (OpCodes.Brtrue, target);
2905                                         else
2906                                                 ig.Emit (OpCodes.Brfalse, target);
2907                                         
2908                                         return;
2909                                 }
2910
2911                         } else if (oper == Operator.LogicalAnd) {
2912
2913                                 if (on_true) {
2914                                         Label tests_end = ig.DefineLabel ();
2915                                         
2916                                         left.EmitBranchable (ec, tests_end, false);
2917                                         right.EmitBranchable (ec, target, true);
2918                                         ig.MarkLabel (tests_end);                                       
2919                                 } else {
2920                                         //
2921                                         // This optimizes code like this 
2922                                         // if (true && i > 4)
2923                                         //
2924                                         if (!(left is Constant))
2925                                                 left.EmitBranchable (ec, target, false);
2926
2927                                         if (!(right is Constant)) 
2928                                                 right.EmitBranchable (ec, target, false);
2929                                 }
2930                                 
2931                                 return;
2932                                 
2933                         } else if (oper == Operator.LogicalOr){
2934                                 if (on_true) {
2935                                         left.EmitBranchable (ec, target, true);
2936                                         right.EmitBranchable (ec, target, true);
2937                                         
2938                                 } else {
2939                                         Label tests_end = ig.DefineLabel ();
2940                                         left.EmitBranchable (ec, tests_end, true);
2941                                         right.EmitBranchable (ec, target, false);
2942                                         ig.MarkLabel (tests_end);
2943                                 }
2944                                 
2945                                 return;
2946                                 
2947                         } else if (!(oper == Operator.LessThan        || oper == Operator.GreaterThan ||
2948                                      oper == Operator.LessThanOrEqual || oper == Operator.GreaterThanOrEqual ||
2949                                      oper == Operator.Equality        || oper == Operator.Inequality)) {
2950                                 base.EmitBranchable (ec, target, on_true);
2951                                 return;
2952                         }
2953                         
2954                         left.Emit (ec);
2955                         right.Emit (ec);
2956
2957                         Type t = left.Type;
2958                         bool is_unsigned = IsUnsigned (t) || t == TypeManager.double_type || t == TypeManager.float_type;
2959                         
2960                         switch (oper){
2961                         case Operator.Equality:
2962                                 if (on_true)
2963                                         ig.Emit (OpCodes.Beq, target);
2964                                 else
2965                                         ig.Emit (OpCodes.Bne_Un, target);
2966                                 break;
2967
2968                         case Operator.Inequality:
2969                                 if (on_true)
2970                                         ig.Emit (OpCodes.Bne_Un, target);
2971                                 else
2972                                         ig.Emit (OpCodes.Beq, target);
2973                                 break;
2974
2975                         case Operator.LessThan:
2976                                 if (on_true)
2977                                         if (is_unsigned)
2978                                                 ig.Emit (OpCodes.Blt_Un, target);
2979                                         else
2980                                                 ig.Emit (OpCodes.Blt, target);
2981                                 else
2982                                         if (is_unsigned)
2983                                                 ig.Emit (OpCodes.Bge_Un, target);
2984                                         else
2985                                                 ig.Emit (OpCodes.Bge, target);
2986                                 break;
2987
2988                         case Operator.GreaterThan:
2989                                 if (on_true)
2990                                         if (is_unsigned)
2991                                                 ig.Emit (OpCodes.Bgt_Un, target);
2992                                         else
2993                                                 ig.Emit (OpCodes.Bgt, target);
2994                                 else
2995                                         if (is_unsigned)
2996                                                 ig.Emit (OpCodes.Ble_Un, target);
2997                                         else
2998                                                 ig.Emit (OpCodes.Ble, target);
2999                                 break;
3000
3001                         case Operator.LessThanOrEqual:
3002                                 if (on_true)
3003                                         if (is_unsigned)
3004                                                 ig.Emit (OpCodes.Ble_Un, target);
3005                                         else
3006                                                 ig.Emit (OpCodes.Ble, target);
3007                                 else
3008                                         if (is_unsigned)
3009                                                 ig.Emit (OpCodes.Bgt_Un, target);
3010                                         else
3011                                                 ig.Emit (OpCodes.Bgt, target);
3012                                 break;
3013
3014
3015                         case Operator.GreaterThanOrEqual:
3016                                 if (on_true)
3017                                         if (is_unsigned)
3018                                                 ig.Emit (OpCodes.Bge_Un, target);
3019                                         else
3020                                                 ig.Emit (OpCodes.Bge, target);
3021                                 else
3022                                         if (is_unsigned)
3023                                                 ig.Emit (OpCodes.Blt_Un, target);
3024                                         else
3025                                                 ig.Emit (OpCodes.Blt, target);
3026                                 break;
3027                         default:
3028                                 throw new InternalErrorException (oper.ToString ());
3029                         }
3030                 }
3031                 
3032                 public override void Emit (EmitContext ec)
3033                 {
3034                         EmitOperator (ec);
3035                 }
3036
3037                 protected void EmitOperator (EmitContext ec)
3038                 {
3039                         ILGenerator ig = ec.ig;
3040
3041                         //
3042                         // Handle short-circuit operators differently
3043                         // than the rest
3044                         //
3045                         if ((oper & Operator.LogicalMask) != 0) {
3046                                 Label load_result = ig.DefineLabel ();
3047                                 Label end = ig.DefineLabel ();
3048
3049                                 bool is_or = oper == Operator.LogicalOr;
3050                                 left.EmitBranchable (ec, load_result, is_or);
3051                                 right.Emit (ec);
3052                                 ig.Emit (OpCodes.Br_S, end);
3053                                 
3054                                 ig.MarkLabel (load_result);
3055                                 ig.Emit (is_or ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
3056                                 ig.MarkLabel (end);
3057                                 return;
3058                         }
3059
3060                         left.Emit (ec);
3061
3062                         //
3063                         // Optimize zero-based operations
3064                         //
3065                         // TODO: Implement more optimizations, but it should probably go to PredefinedOperators
3066                         //
3067                         if ((oper & Operator.ShiftMask) != 0 || oper == Operator.Addition || oper == Operator.Subtraction) {
3068                                 Constant rc = right as Constant;
3069                                 if (rc != null && rc.IsDefaultValue) {
3070                                         return;
3071                                 }
3072                         }
3073
3074                         right.Emit (ec);
3075
3076                         Type l = left.Type;
3077                         OpCode opcode;
3078                         
3079                         switch (oper){
3080                         case Operator.Multiply:
3081                                 if (ec.CheckState){
3082                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
3083                                                 opcode = OpCodes.Mul_Ovf;
3084                                         else if (!IsFloat (l))
3085                                                 opcode = OpCodes.Mul_Ovf_Un;
3086                                         else
3087                                                 opcode = OpCodes.Mul;
3088                                 } else
3089                                         opcode = OpCodes.Mul;
3090                                 
3091                                 break;
3092                                 
3093                         case Operator.Division:
3094                                 if (IsUnsigned (l))
3095                                         opcode = OpCodes.Div_Un;
3096                                 else
3097                                         opcode = OpCodes.Div;
3098                                 break;
3099                                 
3100                         case Operator.Modulus:
3101                                 if (IsUnsigned (l))
3102                                         opcode = OpCodes.Rem_Un;
3103                                 else
3104                                         opcode = OpCodes.Rem;
3105                                 break;
3106
3107                         case Operator.Addition:
3108                                 if (ec.CheckState){
3109                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
3110                                                 opcode = OpCodes.Add_Ovf;
3111                                         else if (!IsFloat (l))
3112                                                 opcode = OpCodes.Add_Ovf_Un;
3113                                         else
3114                                                 opcode = OpCodes.Add;
3115                                 } else
3116                                         opcode = OpCodes.Add;
3117                                 break;
3118
3119                         case Operator.Subtraction:
3120                                 if (ec.CheckState){
3121                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
3122                                                 opcode = OpCodes.Sub_Ovf;
3123                                         else if (!IsFloat (l))
3124                                                 opcode = OpCodes.Sub_Ovf_Un;
3125                                         else
3126                                                 opcode = OpCodes.Sub;
3127                                 } else
3128                                         opcode = OpCodes.Sub;
3129                                 break;
3130
3131                         case Operator.RightShift:
3132                                 if (IsUnsigned (l))
3133                                         opcode = OpCodes.Shr_Un;
3134                                 else
3135                                         opcode = OpCodes.Shr;
3136                                 break;
3137                                 
3138                         case Operator.LeftShift:
3139                                 opcode = OpCodes.Shl;
3140                                 break;
3141
3142                         case Operator.Equality:
3143                                 opcode = OpCodes.Ceq;
3144                                 break;
3145
3146                         case Operator.Inequality:
3147                                 ig.Emit (OpCodes.Ceq);
3148                                 ig.Emit (OpCodes.Ldc_I4_0);
3149                                 
3150                                 opcode = OpCodes.Ceq;
3151                                 break;
3152
3153                         case Operator.LessThan:
3154                                 if (IsUnsigned (l))
3155                                         opcode = OpCodes.Clt_Un;
3156                                 else
3157                                         opcode = OpCodes.Clt;
3158                                 break;
3159
3160                         case Operator.GreaterThan:
3161                                 if (IsUnsigned (l))
3162                                         opcode = OpCodes.Cgt_Un;
3163                                 else
3164                                         opcode = OpCodes.Cgt;
3165                                 break;
3166
3167                         case Operator.LessThanOrEqual:
3168                                 if (IsUnsigned (l) || IsFloat (l))
3169                                         ig.Emit (OpCodes.Cgt_Un);
3170                                 else
3171                                         ig.Emit (OpCodes.Cgt);
3172                                 ig.Emit (OpCodes.Ldc_I4_0);
3173                                 
3174                                 opcode = OpCodes.Ceq;
3175                                 break;
3176
3177                         case Operator.GreaterThanOrEqual:
3178                                 if (IsUnsigned (l) || IsFloat (l))
3179                                         ig.Emit (OpCodes.Clt_Un);
3180                                 else
3181                                         ig.Emit (OpCodes.Clt);
3182                                 
3183                                 ig.Emit (OpCodes.Ldc_I4_0);
3184                                 
3185                                 opcode = OpCodes.Ceq;
3186                                 break;
3187
3188                         case Operator.BitwiseOr:
3189                                 opcode = OpCodes.Or;
3190                                 break;
3191
3192                         case Operator.BitwiseAnd:
3193                                 opcode = OpCodes.And;
3194                                 break;
3195
3196                         case Operator.ExclusiveOr:
3197                                 opcode = OpCodes.Xor;
3198                                 break;
3199
3200                         default:
3201                                 throw new InternalErrorException (oper.ToString ());
3202                         }
3203
3204                         ig.Emit (opcode);
3205                 }
3206
3207                 protected override void CloneTo (CloneContext clonectx, Expression t)
3208                 {
3209                         Binary target = (Binary) t;
3210
3211                         target.left = left.Clone (clonectx);
3212                         target.right = right.Clone (clonectx);
3213                 }
3214                 
3215                 public override Expression CreateExpressionTree (EmitContext ec)
3216                 {
3217                         return CreateExpressionTree (ec, null);
3218                 }
3219
3220                 Expression CreateExpressionTree (EmitContext ec, MethodGroupExpr method)                
3221                 {
3222                         string method_name;
3223                         bool lift_arg = false;
3224                         
3225                         switch (oper) {
3226                         case Operator.Addition:
3227                                 if (method == null && ec.CheckState && !IsFloat (left.Type))
3228                                         method_name = "AddChecked";
3229                                 else
3230                                         method_name = "Add";
3231                                 break;
3232                         case Operator.BitwiseAnd:
3233                                 method_name = "And";
3234                                 break;
3235                         case Operator.BitwiseOr:
3236                                 method_name = "Or";
3237                                 break;
3238                         case Operator.Division:
3239                                 method_name = "Divide";
3240                                 break;
3241                         case Operator.Equality:
3242                                 method_name = "Equal";
3243                                 lift_arg = true;
3244                                 break;
3245                         case Operator.ExclusiveOr:
3246                                 method_name = "ExclusiveOr";
3247                                 break;                          
3248                         case Operator.GreaterThan:
3249                                 method_name = "GreaterThan";
3250                                 lift_arg = true;
3251                                 break;
3252                         case Operator.GreaterThanOrEqual:
3253                                 method_name = "GreaterThanOrEqual";
3254                                 lift_arg = true;
3255                                 break;
3256                         case Operator.Inequality:
3257                                 method_name = "NotEqual";
3258                                 lift_arg = true;
3259                                 break;
3260                         case Operator.LeftShift:
3261                                 method_name = "LeftShift";
3262                                 break;
3263                         case Operator.LessThan:
3264                                 method_name = "LessThan";
3265                                 lift_arg = true;
3266                                 break;
3267                         case Operator.LessThanOrEqual:
3268                                 method_name = "LessThanOrEqual";
3269                                 lift_arg = true;
3270                                 break;
3271                         case Operator.LogicalAnd:
3272                                 method_name = "AndAlso";
3273                                 break;
3274                         case Operator.LogicalOr:
3275                                 method_name = "OrElse";
3276                                 break;
3277                         case Operator.Modulus:
3278                                 method_name = "Modulo";
3279                                 break;
3280                         case Operator.Multiply:
3281                                 if (method == null && ec.CheckState && !IsFloat (left.Type))
3282                                         method_name = "MultiplyChecked";
3283                                 else
3284                                         method_name = "Multiply";
3285                                 break;
3286                         case Operator.RightShift:
3287                                 method_name = "RightShift";
3288                                 break;
3289                         case Operator.Subtraction:
3290                                 if (method == null && ec.CheckState && !IsFloat (left.Type))
3291                                         method_name = "SubtractChecked";
3292                                 else
3293                                         method_name = "Subtract";
3294                                 break;
3295
3296                         default:
3297                                 throw new InternalErrorException ("Unknown expression tree binary operator " + oper);
3298                         }
3299
3300                         ArrayList args = new ArrayList (2);
3301                         args.Add (new Argument (left.CreateExpressionTree (ec)));
3302                         args.Add (new Argument (right.CreateExpressionTree (ec)));
3303                         if (method != null) {
3304                                 if (lift_arg)
3305                                         args.Add (new Argument (new BoolConstant (false, loc)));
3306                                 
3307                                 args.Add (new Argument (method.CreateExpressionTree (ec)));
3308                         }
3309                         
3310                         return CreateExpressionFactoryCall (method_name, args);
3311                 }
3312         }
3313
3314         //
3315         // Object created by Binary when the binary operator uses an method instead of being
3316         // a binary operation that maps to a CIL binary operation.
3317         //
3318         public class BinaryMethod : Expression {
3319                 public MethodBase method;
3320                 public ArrayList  Arguments;
3321                 
3322                 public BinaryMethod (Type t, MethodBase m, ArrayList args)
3323                 {
3324                         method = m;
3325                         Arguments = args;
3326                         type = t;
3327                         eclass = ExprClass.Value;
3328                 }
3329
3330                 public override Expression DoResolve (EmitContext ec)
3331                 {
3332                         return this;
3333                 }
3334
3335                 public override void Emit (EmitContext ec)
3336                 {
3337                         ILGenerator ig = ec.ig;
3338                         
3339                         Invocation.EmitArguments (ec, Arguments, false, null);
3340                         
3341                         if (method is MethodInfo)
3342                                 ig.Emit (OpCodes.Call, (MethodInfo) method);
3343                         else
3344                                 ig.Emit (OpCodes.Call, (ConstructorInfo) method);
3345                 }
3346         }
3347         
3348         //
3349         // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string
3350         // b, c, d... may be strings or objects.
3351         //
3352         public class StringConcat : Expression {
3353                 ArrayList arguments;
3354                 
3355                 public StringConcat (EmitContext ec, Location loc, Expression left, Expression right)
3356                 {
3357                         this.loc = loc;
3358                         type = TypeManager.string_type;
3359                         eclass = ExprClass.Value;
3360
3361                         arguments = new ArrayList (2);
3362                         Append (ec, left);
3363                         Append (ec, right);
3364                 }
3365
3366                 public override Expression CreateExpressionTree (EmitContext ec)
3367                 {
3368                         Argument arg = (Argument) arguments [0];
3369                         return CreateExpressionAddCall (ec, arg, arg.Expr.CreateExpressionTree (ec), 1);
3370                 }
3371
3372                 //
3373                 // Creates nested calls tree from an array of arguments used for IL emit
3374                 //
3375                 Expression CreateExpressionAddCall (EmitContext ec, Argument left, Expression left_etree, int pos)
3376                 {
3377                         ArrayList concat_args = new ArrayList (2);
3378                         ArrayList add_args = new ArrayList (3);
3379
3380                         concat_args.Add (left);
3381                         add_args.Add (new Argument (left_etree));
3382
3383                         concat_args.Add (arguments [pos]);
3384                         add_args.Add (new Argument (((Argument) arguments [pos]).Expr.CreateExpressionTree (ec)));
3385
3386                         MethodGroupExpr method = CreateConcatMemberExpression ().Resolve (ec) as MethodGroupExpr;
3387                         if (method == null)
3388                                 return null;
3389
3390                         method = method.OverloadResolve (ec, ref concat_args, false, loc);
3391                         if (method == null)
3392                                 return null;
3393
3394                         add_args.Add (new Argument (method.CreateExpressionTree (ec)));
3395
3396                         Expression expr = CreateExpressionFactoryCall ("Add", add_args);
3397                         if (++pos == arguments.Count)
3398                                 return expr;
3399
3400                         left = new Argument (new EmptyExpression (method.Type));
3401                         return CreateExpressionAddCall (ec, left, expr, pos);
3402                 }
3403
3404                 public override Expression DoResolve (EmitContext ec)
3405                 {
3406                         return this;
3407                 }
3408                 
3409                 public void Append (EmitContext ec, Expression operand)
3410                 {
3411                         //
3412                         // Constant folding
3413                         //
3414                         StringConstant sc = operand as StringConstant;
3415                         if (sc != null) {
3416                                 if (arguments.Count != 0) {
3417                                         Argument last_argument = (Argument) arguments [arguments.Count - 1];
3418                                         StringConstant last_expr_constant = last_argument.Expr as StringConstant;
3419                                         if (last_expr_constant != null) {
3420                                                 last_argument.Expr = new StringConstant (
3421                                                         last_expr_constant.Value + sc.Value, sc.Location);
3422                                                 return;
3423                                         }
3424                                 }
3425                         } else {
3426                                 //
3427                                 // Multiple (3+) concatenation are resolved as multiple StringConcat instances
3428                                 //
3429                                 StringConcat concat_oper = operand as StringConcat;
3430                                 if (concat_oper != null) {
3431                                         arguments.AddRange (concat_oper.arguments);
3432                                         return;
3433                                 }
3434                         }
3435
3436                         arguments.Add (new Argument (operand));
3437                 }
3438
3439                 Expression CreateConcatMemberExpression ()
3440                 {
3441                         return new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "String", loc), "Concat", loc);
3442                 }
3443
3444                 public override void Emit (EmitContext ec)
3445                 {
3446                         Expression concat = new Invocation (CreateConcatMemberExpression (), arguments, true);
3447                         concat = concat.Resolve (ec);
3448                         if (concat != null)
3449                                 concat.Emit (ec);
3450                 }
3451         }
3452
3453         //
3454         // Object created with +/= on delegates
3455         //
3456         public class BinaryDelegate : Expression {
3457                 MethodInfo method;
3458                 ArrayList  args;
3459
3460                 public BinaryDelegate (Type t, MethodInfo mi, ArrayList args)
3461                 {
3462                         method = mi;
3463                         this.args = args;
3464                         type = t;
3465                         eclass = ExprClass.Value;
3466                 }
3467
3468                 public override Expression DoResolve (EmitContext ec)
3469                 {
3470                         return this;
3471                 }
3472
3473                 public override void Emit (EmitContext ec)
3474                 {
3475                         ILGenerator ig = ec.ig;
3476                         
3477                         Invocation.EmitArguments (ec, args, false, null);
3478                         
3479                         ig.Emit (OpCodes.Call, (MethodInfo) method);
3480                         ig.Emit (OpCodes.Castclass, type);
3481                 }
3482
3483                 public Expression Right {
3484                         get {
3485                                 Argument arg = (Argument) args [1];
3486                                 return arg.Expr;
3487                         }
3488                 }
3489
3490                 public bool IsAddition {
3491                         get {
3492                                 return method == TypeManager.delegate_combine_delegate_delegate;
3493                         }
3494                 }
3495         }
3496         
3497         //
3498         // User-defined conditional logical operator
3499         //
3500         public class ConditionalLogicalOperator : UserOperatorCall {
3501                 readonly bool is_and;
3502                 Expression oper;
3503
3504                 public ConditionalLogicalOperator (MethodGroupExpr oper_method, ArrayList arguments,
3505                         ExpressionTreeExpression expr_tree, bool is_and, Location loc)
3506                         : base (oper_method, arguments, expr_tree, loc)
3507                 {
3508                         this.is_and = is_and;
3509                 }
3510                 
3511                 public override Expression DoResolve (EmitContext ec)
3512                 {
3513                         MethodInfo method = (MethodInfo)mg;
3514                         type = TypeManager.TypeToCoreType (method.ReturnType);
3515                         ParameterData pd = TypeManager.GetParameterData (method);
3516                         if (!TypeManager.IsEqual (type, type) || !TypeManager.IsEqual (type, pd.Types [0]) || !TypeManager.IsEqual (type, pd.Types [1])) {
3517                                 Report.Error (217, loc,
3518                                         "A user-defined operator `{0}' must have parameters and return values of the same type in order to be applicable as a short circuit operator",
3519                                         TypeManager.CSharpSignature (method));
3520                                 return null;
3521                         }
3522
3523                         Expression left_dup = new EmptyExpression (type);
3524                         Expression op_true = GetOperatorTrue (ec, left_dup, loc);
3525                         Expression op_false = GetOperatorFalse (ec, left_dup, loc);
3526                         if (op_true == null || op_false == null) {
3527                                 Report.Error (218, loc,
3528                                         "The type `{0}' must have operator `true' and operator `false' defined when `{1}' is used as a short circuit operator",
3529                                         TypeManager.CSharpName (type), TypeManager.CSharpSignature (method));
3530                                 return null;
3531                         }
3532
3533                         oper = is_and ? op_false : op_true;
3534                         eclass = ExprClass.Value;
3535                         return this;
3536                 }
3537
3538                 public override void Emit (EmitContext ec)
3539                 {
3540                         ILGenerator ig = ec.ig;
3541                         Label end_target = ig.DefineLabel ();
3542
3543                         //
3544                         // Emit and duplicate left argument
3545                         //
3546                         ((Argument)arguments [0]).Expr.Emit (ec);
3547                         ig.Emit (OpCodes.Dup);
3548                         arguments.RemoveAt (0);
3549
3550                         oper.EmitBranchable (ec, end_target, true);
3551                         base.Emit (ec);
3552                         ig.MarkLabel (end_target);
3553                 }
3554         }
3555
3556         public class PointerArithmetic : Expression {
3557                 Expression left, right;
3558                 bool is_add;
3559
3560                 //
3561                 // We assume that `l' is always a pointer
3562                 //
3563                 public PointerArithmetic (bool is_addition, Expression l, Expression r, Type t, Location loc)
3564                 {
3565                         type = t;
3566                         this.loc = loc;
3567                         left = l;
3568                         right = r;
3569                         is_add = is_addition;
3570                 }
3571
3572                 public override Expression DoResolve (EmitContext ec)
3573                 {
3574                         eclass = ExprClass.Variable;
3575                         
3576                         if (left.Type == TypeManager.void_ptr_type) {
3577                                 Error (242, "The operation in question is undefined on void pointers");
3578                                 return null;
3579                         }
3580                         
3581                         return this;
3582                 }
3583
3584                 public override void Emit (EmitContext ec)
3585                 {
3586                         Type op_type = left.Type;
3587                         ILGenerator ig = ec.ig;
3588                         
3589                         // It must be either array or fixed buffer
3590                         Type element = TypeManager.HasElementType (op_type) ?
3591                                 element = TypeManager.GetElementType (op_type) :
3592                                 element = AttributeTester.GetFixedBuffer (((FieldExpr)left).FieldInfo).ElementType;
3593
3594                         int size = GetTypeSize (element);
3595                         Type rtype = right.Type;
3596                         
3597                         if (rtype.IsPointer){
3598                                 //
3599                                 // handle (pointer - pointer)
3600                                 //
3601                                 left.Emit (ec);
3602                                 right.Emit (ec);
3603                                 ig.Emit (OpCodes.Sub);
3604
3605                                 if (size != 1){
3606                                         if (size == 0)
3607                                                 ig.Emit (OpCodes.Sizeof, element);
3608                                         else 
3609                                                 IntLiteral.EmitInt (ig, size);
3610                                         ig.Emit (OpCodes.Div);
3611                                 }
3612                                 ig.Emit (OpCodes.Conv_I8);
3613                         } else {
3614                                 //
3615                                 // handle + and - on (pointer op int)
3616                                 //
3617                                 left.Emit (ec);
3618                                 ig.Emit (OpCodes.Conv_I);
3619
3620                                 Constant right_const = right as Constant;
3621                                 if (right_const != null && size != 0) {
3622                                         Expression ex = ConstantFold.BinaryFold (ec, Binary.Operator.Multiply, new IntConstant (size, right.Location), right_const, loc);
3623                                         if (ex == null)
3624                                                 return;
3625                                         ex.Emit (ec);
3626                                 } else {
3627                                         right.Emit (ec);
3628                                         if (size != 1){
3629                                                 if (size == 0)
3630                                                         ig.Emit (OpCodes.Sizeof, element);
3631                                                 else 
3632                                                         IntLiteral.EmitInt (ig, size);
3633                                                 if (rtype == TypeManager.int64_type)
3634                                                         ig.Emit (OpCodes.Conv_I8);
3635                                                 else if (rtype == TypeManager.uint64_type)
3636                                                         ig.Emit (OpCodes.Conv_U8);
3637                                                 ig.Emit (OpCodes.Mul);
3638                                         }
3639                                 }
3640                                 
3641                                 if (rtype == TypeManager.int64_type || rtype == TypeManager.uint64_type)
3642                                         ig.Emit (OpCodes.Conv_I);
3643                                 
3644                                 if (is_add)
3645                                         ig.Emit (OpCodes.Add);
3646                                 else
3647                                         ig.Emit (OpCodes.Sub);
3648                         }
3649                 }
3650         }
3651         
3652         /// <summary>
3653         ///   Implements the ternary conditional operator (?:)
3654         /// </summary>
3655         public class Conditional : Expression {
3656                 Expression expr, true_expr, false_expr;
3657                 
3658                 public Conditional (Expression expr, Expression true_expr, Expression false_expr)
3659                 {
3660                         this.expr = expr;
3661                         this.true_expr = true_expr;
3662                         this.false_expr = false_expr;
3663                         this.loc = expr.Location;
3664                 }
3665
3666                 public Expression Expr {
3667                         get {
3668                                 return expr;
3669                         }
3670                 }
3671
3672                 public Expression TrueExpr {
3673                         get {
3674                                 return true_expr;
3675                         }
3676                 }
3677
3678                 public Expression FalseExpr {
3679                         get {
3680                                 return false_expr;
3681                         }
3682                 }
3683
3684                 public override Expression CreateExpressionTree (EmitContext ec)
3685                 {
3686                         ArrayList args = new ArrayList (3);
3687                         args.Add (new Argument (expr.CreateExpressionTree (ec)));
3688                         args.Add (new Argument (true_expr.CreateExpressionTree (ec)));
3689                         args.Add (new Argument (false_expr.CreateExpressionTree (ec)));
3690                         return CreateExpressionFactoryCall ("Condition", args);
3691                 }
3692
3693                 public override Expression DoResolve (EmitContext ec)
3694                 {
3695                         expr = expr.Resolve (ec);
3696
3697                         if (expr == null)
3698                                 return null;
3699
3700                         if (expr.Type != TypeManager.bool_type){
3701                                 expr = Expression.ResolveBoolean (
3702                                         ec, expr, loc);
3703                                 
3704                                 if (expr == null)
3705                                         return null;
3706                         }
3707                         
3708                         Assign ass = expr as Assign;
3709                         if (ass != null && ass.Source is Constant) {
3710                                 Report.Warning (665, 3, loc, "Assignment in conditional expression is always constant; did you mean to use == instead of = ?");
3711                         }
3712
3713                         true_expr = true_expr.Resolve (ec);
3714                         false_expr = false_expr.Resolve (ec);
3715
3716                         if (true_expr == null || false_expr == null)
3717                                 return null;
3718
3719                         eclass = ExprClass.Value;
3720                         if (true_expr.Type == false_expr.Type) {
3721                                 type = true_expr.Type;
3722                                 if (type == TypeManager.null_type) {
3723                                         // TODO: probably will have to implement ConditionalConstant
3724                                         // to call method without return constant as well
3725                                         Report.Warning (-101, 1, loc, "Conditional expression will always return same value");
3726                                         return true_expr;
3727                                 }
3728                         } else {
3729                                 Expression conv;
3730                                 Type true_type = true_expr.Type;
3731                                 Type false_type = false_expr.Type;
3732
3733                                 //
3734                                 // First, if an implicit conversion exists from true_expr
3735                                 // to false_expr, then the result type is of type false_expr.Type
3736                                 //
3737                                 conv = Convert.ImplicitConversion (ec, true_expr, false_type, loc);
3738                                 if (conv != null){
3739                                         //
3740                                         // Check if both can convert implicitl to each other's type
3741                                         //
3742                                         if (Convert.ImplicitConversion (ec, false_expr, true_type, loc) != null){
3743                                                 Error (172,
3744                                                        "Can not compute type of conditional expression " +
3745                                                        "as `" + TypeManager.CSharpName (true_expr.Type) +
3746                                                        "' and `" + TypeManager.CSharpName (false_expr.Type) +
3747                                                        "' convert implicitly to each other");
3748                                                 return null;
3749                                         }
3750                                         type = false_type;
3751                                         true_expr = conv;
3752                                 } else if ((conv = Convert.ImplicitConversion(ec, false_expr, true_type,loc))!= null){
3753                                         type = true_type;
3754                                         false_expr = conv;
3755                                 } else {
3756                                         Report.Error (173, loc, "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'",
3757                                                 true_expr.GetSignatureForError (), false_expr.GetSignatureForError ());
3758                                         return null;
3759                                 }
3760                         }
3761
3762                         // Dead code optimalization
3763                         if (expr is BoolConstant){
3764                                 BoolConstant bc = (BoolConstant) expr;
3765
3766                                 Report.Warning (429, 4, bc.Value ? false_expr.Location : true_expr.Location, "Unreachable expression code detected");
3767                                 return bc.Value ? true_expr : false_expr;
3768                         }
3769
3770                         return this;
3771                 }
3772
3773                 public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
3774                 {
3775                         return null;
3776                 }
3777
3778                 public override void Emit (EmitContext ec)
3779                 {
3780                         ILGenerator ig = ec.ig;
3781                         Label false_target = ig.DefineLabel ();
3782                         Label end_target = ig.DefineLabel ();
3783
3784                         expr.EmitBranchable (ec, false_target, false);
3785                         true_expr.Emit (ec);
3786
3787                         if (type.IsInterface) {
3788                                 LocalBuilder temp = ec.GetTemporaryLocal (type);
3789                                 ig.Emit (OpCodes.Stloc, temp);
3790                                 ig.Emit (OpCodes.Ldloc, temp);
3791                                 ec.FreeTemporaryLocal (temp, type);
3792                         }
3793
3794                         ig.Emit (OpCodes.Br, end_target);
3795                         ig.MarkLabel (false_target);
3796                         false_expr.Emit (ec);
3797                         ig.MarkLabel (end_target);
3798                 }
3799
3800                 protected override void CloneTo (CloneContext clonectx, Expression t)
3801                 {
3802                         Conditional target = (Conditional) t;
3803
3804                         target.expr = expr.Clone (clonectx);
3805                         target.true_expr = true_expr.Clone (clonectx);
3806                         target.false_expr = false_expr.Clone (clonectx);
3807                 }
3808         }
3809
3810         public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation {
3811                 bool prepared;
3812                 LocalTemporary temp;
3813
3814                 public abstract Variable Variable {
3815                         get;
3816                 }
3817
3818                 public abstract bool IsRef {
3819                         get;
3820                 }
3821
3822                 public override void Emit (EmitContext ec)
3823                 {
3824                         Emit (ec, false);
3825                 }
3826
3827                 //
3828                 // This method is used by parameters that are references, that are
3829                 // being passed as references:  we only want to pass the pointer (that
3830                 // is already stored in the parameter, not the address of the pointer,
3831                 // and not the value of the variable).
3832                 //
3833                 public void EmitLoad (EmitContext ec)
3834                 {
3835                         Report.Debug (64, "VARIABLE EMIT LOAD", this, Variable, type, loc);
3836                         if (!prepared)
3837                                 Variable.EmitInstance (ec);
3838                         Variable.Emit (ec);
3839                 }
3840                 
3841                 public void Emit (EmitContext ec, bool leave_copy)
3842                 {
3843                         Report.Debug (64, "VARIABLE EMIT", this, Variable, type, IsRef, loc);
3844
3845                         EmitLoad (ec);
3846
3847                         if (IsRef) {
3848                                 //
3849                                 // If we are a reference, we loaded on the stack a pointer
3850                                 // Now lets load the real value
3851                                 //
3852                                 LoadFromPtr (ec.ig, type);
3853                         }
3854
3855                         if (leave_copy) {
3856                                 ec.ig.Emit (OpCodes.Dup);
3857
3858                                 if (IsRef || Variable.NeedsTemporary) {
3859                                         temp = new LocalTemporary (Type);
3860                                         temp.Store (ec);
3861                                 }
3862                         }
3863                 }
3864
3865                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
3866                                         bool prepare_for_load)
3867                 {
3868                         Report.Debug (64, "VARIABLE EMIT ASSIGN", this, Variable, type, IsRef,
3869                                       source, loc);
3870
3871                         ILGenerator ig = ec.ig;
3872                         prepared = prepare_for_load;
3873
3874                         Variable.EmitInstance (ec);
3875                         if (prepare_for_load) {
3876                                 if (Variable.HasInstance)
3877                                         ig.Emit (OpCodes.Dup);
3878                         }
3879
3880                         if (IsRef)
3881                                 Variable.Emit (ec);
3882
3883                         source.Emit (ec);
3884
3885                         // HACK: variable is already emitted when source is an initializer 
3886                         if (source is NewInitialize)
3887                                 return;
3888
3889                         if (leave_copy) {
3890                                 ig.Emit (OpCodes.Dup);
3891                                 if (IsRef || Variable.NeedsTemporary) {
3892                                         temp = new LocalTemporary (Type);
3893                                         temp.Store (ec);
3894                                 }
3895                         }
3896
3897                         if (IsRef)
3898                                 StoreFromPtr (ig, type);
3899                         else
3900                                 Variable.EmitAssign (ec);
3901
3902                         if (temp != null) {
3903                                 temp.Emit (ec);
3904                                 temp.Release (ec);
3905                         }
3906                 }
3907                 
3908                 public void AddressOf (EmitContext ec, AddressOp mode)
3909                 {
3910                         Variable.EmitInstance (ec);
3911                         Variable.EmitAddressOf (ec);
3912                 }
3913         }
3914
3915         /// <summary>
3916         ///   Local variables
3917         /// </summary>
3918         public class LocalVariableReference : VariableReference, IVariable {
3919                 public readonly string Name;
3920                 public Block Block;
3921                 public LocalInfo local_info;
3922                 bool is_readonly;
3923                 Variable variable;
3924
3925                 public LocalVariableReference (Block block, string name, Location l)
3926                 {
3927                         Block = block;
3928                         Name = name;
3929                         loc = l;
3930                         eclass = ExprClass.Variable;
3931                 }
3932
3933                 //
3934                 // Setting `is_readonly' to false will allow you to create a writable
3935                 // reference to a read-only variable.  This is used by foreach and using.
3936                 //
3937                 public LocalVariableReference (Block block, string name, Location l,
3938                                                LocalInfo local_info, bool is_readonly)
3939                         : this (block, name, l)
3940                 {
3941                         this.local_info = local_info;
3942                         this.is_readonly = is_readonly;
3943                 }
3944
3945                 public VariableInfo VariableInfo {
3946                         get { return local_info.VariableInfo; }
3947                 }
3948
3949                 public override bool IsRef {
3950                         get { return false; }
3951                 }
3952
3953                 public bool IsReadOnly {
3954                         get { return is_readonly; }
3955                 }
3956
3957                 public bool VerifyAssigned (EmitContext ec)
3958                 {
3959                         VariableInfo variable_info = local_info.VariableInfo;
3960                         return variable_info == null || variable_info.IsAssigned (ec, loc);
3961                 }
3962
3963                 void ResolveLocalInfo ()
3964                 {
3965                         if (local_info == null) {
3966                                 local_info = Block.GetLocalInfo (Name);
3967                                 type = local_info.VariableType;
3968                                 is_readonly = local_info.ReadOnly;
3969                         }
3970                 }
3971
3972                 public override Expression CreateExpressionTree (EmitContext ec)
3973                 {
3974                         ArrayList arg = new ArrayList (1);
3975                         arg.Add (new Argument (this));
3976                         return CreateExpressionFactoryCall ("Constant", arg);
3977                 }
3978
3979                 protected Expression DoResolveBase (EmitContext ec)
3980                 {
3981                         type = local_info.VariableType;
3982
3983                         Expression e = Block.GetConstantExpression (Name);
3984                         if (e != null)
3985                                 return e.Resolve (ec);
3986
3987                         if (!VerifyAssigned (ec))
3988                                 return null;
3989
3990                         //
3991                         // If we are referencing a variable from the external block
3992                         // flag it for capturing
3993                         //
3994                         if (ec.MustCaptureVariable (local_info)) {
3995                                 if (local_info.AddressTaken){
3996                                         AnonymousMethod.Error_AddressOfCapturedVar (local_info.Name, loc);
3997                                         return null;
3998                                 }
3999
4000                                 if (!ec.IsInProbingMode)
4001                                 {
4002                                         ScopeInfo scope = local_info.Block.CreateScopeInfo ();
4003                                         variable = scope.AddLocal (local_info);
4004                                         type = variable.Type;
4005                                 }
4006                         }
4007
4008                         return this;
4009                 }
4010
4011                 public override Expression DoResolve (EmitContext ec)
4012                 {
4013                         ResolveLocalInfo ();
4014                         local_info.Used = true;
4015
4016                         if (type == null && local_info.Type is VarExpr) {
4017                             local_info.VariableType = TypeManager.object_type;
4018                                 Error_VariableIsUsedBeforeItIsDeclared (Name);
4019                             return null;
4020                         }
4021                         
4022                         return DoResolveBase (ec);
4023                 }
4024
4025                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
4026                 {
4027                         ResolveLocalInfo ();
4028
4029                         // is out param
4030                         if (right_side == EmptyExpression.OutAccess)
4031                                 local_info.Used = true;
4032
4033                         // Infer implicitly typed local variable
4034                         if (type == null) {
4035                                 VarExpr ve = local_info.Type as VarExpr;
4036                                 if (ve != null) {
4037                                         ve.DoResolveLValue (ec, right_side);
4038                                         type = local_info.VariableType = ve.Type;
4039                                 }
4040                         }
4041                                                 
4042                         if (is_readonly) {
4043                                 int code;
4044                                 string msg;
4045                                 if (right_side == EmptyExpression.OutAccess) {
4046                                         code = 1657; msg = "Cannot pass `{0}' as a ref or out argument because it is a `{1}'";
4047                                 } else if (right_side == EmptyExpression.LValueMemberAccess) {
4048                                         code = 1654; msg = "Cannot assign to members of `{0}' because it is a `{1}'";
4049                                 } else if (right_side == EmptyExpression.LValueMemberOutAccess) {
4050                                         code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'";
4051                                 } else {
4052                                         code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'";
4053                                 }
4054                                 Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ());
4055                                 return null;
4056                         }
4057
4058                         if (VariableInfo != null)
4059                                 VariableInfo.SetAssigned (ec);
4060
4061                         return DoResolveBase (ec);
4062                 }
4063
4064                 public bool VerifyFixed ()
4065                 {
4066                         // A local Variable is always fixed.
4067                         return true;
4068                 }
4069
4070                 public override int GetHashCode ()
4071                 {
4072                         return Name.GetHashCode ();
4073                 }
4074
4075                 public override bool Equals (object obj)
4076                 {
4077                         LocalVariableReference lvr = obj as LocalVariableReference;
4078                         if (lvr == null)
4079                                 return false;
4080
4081                         return Name == lvr.Name && Block == lvr.Block;
4082                 }
4083
4084                 public override Variable Variable {
4085                         get { return variable != null ? variable : local_info.Variable; }
4086                 }
4087
4088                 public override string ToString ()
4089                 {
4090                         return String.Format ("{0} ({1}:{2})", GetType (), Name, loc);
4091                 }
4092
4093                 protected override void CloneTo (CloneContext clonectx, Expression t)
4094                 {
4095                         LocalVariableReference target = (LocalVariableReference) t;
4096                         
4097                         target.Block = clonectx.LookupBlock (Block);
4098                         if (local_info != null)
4099                                 target.local_info = clonectx.LookupVariable (local_info);
4100                 }
4101         }
4102
4103         /// <summary>
4104         ///   This represents a reference to a parameter in the intermediate
4105         ///   representation.
4106         /// </summary>
4107         public class ParameterReference : VariableReference, IVariable {
4108                 readonly ToplevelParameterInfo pi;
4109                 readonly ToplevelBlock referenced;
4110                 Variable variable;
4111
4112                 public bool is_ref, is_out;
4113
4114                 public bool IsOut {
4115                         get { return is_out; }
4116                 }
4117
4118                 public override bool IsRef {
4119                         get { return is_ref; }
4120                 }
4121
4122                 public string Name {
4123                         get { return Parameter.Name; }
4124                 }
4125
4126                 public Parameter Parameter {
4127                         get { return pi.Parameter; }
4128                 }
4129
4130                 public ParameterReference (ToplevelBlock referenced, ToplevelParameterInfo pi, Location loc)
4131                 {
4132                         this.pi = pi;
4133                         this.referenced = referenced;
4134                         this.loc = loc;
4135                         eclass = ExprClass.Variable;
4136                 }
4137
4138                 public VariableInfo VariableInfo {
4139                         get { return pi.VariableInfo; }
4140                 }
4141
4142                 public override Variable Variable {
4143                         get { return variable != null ? variable : Parameter.Variable; }
4144                 }
4145
4146                 public bool VerifyFixed ()
4147                 {
4148                         // A parameter is fixed if it's a value parameter (i.e., no modifier like out, ref, param).
4149                         return Parameter.ModFlags == Parameter.Modifier.NONE;
4150                 }
4151
4152                 public bool IsAssigned (EmitContext ec, Location loc)
4153                 {
4154                         // HACK: Variables are not captured in probing mode
4155                         if (ec.IsInProbingMode)
4156                                 return true;
4157                         
4158                         if (!ec.DoFlowAnalysis || !is_out || ec.CurrentBranching.IsAssigned (VariableInfo))
4159                                 return true;
4160
4161                         Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name);
4162                         return false;
4163                 }
4164
4165                 public bool IsFieldAssigned (EmitContext ec, string field_name, Location loc)
4166                 {
4167                         if (!ec.DoFlowAnalysis || !is_out || ec.CurrentBranching.IsFieldAssigned (VariableInfo, field_name))
4168                                 return true;
4169
4170                         Report.Error (170, loc, "Use of possibly unassigned field `{0}'", field_name);
4171                         return false;
4172                 }
4173
4174                 public void SetAssigned (EmitContext ec)
4175                 {
4176                         if (is_out && ec.DoFlowAnalysis)
4177                                 ec.CurrentBranching.SetAssigned (VariableInfo);
4178                 }
4179
4180                 public void SetFieldAssigned (EmitContext ec, string field_name)
4181                 {
4182                         if (is_out && ec.DoFlowAnalysis)
4183                                 ec.CurrentBranching.SetFieldAssigned (VariableInfo, field_name);
4184                 }
4185
4186                 protected bool DoResolveBase (EmitContext ec)
4187                 {
4188                         Parameter par = Parameter;
4189                         if (!par.Resolve (ec)) {
4190                                 //TODO:
4191                         }
4192
4193                         type = par.ParameterType;
4194                         Parameter.Modifier mod = par.ModFlags;
4195                         is_ref = (mod & Parameter.Modifier.ISBYREF) != 0;
4196                         is_out = (mod & Parameter.Modifier.OUT) == Parameter.Modifier.OUT;
4197                         eclass = ExprClass.Variable;
4198
4199                         AnonymousContainer am = ec.CurrentAnonymousMethod;
4200                         if (am == null)
4201                                 return true;
4202
4203                         ToplevelBlock declared = pi.Block;
4204                         if (is_ref && declared != referenced) {
4205                                 Report.Error (1628, Location,
4206                                               "Cannot use ref or out parameter `{0}' inside an " +
4207                                               "anonymous method block", par.Name);
4208                                 return false;
4209                         }
4210
4211                         if (!am.IsIterator && declared == referenced)
4212                                 return true;
4213
4214                         // Don't capture aruments when the probing is on
4215                         if (!ec.IsInProbingMode) {
4216                                 ScopeInfo scope = declared.CreateScopeInfo ();
4217                                 variable = scope.AddParameter (par, pi.Index);
4218                                 type = variable.Type;
4219                         }
4220                         return true;
4221                 }
4222
4223                 public override int GetHashCode ()
4224                 {
4225                         return Name.GetHashCode ();
4226                 }
4227
4228                 public override bool Equals (object obj)
4229                 {
4230                         ParameterReference pr = obj as ParameterReference;
4231                         if (pr == null)
4232                                 return false;
4233
4234                         return Name == pr.Name && referenced == pr.referenced;
4235                 }
4236
4237                 public override Expression CreateExpressionTree (EmitContext ec)
4238                 {
4239                         return Parameter.ExpressionTreeVariableReference ();
4240                 }
4241
4242                 //
4243                 // Notice that for ref/out parameters, the type exposed is not the
4244                 // same type exposed externally.
4245                 //
4246                 // for "ref int a":
4247                 //   externally we expose "int&"
4248                 //   here we expose       "int".
4249                 //
4250                 // We record this in "is_ref".  This means that the type system can treat
4251                 // the type as it is expected, but when we generate the code, we generate
4252                 // the alternate kind of code.
4253                 //
4254                 public override Expression DoResolve (EmitContext ec)
4255                 {
4256                         if (!DoResolveBase (ec))
4257                                 return null;
4258
4259                         if (is_out && ec.DoFlowAnalysis &&
4260                             (!ec.OmitStructFlowAnalysis || !VariableInfo.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
4261                                 return null;
4262
4263                         return this;
4264                 }
4265
4266                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
4267                 {
4268                         if (!DoResolveBase (ec))
4269                                 return null;
4270
4271                         // HACK: parameters are not captured when probing is on
4272                         if (!ec.IsInProbingMode)
4273                                 SetAssigned (ec);
4274
4275                         return this;
4276                 }
4277
4278                 static public void EmitLdArg (ILGenerator ig, int x)
4279                 {
4280                         if (x <= 255){
4281                                 switch (x){
4282                                 case 0: ig.Emit (OpCodes.Ldarg_0); break;
4283                                 case 1: ig.Emit (OpCodes.Ldarg_1); break;
4284                                 case 2: ig.Emit (OpCodes.Ldarg_2); break;
4285                                 case 3: ig.Emit (OpCodes.Ldarg_3); break;
4286                                 default: ig.Emit (OpCodes.Ldarg_S, (byte) x); break;
4287                                 }
4288                         } else
4289                                 ig.Emit (OpCodes.Ldarg, x);
4290                 }
4291                 
4292                 public override string ToString ()
4293                 {
4294                         return "ParameterReference[" + Name + "]";
4295                 }
4296         }
4297         
4298         /// <summary>
4299         ///   Used for arguments to New(), Invocation()
4300         /// </summary>
4301         public class Argument {
4302                 public enum AType : byte {
4303                         Expression,
4304                         Ref,
4305                         Out,
4306                         ArgList
4307                 };
4308
4309                 public static readonly Argument[] Empty = new Argument [0];
4310
4311                 public readonly AType ArgType;
4312                 public Expression Expr;
4313                 
4314                 public Argument (Expression expr, AType type)
4315                 {
4316                         this.Expr = expr;
4317                         this.ArgType = type;
4318                 }
4319
4320                 public Argument (Expression expr)
4321                 {
4322                         this.Expr = expr;
4323                         this.ArgType = AType.Expression;
4324                 }
4325
4326                 public Type Type {
4327                         get {
4328                                 if (ArgType == AType.Ref || ArgType == AType.Out)
4329                                         return TypeManager.GetReferenceType (Expr.Type);
4330                                 else
4331                                         return Expr.Type;
4332                         }
4333                 }
4334
4335                 public Parameter.Modifier Modifier
4336                 {
4337                         get {
4338                                 switch (ArgType) {
4339                                         case AType.Out:
4340                                                 return Parameter.Modifier.OUT;
4341
4342                                         case AType.Ref:
4343                                                 return Parameter.Modifier.REF;
4344
4345                                         default:
4346                                                 return Parameter.Modifier.NONE;
4347                                 }
4348                         }
4349                 }
4350
4351                 public string GetSignatureForError ()
4352                 {
4353                         if (Expr.eclass == ExprClass.MethodGroup)
4354                                 return Expr.ExprClassName;
4355
4356                         return Expr.GetSignatureForError ();
4357                 }               
4358
4359                 public bool ResolveMethodGroup (EmitContext ec)
4360                 {
4361                         SimpleName sn = Expr as SimpleName;
4362                         if (sn != null)
4363                                 Expr = sn.GetMethodGroup ();
4364
4365                         // FIXME: csc doesn't report any error if you try to use `ref' or
4366                         //        `out' in a delegate creation expression.
4367                         Expr = Expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
4368                         if (Expr == null)
4369                                 return false;
4370
4371                         return true;
4372                 }
4373
4374                 public bool Resolve (EmitContext ec, Location loc)
4375                 {
4376                         using (ec.With (EmitContext.Flags.DoFlowAnalysis, true)) {
4377                                 // Verify that the argument is readable
4378                                 if (ArgType != AType.Out)
4379                                         Expr = Expr.Resolve (ec);
4380
4381                                 // Verify that the argument is writeable
4382                                 if (Expr != null && (ArgType == AType.Out || ArgType == AType.Ref))
4383                                         Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess, loc);
4384
4385                                 return Expr != null;
4386                         }
4387                 }
4388
4389                 public void Emit (EmitContext ec)
4390                 {
4391                         if (ArgType != AType.Ref && ArgType != AType.Out) {
4392                                 Expr.Emit (ec);
4393                                 return;
4394                         }
4395
4396                         AddressOp mode = AddressOp.Store;
4397                         if (ArgType == AType.Ref)
4398                                 mode |= AddressOp.Load;
4399                                 
4400                         IMemoryLocation ml = (IMemoryLocation) Expr;
4401                         ParameterReference pr = ml as ParameterReference;
4402
4403                         //
4404                         // ParameterReferences might already be references, so we want
4405                         // to pass just the value
4406                         //
4407                         if (pr != null && pr.IsRef)
4408                                 pr.EmitLoad (ec);
4409                         else
4410                                 ml.AddressOf (ec, mode);
4411                 }
4412
4413                 public Argument Clone (CloneContext clonectx)
4414                 {
4415                         return new Argument (Expr.Clone (clonectx), ArgType);
4416                 }
4417         }
4418
4419         /// <summary>
4420         ///   Invocation of methods or delegates.
4421         /// </summary>
4422         public class Invocation : ExpressionStatement {
4423                 protected ArrayList Arguments;
4424                 protected Expression expr;
4425                 protected MethodGroupExpr mg;
4426                 bool arguments_resolved;
4427                 
4428                 //
4429                 // arguments is an ArrayList, but we do not want to typecast,
4430                 // as it might be null.
4431                 //
4432                 public Invocation (Expression expr, ArrayList arguments)
4433                 {
4434                         SimpleName sn = expr as SimpleName;
4435                         if (sn != null)
4436                                 this.expr = sn.GetMethodGroup ();
4437                         else
4438                                 this.expr = expr;
4439                         
4440                         Arguments = arguments;
4441                         if (expr != null)
4442                                 loc = expr.Location;
4443                 }
4444
4445                 public Invocation (Expression expr, ArrayList arguments, bool arguments_resolved)
4446                         : this (expr, arguments)
4447                 {
4448                         this.arguments_resolved = arguments_resolved;
4449                 }
4450
4451                 public override Expression CreateExpressionTree (EmitContext ec)
4452                 {
4453                         ArrayList args;
4454
4455                         //
4456                         // Special conversion for nested expression trees
4457                         //
4458                         if (TypeManager.DropGenericTypeArguments (type) == TypeManager.expression_type) {
4459                                 args = new ArrayList (1);
4460                                 args.Add (new Argument (this));
4461                                 return CreateExpressionFactoryCall ("Quote", args);
4462                         }
4463
4464                         args = new ArrayList (Arguments.Count + 3);
4465                         if (mg.IsInstance)
4466                                 args.Add (new Argument (mg.InstanceExpression.CreateExpressionTree (ec)));
4467                         else
4468                                 args.Add (new Argument (new NullLiteral (loc).CreateExpressionTree (ec)));
4469
4470                         args.Add (new Argument (mg.CreateExpressionTree (ec)));
4471                         foreach (Argument a in Arguments) {
4472                                 Expression e = a.Expr.CreateExpressionTree (ec);
4473                                 if (e != null)
4474                                         args.Add (new Argument (e));
4475                         }
4476
4477                         return CreateExpressionFactoryCall ("Call", args);
4478                 }
4479
4480                 public override Expression DoResolve (EmitContext ec)
4481                 {
4482                         // Don't resolve already resolved expression
4483                         if (eclass != ExprClass.Invalid)
4484                                 return this;
4485                         
4486                         Expression expr_resolved = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
4487                         if (expr_resolved == null)
4488                                 return null;
4489
4490                         mg = expr_resolved as MethodGroupExpr;
4491                         if (mg == null) {
4492                                 Type expr_type = expr_resolved.Type;
4493
4494                                 if (expr_type != null && TypeManager.IsDelegateType (expr_type)){
4495                                         return (new DelegateInvocation (
4496                                                 expr_resolved, Arguments, loc)).Resolve (ec);
4497                                 }
4498
4499                                 MemberExpr me = expr_resolved as MemberExpr;
4500                                 if (me == null) {
4501                                         expr_resolved.Error_UnexpectedKind (ResolveFlags.MethodGroup, loc);
4502                                         return null;
4503                                 }
4504                                 
4505                                 mg = ec.TypeContainer.LookupExtensionMethod (me.Type, me.Name, loc);
4506                                 if (mg == null) {
4507                                         Report.Error (1955, loc, "The member `{0}' cannot be used as method or delegate",
4508                                                 expr_resolved.GetSignatureForError ());
4509                                         return null;
4510                                 }
4511
4512                                 ((ExtensionMethodGroupExpr)mg).ExtensionExpression = me.InstanceExpression;
4513                         }
4514
4515                         //
4516                         // Next, evaluate all the expressions in the argument list
4517                         //
4518                         if (Arguments != null && !arguments_resolved) {
4519                                 for (int i = 0; i < Arguments.Count; ++i)
4520                                 {
4521                                         if (!((Argument)Arguments[i]).Resolve(ec, loc))
4522                                                 return null;
4523                                 }
4524                         }
4525
4526                         mg = DoResolveOverload (ec);
4527                         if (mg == null)
4528                                 return null;
4529
4530                         MethodInfo method = (MethodInfo)mg;
4531                         if (method != null) {
4532                                 type = TypeManager.TypeToCoreType (method.ReturnType);
4533
4534                                 // TODO: this is a copy of mg.ResolveMemberAccess method
4535                                 Expression iexpr = mg.InstanceExpression;
4536                                 if (method.IsStatic) {
4537                                         if (iexpr == null ||
4538                                                 iexpr is This || iexpr is EmptyExpression ||
4539                                                 mg.IdenticalTypeName) {
4540                                                 mg.InstanceExpression = null;
4541                                         } else {
4542                                                 MemberExpr.error176 (loc, mg.GetSignatureForError ());
4543                                                 return null;
4544                                         }
4545                                 }
4546                         }
4547
4548                         if (type.IsPointer){
4549                                 if (!ec.InUnsafe){
4550                                         UnsafeError (loc);
4551                                         return null;
4552                                 }
4553                         }
4554                         
4555                         //
4556                         // Only base will allow this invocation to happen.
4557                         //
4558                         if (mg.IsBase && method.IsAbstract){
4559                                 Error_CannotCallAbstractBase (TypeManager.CSharpSignature (method));
4560                                 return null;
4561                         }
4562
4563                         if (Arguments == null && method.DeclaringType == TypeManager.object_type && method.Name == "Finalize") {
4564                                 if (mg.IsBase)
4565                                         Report.Error (250, loc, "Do not directly call your base class Finalize method. It is called automatically from your destructor");
4566                                 else
4567                                         Report.Error (245, loc, "Destructors and object.Finalize cannot be called directly. Consider calling IDisposable.Dispose if available");
4568                                 return null;
4569                         }
4570
4571                         if (IsSpecialMethodInvocation (method)) {
4572                                 return null;
4573                         }
4574                         
4575                         if (mg.InstanceExpression != null)
4576                                 mg.InstanceExpression.CheckMarshalByRefAccess (ec);
4577
4578                         eclass = ExprClass.Value;
4579                         return this;
4580                 }
4581
4582                 protected virtual MethodGroupExpr DoResolveOverload (EmitContext ec)
4583                 {
4584                         return mg.OverloadResolve (ec, ref Arguments, false, loc);
4585                 }
4586
4587                 bool IsSpecialMethodInvocation (MethodBase method)
4588                 {
4589                         if (!TypeManager.IsSpecialMethod (method))
4590                                 return false;
4591
4592                         Report.SymbolRelatedToPreviousError (method);
4593                         Report.Error (571, loc, "`{0}': cannot explicitly call operator or accessor",
4594                                 TypeManager.CSharpSignature (method, true));
4595         
4596                         return true;
4597                 }
4598
4599                 /// <summary>
4600                 ///   Emits a list of resolved Arguments that are in the arguments
4601                 ///   ArrayList.
4602                 /// 
4603                 ///   The MethodBase argument might be null if the
4604                 ///   emission of the arguments is known not to contain
4605                 ///   a `params' field (for example in constructors or other routines
4606                 ///   that keep their arguments in this structure)
4607                 ///   
4608                 ///   if `dup_args' is true, a copy of the arguments will be left
4609                 ///   on the stack. If `dup_args' is true, you can specify `this_arg'
4610                 ///   which will be duplicated before any other args. Only EmitCall
4611                 ///   should be using this interface.
4612                 /// </summary>
4613                 public static void EmitArguments (EmitContext ec, ArrayList arguments, bool dup_args, LocalTemporary this_arg)
4614                 {
4615                         if (arguments == null)
4616                                 return;
4617
4618                         int top = arguments.Count;
4619                         LocalTemporary [] temps = null;
4620                         
4621                         if (dup_args && top != 0)
4622                                 temps = new LocalTemporary [top];
4623
4624                         int argument_index = 0;
4625                         Argument a;
4626                         for (int i = 0; i < top; i++) {
4627                                 a = (Argument) arguments [argument_index++];
4628                                 a.Emit (ec);
4629                                 if (dup_args) {
4630                                         ec.ig.Emit (OpCodes.Dup);
4631                                         (temps [i] = new LocalTemporary (a.Type)).Store (ec);
4632                                 }
4633                         }
4634                         
4635                         if (dup_args) {
4636                                 if (this_arg != null)
4637                                         this_arg.Emit (ec);
4638                                 
4639                                 for (int i = 0; i < top; i ++) {
4640                                         temps [i].Emit (ec);
4641                                         temps [i].Release (ec);
4642                                 }
4643                         }
4644                 }
4645
4646                 static Type[] GetVarargsTypes (MethodBase mb, ArrayList arguments)
4647                 {
4648                         ParameterData pd = TypeManager.GetParameterData (mb);
4649
4650                         if (arguments == null)
4651                                 return new Type [0];
4652
4653                         Argument a = (Argument) arguments [pd.Count - 1];
4654                         Arglist list = (Arglist) a.Expr;
4655
4656                         return list.ArgumentTypes;
4657                 }
4658
4659                 /// <summary>
4660                 /// This checks the ConditionalAttribute on the method 
4661                 /// </summary>
4662                 public static bool IsMethodExcluded (MethodBase method)
4663                 {
4664                         if (method.IsConstructor)
4665                                 return false;
4666
4667                         method = TypeManager.DropGenericMethodArguments (method);
4668                         if (method.DeclaringType.Module == CodeGen.Module.Builder) {
4669                                 IMethodData md = TypeManager.GetMethod (method);
4670                                 if (md != null)
4671                                         return md.IsExcluded ();
4672
4673                                 // For some methods (generated by delegate class) GetMethod returns null
4674                                 // because they are not included in builder_to_method table
4675                                 return false;
4676                         }
4677
4678                         return AttributeTester.IsConditionalMethodExcluded (method);
4679                 }
4680
4681                 /// <remarks>
4682                 ///   is_base tells whether we want to force the use of the `call'
4683                 ///   opcode instead of using callvirt.  Call is required to call
4684                 ///   a specific method, while callvirt will always use the most
4685                 ///   recent method in the vtable.
4686                 ///
4687                 ///   is_static tells whether this is an invocation on a static method
4688                 ///
4689                 ///   instance_expr is an expression that represents the instance
4690                 ///   it must be non-null if is_static is false.
4691                 ///
4692                 ///   method is the method to invoke.
4693                 ///
4694                 ///   Arguments is the list of arguments to pass to the method or constructor.
4695                 /// </remarks>
4696                 public static void EmitCall (EmitContext ec, bool is_base,
4697                                              Expression instance_expr,
4698                                              MethodBase method, ArrayList Arguments, Location loc)
4699                 {
4700                         EmitCall (ec, is_base, instance_expr, method, Arguments, loc, false, false);
4701                 }
4702                 
4703                 // `dup_args' leaves an extra copy of the arguments on the stack
4704                 // `omit_args' does not leave any arguments at all.
4705                 // So, basically, you could make one call with `dup_args' set to true,
4706                 // and then another with `omit_args' set to true, and the two calls
4707                 // would have the same set of arguments. However, each argument would
4708                 // only have been evaluated once.
4709                 public static void EmitCall (EmitContext ec, bool is_base,
4710                                              Expression instance_expr,
4711                                              MethodBase method, ArrayList Arguments, Location loc,
4712                                              bool dup_args, bool omit_args)
4713                 {
4714                         ILGenerator ig = ec.ig;
4715                         bool struct_call = false;
4716                         bool this_call = false;
4717                         LocalTemporary this_arg = null;
4718
4719                         Type decl_type = method.DeclaringType;
4720
4721                         if (!ec.IsInObsoleteScope) {
4722                                 //
4723                                 // This checks ObsoleteAttribute on the method and on the declaring type
4724                                 //
4725                                 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (method);
4726                                 if (oa != null)
4727                                         AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (method), loc);
4728
4729                                 oa = AttributeTester.GetObsoleteAttribute (method.DeclaringType);
4730                                 if (oa != null) {
4731                                         AttributeTester.Report_ObsoleteMessage (oa, method.DeclaringType.FullName, loc);
4732                                 }
4733                         }
4734
4735                         if (IsMethodExcluded (method))
4736                                 return;
4737                         
4738                         bool is_static = method.IsStatic;
4739                         if (!is_static){
4740                                 if (instance_expr == EmptyExpression.Null) {
4741                                         SimpleName.Error_ObjectRefRequired (ec, loc, TypeManager.CSharpSignature (method));
4742                                         return;
4743                                 }
4744
4745                                 this_call = instance_expr is This;
4746                                 if (decl_type.IsValueType || (!this_call && instance_expr.Type.IsValueType))
4747                                         struct_call = true;
4748
4749                                 //
4750                                 // If this is ourselves, push "this"
4751                                 //
4752                                 if (!omit_args) {
4753                                         Type t = null;
4754                                         Type iexpr_type = instance_expr.Type;
4755
4756                                         //
4757                                         // Push the instance expression
4758                                         //
4759                                         if (TypeManager.IsValueType (iexpr_type)) {
4760                                                 //
4761                                                 // Special case: calls to a function declared in a 
4762                                                 // reference-type with a value-type argument need
4763                                                 // to have their value boxed.
4764                                                 if (decl_type.IsValueType ||
4765                                                     TypeManager.IsGenericParameter (iexpr_type)) {
4766                                                         //
4767                                                         // If the expression implements IMemoryLocation, then
4768                                                         // we can optimize and use AddressOf on the
4769                                                         // return.
4770                                                         //
4771                                                         // If not we have to use some temporary storage for
4772                                                         // it.
4773                                                         if (instance_expr is IMemoryLocation) {
4774                                                                 ((IMemoryLocation)instance_expr).
4775                                                                         AddressOf (ec, AddressOp.LoadStore);
4776                                                         } else {
4777                                                                 LocalTemporary temp = new LocalTemporary (iexpr_type);
4778                                                                 instance_expr.Emit (ec);
4779                                                                 temp.Store (ec);
4780                                                                 temp.AddressOf (ec, AddressOp.Load);
4781                                                         }
4782
4783                                                         // avoid the overhead of doing this all the time.
4784                                                         if (dup_args)
4785                                                                 t = TypeManager.GetReferenceType (iexpr_type);
4786                                                 } else {
4787                                                         instance_expr.Emit (ec);
4788                                                         ig.Emit (OpCodes.Box, instance_expr.Type);
4789                                                         t = TypeManager.object_type;
4790                                                 }
4791                                         } else {
4792                                                 instance_expr.Emit (ec);
4793                                                 t = instance_expr.Type;
4794                                         }
4795
4796                                         if (dup_args) {
4797                                                 ig.Emit (OpCodes.Dup);
4798                                                 if (Arguments != null && Arguments.Count != 0) {
4799                                                         this_arg = new LocalTemporary (t);
4800                                                         this_arg.Store (ec);
4801                                                 }
4802                                         }
4803                                 }
4804                         }
4805
4806                         if (!omit_args)
4807                                 EmitArguments (ec, Arguments, dup_args, this_arg);
4808
4809 #if GMCS_SOURCE
4810                         if ((instance_expr != null) && (instance_expr.Type.IsGenericParameter))
4811                                 ig.Emit (OpCodes.Constrained, instance_expr.Type);
4812 #endif
4813
4814                         OpCode call_op;
4815                         if (is_static || struct_call || is_base || (this_call && !method.IsVirtual))
4816                                 call_op = OpCodes.Call;
4817                         else
4818                                 call_op = OpCodes.Callvirt;
4819
4820                         if ((method.CallingConvention & CallingConventions.VarArgs) != 0) {
4821                                 Type[] varargs_types = GetVarargsTypes (method, Arguments);
4822                                 ig.EmitCall (call_op, (MethodInfo) method, varargs_types);
4823                                 return;
4824                         }
4825
4826                         //
4827                         // If you have:
4828                         // this.DoFoo ();
4829                         // and DoFoo is not virtual, you can omit the callvirt,
4830                         // because you don't need the null checking behavior.
4831                         //
4832                         if (method is MethodInfo)
4833                                 ig.Emit (call_op, (MethodInfo) method);
4834                         else
4835                                 ig.Emit (call_op, (ConstructorInfo) method);
4836                 }
4837                 
4838                 public override void Emit (EmitContext ec)
4839                 {
4840                         mg.EmitCall (ec, Arguments);
4841                 }
4842                 
4843                 public override void EmitStatement (EmitContext ec)
4844                 {
4845                         Emit (ec);
4846
4847                         // 
4848                         // Pop the return value if there is one
4849                         //
4850                         if (TypeManager.TypeToCoreType (type) != TypeManager.void_type)
4851                                 ec.ig.Emit (OpCodes.Pop);
4852                 }
4853
4854                 protected override void CloneTo (CloneContext clonectx, Expression t)
4855                 {
4856                         Invocation target = (Invocation) t;
4857
4858                         if (Arguments != null) {
4859                                 target.Arguments = new ArrayList (Arguments.Count);
4860                                 foreach (Argument a in Arguments)
4861                                         target.Arguments.Add (a.Clone (clonectx));
4862                         }
4863
4864                         target.expr = expr.Clone (clonectx);
4865                 }
4866         }
4867
4868         public class InvocationOrCast : ExpressionStatement
4869         {
4870                 Expression expr;
4871                 Expression argument;
4872
4873                 public InvocationOrCast (Expression expr, Expression argument)
4874                 {
4875                         this.expr = expr;
4876                         this.argument = argument;
4877                         this.loc = expr.Location;
4878                 }
4879
4880                 public override Expression DoResolve (EmitContext ec)
4881                 {
4882                         //
4883                         // First try to resolve it as a cast.
4884                         //
4885                         TypeExpr te = expr.ResolveAsTypeTerminal (ec, true);
4886                         if ((te != null) && (te.eclass == ExprClass.Type)) {
4887                                 Cast cast = new Cast (te, argument, loc);
4888                                 return cast.Resolve (ec);
4889                         }
4890
4891                         //
4892                         // This can either be a type or a delegate invocation.
4893                         // Let's just resolve it and see what we'll get.
4894                         //
4895                         expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
4896                         if (expr == null)
4897                                 return null;
4898
4899                         //
4900                         // Ok, so it's a Cast.
4901                         //
4902                         if (expr.eclass == ExprClass.Type) {
4903                                 Cast cast = new Cast (new TypeExpression (expr.Type, loc), argument, loc);
4904                                 return cast.Resolve (ec);
4905                         }
4906
4907                         //
4908                         // It's a delegate invocation.
4909                         //
4910                         if (!TypeManager.IsDelegateType (expr.Type)) {
4911                                 Error (149, "Method name expected");
4912                                 return null;
4913                         }
4914
4915                         ArrayList args = new ArrayList ();
4916                         args.Add (new Argument (argument, Argument.AType.Expression));
4917                         DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
4918                         return invocation.Resolve (ec);
4919                 }
4920
4921                 public override ExpressionStatement ResolveStatement (EmitContext ec)
4922                 {
4923                         //
4924                         // First try to resolve it as a cast.
4925                         //
4926                         TypeExpr te = expr.ResolveAsTypeTerminal (ec, true);
4927                         if ((te != null) && (te.eclass == ExprClass.Type)) {
4928                                 Error_InvalidExpressionStatement ();
4929                                 return null;
4930                         }
4931
4932                         //
4933                         // This can either be a type or a delegate invocation.
4934                         // Let's just resolve it and see what we'll get.
4935                         //
4936                         expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
4937                         if ((expr == null) || (expr.eclass == ExprClass.Type)) {
4938                                 Error_InvalidExpressionStatement ();
4939                                 return null;
4940                         }
4941
4942                         //
4943                         // It's a delegate invocation.
4944                         //
4945                         if (!TypeManager.IsDelegateType (expr.Type)) {
4946                                 Error (149, "Method name expected");
4947                                 return null;
4948                         }
4949
4950                         ArrayList args = new ArrayList ();
4951                         args.Add (new Argument (argument, Argument.AType.Expression));
4952                         DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
4953                         return invocation.ResolveStatement (ec);
4954                 }
4955
4956                 public override void Emit (EmitContext ec)
4957                 {
4958                         throw new Exception ("Cannot happen");
4959                 }
4960
4961                 public override void EmitStatement (EmitContext ec)
4962                 {
4963                         throw new Exception ("Cannot happen");
4964                 }
4965
4966                 protected override void CloneTo (CloneContext clonectx, Expression t)
4967                 {
4968                         InvocationOrCast target = (InvocationOrCast) t;
4969
4970                         target.expr = expr.Clone (clonectx);
4971                         target.argument = argument.Clone (clonectx);
4972                 }
4973         }
4974
4975         //
4976         // This class is used to "disable" the code generation for the
4977         // temporary variable when initializing value types.
4978         //
4979         class EmptyAddressOf : EmptyExpression, IMemoryLocation {
4980                 public void AddressOf (EmitContext ec, AddressOp Mode)
4981                 {
4982                         // nothing
4983                 }
4984         }
4985         
4986         /// <summary>
4987         ///    Implements the new expression 
4988         /// </summary>
4989         public class New : ExpressionStatement, IMemoryLocation {
4990                 ArrayList Arguments;
4991
4992                 //
4993                 // During bootstrap, it contains the RequestedType,
4994                 // but if `type' is not null, it *might* contain a NewDelegate
4995                 // (because of field multi-initialization)
4996                 //
4997                 public Expression RequestedType;
4998
4999                 MethodGroupExpr method;
5000
5001                 //
5002                 // If set, the new expression is for a value_target, and
5003                 // we will not leave anything on the stack.
5004                 //
5005                 protected Expression value_target;
5006                 protected bool value_target_set;
5007                 bool is_type_parameter = false;
5008                 
5009                 public New (Expression requested_type, ArrayList arguments, Location l)
5010                 {
5011                         RequestedType = requested_type;
5012                         Arguments = arguments;
5013                         loc = l;
5014                 }
5015
5016                 public bool SetTargetVariable (Expression value)
5017                 {
5018                         value_target = value;
5019                         value_target_set = true;
5020                         if (!(value_target is IMemoryLocation)){
5021                                 Error_UnexpectedKind (null, "variable", loc);
5022                                 return false;
5023                         }
5024                         return true;
5025                 }
5026
5027                 //
5028                 // This function is used to disable the following code sequence for
5029                 // value type initialization:
5030                 //
5031                 // AddressOf (temporary)
5032                 // Construct/Init
5033                 // LoadTemporary
5034                 //
5035                 // Instead the provide will have provided us with the address on the
5036                 // stack to store the results.
5037                 //
5038                 static Expression MyEmptyExpression;
5039                 
5040                 public void DisableTemporaryValueType ()
5041                 {
5042                         if (MyEmptyExpression == null)
5043                                 MyEmptyExpression = new EmptyAddressOf ();
5044
5045                         //
5046                         // To enable this, look into:
5047                         // test-34 and test-89 and self bootstrapping.
5048                         //
5049                         // For instance, we can avoid a copy by using `newobj'
5050                         // instead of Call + Push-temp on value types.
5051 //                      value_target = MyEmptyExpression;
5052                 }
5053
5054
5055                 /// <summary>
5056                 /// Converts complex core type syntax like 'new int ()' to simple constant
5057                 /// </summary>
5058                 public static Constant Constantify (Type t)
5059                 {
5060                         if (t == TypeManager.int32_type)
5061                                 return new IntConstant (0, Location.Null);
5062                         if (t == TypeManager.uint32_type)
5063                                 return new UIntConstant (0, Location.Null);
5064                         if (t == TypeManager.int64_type)
5065                                 return new LongConstant (0, Location.Null);
5066                         if (t == TypeManager.uint64_type)
5067                                 return new ULongConstant (0, Location.Null);
5068                         if (t == TypeManager.float_type)
5069                                 return new FloatConstant (0, Location.Null);
5070                         if (t == TypeManager.double_type)
5071                                 return new DoubleConstant (0, Location.Null);
5072                         if (t == TypeManager.short_type)
5073                                 return new ShortConstant (0, Location.Null);
5074                         if (t == TypeManager.ushort_type)
5075                                 return new UShortConstant (0, Location.Null);
5076                         if (t == TypeManager.sbyte_type)
5077                                 return new SByteConstant (0, Location.Null);
5078                         if (t == TypeManager.byte_type)
5079                                 return new ByteConstant (0, Location.Null);
5080                         if (t == TypeManager.char_type)
5081                                 return new CharConstant ('\0', Location.Null);
5082                         if (t == TypeManager.bool_type)
5083                                 return new BoolConstant (false, Location.Null);
5084                         if (t == TypeManager.decimal_type)
5085                                 return new DecimalConstant (0, Location.Null);
5086                         if (TypeManager.IsEnumType (t))
5087                                 return new EnumConstant (Constantify (TypeManager.GetEnumUnderlyingType (t)), t);
5088
5089                         return null;
5090                 }
5091
5092                 //
5093                 // Checks whether the type is an interface that has the
5094                 // [ComImport, CoClass] attributes and must be treated
5095                 // specially
5096                 //
5097                 public Expression CheckComImport (EmitContext ec)
5098                 {
5099                         if (!type.IsInterface)
5100                                 return null;
5101
5102                         //
5103                         // Turn the call into:
5104                         // (the-interface-stated) (new class-referenced-in-coclassattribute ())
5105                         //
5106                         Type real_class = AttributeTester.GetCoClassAttribute (type);
5107                         if (real_class == null)
5108                                 return null;
5109
5110                         New proxy = new New (new TypeExpression (real_class, loc), Arguments, loc);
5111                         Cast cast = new Cast (new TypeExpression (type, loc), proxy, loc);
5112                         return cast.Resolve (ec);
5113                 }
5114
5115                 public override Expression CreateExpressionTree (EmitContext ec)
5116                 {
5117                         ArrayList args = Arguments == null ?
5118                                 new ArrayList (1) : new ArrayList (Arguments.Count + 1);
5119
5120                         args.Add (new Argument (method.CreateExpressionTree (ec)));
5121                         if (Arguments != null) {
5122                                 Expression expr;
5123                                 foreach (Argument a in Arguments) {
5124                                         expr = a.Expr.CreateExpressionTree (ec);
5125                                         if (expr != null)
5126                                                 args.Add (new Argument (expr));
5127                                 }
5128                         }
5129
5130                         return CreateExpressionFactoryCall ("New", args);
5131                 }
5132                 
5133                 public override Expression DoResolve (EmitContext ec)
5134                 {
5135                         //
5136                         // The New DoResolve might be called twice when initializing field
5137                         // expressions (see EmitFieldInitializers, the call to
5138                         // GetInitializerExpression will perform a resolve on the expression,
5139                         // and later the assign will trigger another resolution
5140                         //
5141                         // This leads to bugs (#37014)
5142                         //
5143                         if (type != null){
5144                                 if (RequestedType is NewDelegate)
5145                                         return RequestedType;
5146                                 return this;
5147                         }
5148
5149                         TypeExpr texpr = RequestedType.ResolveAsTypeTerminal (ec, false);
5150                         if (texpr == null)
5151                                 return null;
5152
5153                         type = texpr.Type;
5154
5155                         if (type == TypeManager.void_type) {
5156                                 Error_VoidInvalidInTheContext (loc);
5157                                 return null;
5158                         }
5159
5160                         if (type.IsPointer) {
5161                                 Report.Error (1919, loc, "Unsafe type `{0}' cannot be used in an object creation expression",
5162                                         TypeManager.CSharpName (type));
5163                                 return null;
5164                         }
5165
5166                         if (Arguments == null) {
5167                                 Expression c = Constantify (type);
5168                                 if (c != null)
5169                                         return c;
5170                         }
5171
5172                         if (TypeManager.IsDelegateType (type)) {
5173                                 RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec);
5174                                 if (RequestedType != null)
5175                                         if (!(RequestedType is DelegateCreation))
5176                                                 throw new Exception ("NewDelegate.Resolve returned a non NewDelegate: " + RequestedType.GetType ());
5177                                 return RequestedType;
5178                         }
5179
5180 #if GMCS_SOURCE
5181                         if (type.IsGenericParameter) {
5182                                 GenericConstraints gc = TypeManager.GetTypeParameterConstraints (type);
5183
5184                                 if ((gc == null) || (!gc.HasConstructorConstraint && !gc.IsValueType)) {
5185                                         Error (304, String.Format (
5186                                                        "Cannot create an instance of the " +
5187                                                        "variable type '{0}' because it " +
5188                                                        "doesn't have the new() constraint",
5189                                                        type));
5190                                         return null;
5191                                 }
5192
5193                                 if ((Arguments != null) && (Arguments.Count != 0)) {
5194                                         Error (417, String.Format (
5195                                                        "`{0}': cannot provide arguments " +
5196                                                        "when creating an instance of a " +
5197                                                        "variable type.", type));
5198                                         return null;
5199                                 }
5200
5201                                 if (TypeManager.activator_create_instance == null) {
5202                                         Type activator_type = TypeManager.CoreLookupType ("System", "Activator", Kind.Class, true);
5203                                         if (activator_type != null) {
5204                                                 TypeManager.activator_create_instance = TypeManager.GetPredefinedMethod (
5205                                                         activator_type, "CreateInstance", loc, Type.EmptyTypes);
5206                                         }
5207                                 }
5208
5209                                 is_type_parameter = true;
5210                                 eclass = ExprClass.Value;
5211                                 return this;
5212                         }
5213 #endif
5214
5215                         if (type.IsAbstract && type.IsSealed) {
5216                                 Report.SymbolRelatedToPreviousError (type);
5217                                 Report.Error (712, loc, "Cannot create an instance of the static class `{0}'", TypeManager.CSharpName (type));
5218                                 return null;
5219                         }
5220
5221                         if (type.IsInterface || type.IsAbstract){
5222                                 if (!TypeManager.IsGenericType (type)) {
5223                                         RequestedType = CheckComImport (ec);
5224                                         if (RequestedType != null)
5225                                                 return RequestedType;
5226                                 }
5227                                 
5228                                 Report.SymbolRelatedToPreviousError (type);
5229                                 Report.Error (144, loc, "Cannot create an instance of the abstract class or interface `{0}'", TypeManager.CSharpName (type));
5230                                 return null;
5231                         }
5232
5233                         bool is_struct = type.IsValueType;
5234                         eclass = ExprClass.Value;
5235
5236                         //
5237                         // SRE returns a match for .ctor () on structs (the object constructor), 
5238                         // so we have to manually ignore it.
5239                         //
5240                         if (is_struct && Arguments == null)
5241                                 return this;
5242
5243                         // For member-lookup, treat 'new Foo (bar)' as call to 'foo.ctor (bar)', where 'foo' is of type 'Foo'.
5244                         Expression ml = MemberLookupFinal (ec, type, type, ".ctor",
5245                                 MemberTypes.Constructor, AllBindingFlags | BindingFlags.DeclaredOnly, loc);
5246
5247                         if (Arguments != null){
5248                                 foreach (Argument a in Arguments){
5249                                         if (!a.Resolve (ec, loc))
5250                                                 return null;
5251                                 }
5252                         }
5253
5254                         if (ml == null)
5255                                 return null;
5256
5257                         method = ml as MethodGroupExpr;
5258                         if (method == null) {
5259                                 ml.Error_UnexpectedKind (ec.DeclContainer, "method group", loc);
5260                                 return null;
5261                         }
5262
5263                         method = method.OverloadResolve (ec, ref Arguments, false, loc);
5264                         if (method == null)
5265                                 return null;
5266
5267                         return this;
5268                 }
5269
5270                 bool DoEmitTypeParameter (EmitContext ec)
5271                 {
5272 #if GMCS_SOURCE
5273                         ILGenerator ig = ec.ig;
5274 //                      IMemoryLocation ml;
5275
5276                         MethodInfo ci = TypeManager.activator_create_instance.MakeGenericMethod (
5277                                 new Type [] { type });
5278
5279                         GenericConstraints gc = TypeManager.GetTypeParameterConstraints (type);
5280                         if (gc.HasReferenceTypeConstraint || gc.HasClassConstraint) {
5281                                 ig.Emit (OpCodes.Call, ci);
5282                                 return true;
5283                         }
5284
5285                         // Allow DoEmit() to be called multiple times.
5286                         // We need to create a new LocalTemporary each time since
5287                         // you can't share LocalBuilders among ILGeneators.
5288                         LocalTemporary temp = new LocalTemporary (type);
5289
5290                         Label label_activator = ig.DefineLabel ();
5291                         Label label_end = ig.DefineLabel ();
5292
5293                         temp.AddressOf (ec, AddressOp.Store);
5294                         ig.Emit (OpCodes.Initobj, type);
5295
5296                         temp.Emit (ec);
5297                         ig.Emit (OpCodes.Box, type);
5298                         ig.Emit (OpCodes.Brfalse, label_activator);
5299
5300                         temp.AddressOf (ec, AddressOp.Store);
5301                         ig.Emit (OpCodes.Initobj, type);
5302                         temp.Emit (ec);
5303                         ig.Emit (OpCodes.Br, label_end);
5304
5305                         ig.MarkLabel (label_activator);
5306
5307                         ig.Emit (OpCodes.Call, ci);
5308                         ig.MarkLabel (label_end);
5309                         return true;
5310 #else
5311                         throw new InternalErrorException ();
5312 #endif
5313                 }
5314
5315                 //
5316                 // This DoEmit can be invoked in two contexts:
5317                 //    * As a mechanism that will leave a value on the stack (new object)
5318                 //    * As one that wont (init struct)
5319                 //
5320                 // You can control whether a value is required on the stack by passing
5321                 // need_value_on_stack.  The code *might* leave a value on the stack
5322                 // so it must be popped manually
5323                 //
5324                 // If we are dealing with a ValueType, we have a few
5325                 // situations to deal with:
5326                 //
5327                 //    * The target is a ValueType, and we have been provided
5328                 //      the instance (this is easy, we are being assigned).
5329                 //
5330                 //    * The target of New is being passed as an argument,
5331                 //      to a boxing operation or a function that takes a
5332                 //      ValueType.
5333                 //
5334                 //      In this case, we need to create a temporary variable
5335                 //      that is the argument of New.
5336                 //
5337                 // Returns whether a value is left on the stack
5338                 //
5339                 bool DoEmit (EmitContext ec, bool need_value_on_stack)
5340                 {
5341                         bool is_value_type = TypeManager.IsValueType (type);
5342                         ILGenerator ig = ec.ig;
5343
5344                         if (is_value_type){
5345                                 IMemoryLocation ml;
5346
5347                                 // Allow DoEmit() to be called multiple times.
5348                                 // We need to create a new LocalTemporary each time since
5349                                 // you can't share LocalBuilders among ILGeneators.
5350                                 if (!value_target_set)
5351                                         value_target = new LocalTemporary (type);
5352
5353                                 ml = (IMemoryLocation) value_target;
5354                                 ml.AddressOf (ec, AddressOp.Store);
5355                         }
5356
5357                         if (method != null)
5358                                 method.EmitArguments (ec, Arguments);
5359
5360                         if (is_value_type){
5361                                 if (method == null)
5362                                         ig.Emit (OpCodes.Initobj, type);
5363                                 else
5364                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
5365                                 if (need_value_on_stack){
5366                                         value_target.Emit (ec);
5367                                         return true;
5368                                 }
5369                                 return false;
5370                         } else {
5371                                 ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
5372                                 return true;
5373                         }
5374                 }
5375
5376                 public override void Emit (EmitContext ec)
5377                 {
5378                         if (is_type_parameter)
5379                                 DoEmitTypeParameter (ec);
5380                         else
5381                                 DoEmit (ec, true);
5382                 }
5383                 
5384                 public override void EmitStatement (EmitContext ec)
5385                 {
5386                         bool value_on_stack;
5387
5388                         if (is_type_parameter)
5389                                 value_on_stack = DoEmitTypeParameter (ec);
5390                         else
5391                                 value_on_stack = DoEmit (ec, false);
5392
5393                         if (value_on_stack)
5394                                 ec.ig.Emit (OpCodes.Pop);
5395
5396                 }
5397
5398                 public virtual bool HasInitializer {
5399                         get {
5400                                 return false;
5401                         }
5402                 }
5403
5404                 public void AddressOf (EmitContext ec, AddressOp Mode)
5405                 {
5406                         if (is_type_parameter) {
5407                                 LocalTemporary temp = new LocalTemporary (type);
5408                                 DoEmitTypeParameter (ec);
5409                                 temp.Store (ec);
5410                                 temp.AddressOf (ec, Mode);
5411                                 return;
5412                         }
5413
5414                         if (!type.IsValueType){
5415                                 //
5416                                 // We throw an exception.  So far, I believe we only need to support
5417                                 // value types:
5418                                 // foreach (int j in new StructType ())
5419                                 // see bug 42390
5420                                 //
5421                                 throw new Exception ("AddressOf should not be used for classes");
5422                         }
5423
5424                         if (!value_target_set)
5425                                 value_target = new LocalTemporary (type);
5426                         IMemoryLocation ml = (IMemoryLocation) value_target;
5427
5428                         ml.AddressOf (ec, AddressOp.Store);
5429                         if (method == null) {
5430                                 ec.ig.Emit (OpCodes.Initobj, type);
5431                         } else {
5432                                 method.EmitArguments (ec, Arguments);
5433                                 ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
5434                         }
5435                         
5436                         ((IMemoryLocation) value_target).AddressOf (ec, Mode);
5437                 }
5438
5439                 protected override void CloneTo (CloneContext clonectx, Expression t)
5440                 {
5441                         New target = (New) t;
5442
5443                         target.RequestedType = RequestedType.Clone (clonectx);
5444                         if (Arguments != null){
5445                                 target.Arguments = new ArrayList ();
5446                                 foreach (Argument a in Arguments){
5447                                         target.Arguments.Add (a.Clone (clonectx));
5448                                 }
5449                         }
5450                 }
5451         }
5452
5453         /// <summary>
5454         ///   14.5.10.2: Represents an array creation expression.
5455         /// </summary>
5456         ///
5457         /// <remarks>
5458         ///   There are two possible scenarios here: one is an array creation
5459         ///   expression that specifies the dimensions and optionally the
5460         ///   initialization data and the other which does not need dimensions
5461         ///   specified but where initialization data is mandatory.
5462         /// </remarks>
5463         public class ArrayCreation : Expression {
5464                 Expression requested_base_type;
5465                 ArrayList initializers;
5466
5467                 //
5468                 // The list of Argument types.
5469                 // This is used to construct the `newarray' or constructor signature
5470                 //
5471                 protected ArrayList arguments;
5472                 
5473                 protected Type array_element_type;
5474                 bool expect_initializers = false;
5475                 int num_arguments = 0;
5476                 protected int dimensions;
5477                 protected readonly string rank;
5478
5479                 protected ArrayList array_data;
5480
5481                 IDictionary bounds;
5482
5483                 // The number of constants in array initializers
5484                 int const_initializers_count;
5485                 bool only_constant_initializers;
5486                 
5487                 public ArrayCreation (Expression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l)
5488                 {
5489                         this.requested_base_type = requested_base_type;
5490                         this.initializers = initializers;
5491                         this.rank = rank;
5492                         loc = l;
5493
5494                         arguments = new ArrayList ();
5495
5496                         foreach (Expression e in exprs) {
5497                                 arguments.Add (new Argument (e, Argument.AType.Expression));
5498                                 num_arguments++;
5499                         }
5500                 }
5501
5502                 public ArrayCreation (Expression requested_base_type, string rank, ArrayList initializers, Location l)
5503                 {
5504                         this.requested_base_type = requested_base_type;
5505                         this.initializers = initializers;
5506                         this.rank = rank;
5507                         loc = l;
5508
5509                         //this.rank = rank.Substring (0, rank.LastIndexOf ('['));
5510                         //
5511                         //string tmp = rank.Substring (rank.LastIndexOf ('['));
5512                         //
5513                         //dimensions = tmp.Length - 1;
5514                         expect_initializers = true;
5515                 }
5516
5517                 public Expression FormArrayType (Expression base_type, int idx_count, string rank)
5518                 {
5519                         StringBuilder sb = new StringBuilder (rank);
5520                         
5521                         sb.Append ("[");
5522                         for (int i = 1; i < idx_count; i++)
5523                                 sb.Append (",");
5524                         
5525                         sb.Append ("]");
5526
5527                         return new ComposedCast (base_type, sb.ToString (), loc);
5528                 }
5529
5530                 void Error_IncorrectArrayInitializer ()
5531                 {
5532                         Error (178, "Invalid rank specifier: expected `,' or `]'");
5533                 }
5534
5535                 protected override void Error_NegativeArrayIndex (Location loc)
5536                 {
5537                         Report.Error (248, loc, "Cannot create an array with a negative size");
5538                 }
5539                 
5540                 bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims)
5541                 {
5542                         if (specified_dims) { 
5543                                 Argument a = (Argument) arguments [idx];
5544
5545                                 if (!a.Resolve (ec, loc))
5546                                         return false;
5547
5548                                 Constant c = a.Expr as Constant;
5549                                 if (c != null) {
5550                                         c = c.ImplicitConversionRequired (TypeManager.int32_type, a.Expr.Location);
5551                                 }
5552
5553                                 if (c == null) {
5554                                         Report.Error (150, a.Expr.Location, "A constant value is expected");
5555                                         return false;
5556                                 }
5557
5558                                 int value = (int) c.GetValue ();
5559                                 
5560                                 if (value != probe.Count) {
5561                                         Error_IncorrectArrayInitializer ();
5562                                         return false;
5563                                 }
5564                                 
5565                                 bounds [idx] = value;
5566                         }
5567
5568                         int child_bounds = -1;
5569                         only_constant_initializers = true;
5570                         for (int i = 0; i < probe.Count; ++i) {
5571                                 object o = probe [i];
5572                                 if (o is ArrayList) {
5573                                         ArrayList sub_probe = o as ArrayList;
5574                                         int current_bounds = sub_probe.Count;
5575                                         
5576                                         if (child_bounds == -1) 
5577                                                 child_bounds = current_bounds;
5578
5579                                         else if (child_bounds != current_bounds){
5580                                                 Error_IncorrectArrayInitializer ();
5581                                                 return false;
5582                                         }
5583                                         if (idx + 1 >= dimensions){
5584                                                 Error (623, "Array initializers can only be used in a variable or field initializer. Try using a new expression instead");
5585                                                 return false;
5586                                         }
5587                                         
5588                                         bool ret = CheckIndices (ec, sub_probe, idx + 1, specified_dims);
5589                                         if (!ret)
5590                                                 return false;
5591                                 } else {
5592                                         if (child_bounds != -1){
5593                                                 Error_IncorrectArrayInitializer ();
5594                                                 return false;
5595                                         }
5596                                         
5597                                         Expression element = ResolveArrayElement (ec, (Expression) o);
5598                                         if (element == null)
5599                                                 continue;
5600
5601                                         // Initializers with the default values can be ignored
5602                                         Constant c = element as Constant;
5603                                         if (c != null) {
5604                                                 if (c.IsDefaultInitializer (array_element_type)) {
5605                                                         element = null;
5606                                                 }
5607                                                 else {
5608                                                         ++const_initializers_count;
5609                                                 }
5610                                         } else {
5611                                                 only_constant_initializers = false;
5612                                         }
5613                                         
5614                                         array_data.Add (element);
5615                                 }
5616                         }
5617
5618                         return true;
5619                 }
5620
5621                 public override Expression CreateExpressionTree (EmitContext ec)
5622                 {
5623                         if (dimensions != 1) {
5624                                 Report.Error (838, loc, "An expression tree cannot contain a multidimensional array initializer");
5625                                 return null;
5626                         }
5627
5628                         ArrayList args = new ArrayList (array_data == null ? 1 : array_data.Count + 1);
5629                         args.Add (new Argument (new TypeOf (new TypeExpression (array_element_type, loc), loc)));
5630                         if (array_data != null) {
5631                                 foreach (Expression e in array_data)
5632                                         args.Add (new Argument (e.CreateExpressionTree (ec)));
5633                         }
5634
5635                         return CreateExpressionFactoryCall ("NewArrayInit", args);
5636                 }               
5637                 
5638                 public void UpdateIndices ()
5639                 {
5640                         int i = 0;
5641                         for (ArrayList probe = initializers; probe != null;) {
5642                                 if (probe.Count > 0 && probe [0] is ArrayList) {
5643                                         Expression e = new IntConstant (probe.Count, Location.Null);
5644                                         arguments.Add (new Argument (e, Argument.AType.Expression));
5645
5646                                         bounds [i++] =  probe.Count;
5647                                         
5648                                         probe = (ArrayList) probe [0];
5649                                         
5650                                 } else {
5651                                         Expression e = new IntConstant (probe.Count, Location.Null);
5652                                         arguments.Add (new Argument (e, Argument.AType.Expression));
5653
5654                                         bounds [i++] = probe.Count;
5655                                         return;
5656                                 }
5657                         }
5658
5659                 }
5660
5661                 protected virtual Expression ResolveArrayElement (EmitContext ec, Expression element)
5662                 {
5663                         element = element.Resolve (ec);
5664                         if (element == null)
5665                                 return null;
5666
5667                         return Convert.ImplicitConversionRequired (
5668                                 ec, element, array_element_type, loc);
5669                 }
5670
5671                 protected bool ResolveInitializers (EmitContext ec)
5672                 {
5673                         if (initializers == null) {
5674                                 return !expect_initializers;
5675                         }
5676                                                 
5677                         //
5678                         // We use this to store all the date values in the order in which we
5679                         // will need to store them in the byte blob later
5680                         //
5681                         array_data = new ArrayList ();
5682                         bounds = new System.Collections.Specialized.HybridDictionary ();
5683                         
5684                         if (arguments != null)
5685                                 return CheckIndices (ec, initializers, 0, true);
5686
5687                         arguments = new ArrayList ();
5688
5689                         if (!CheckIndices (ec, initializers, 0, false))
5690                                 return false;
5691                                 
5692                         UpdateIndices ();
5693                                 
5694                         return true;
5695                 }
5696
5697                 //
5698                 // Resolved the type of the array
5699                 //
5700                 bool ResolveArrayType (EmitContext ec)
5701                 {
5702                         if (requested_base_type == null) {
5703                                 Report.Error (622, loc, "Can only use array initializer expressions to assign to array types. Try using a new expression instead");
5704                                 return false;
5705                         }
5706                         
5707                         StringBuilder array_qualifier = new StringBuilder (rank);
5708
5709                         //
5710                         // `In the first form allocates an array instace of the type that results
5711                         // from deleting each of the individual expression from the expression list'
5712                         //
5713                         if (num_arguments > 0) {
5714                                 array_qualifier.Append ("[");
5715                                 for (int i = num_arguments-1; i > 0; i--)
5716                                         array_qualifier.Append (",");
5717                                 array_qualifier.Append ("]");
5718                         }
5719
5720                         //
5721                         // Lookup the type
5722                         //
5723                         TypeExpr array_type_expr;
5724                         array_type_expr = new ComposedCast (requested_base_type, array_qualifier.ToString (), loc);
5725                         array_type_expr = array_type_expr.ResolveAsTypeTerminal (ec, false);
5726                         if (array_type_expr == null)
5727                                 return false;
5728
5729                         type = array_type_expr.Type;
5730                         array_element_type = TypeManager.GetElementType (type);
5731                         dimensions = type.GetArrayRank ();
5732
5733                         return true;
5734                 }
5735
5736                 public override Expression DoResolve (EmitContext ec)
5737                 {
5738                         if (type != null)
5739                                 return this;
5740
5741                         if (!ResolveArrayType (ec))
5742                                 return null;
5743                         
5744                         if ((array_element_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
5745                                 Report.Error (719, loc, "`{0}': array elements cannot be of static type",
5746                                         TypeManager.CSharpName (array_element_type));
5747                         }
5748
5749                         //
5750                         // First step is to validate the initializers and fill
5751                         // in any missing bits
5752                         //
5753                         if (!ResolveInitializers (ec))
5754                                 return null;
5755
5756                         if (arguments.Count != dimensions) {
5757                                 Error_IncorrectArrayInitializer ();
5758                         }
5759
5760                         foreach (Argument a in arguments){
5761                                 if (!a.Resolve (ec, loc))
5762                                         continue;
5763
5764                                 a.Expr = ConvertExpressionToArrayIndex (ec, a.Expr);
5765                         }
5766                                                         
5767                         eclass = ExprClass.Value;
5768                         return this;
5769                 }
5770
5771                 MethodInfo GetArrayMethod (int arguments)
5772                 {
5773                         ModuleBuilder mb = CodeGen.Module.Builder;
5774
5775                         Type[] arg_types = new Type[arguments];
5776                         for (int i = 0; i < arguments; i++)
5777                                 arg_types[i] = TypeManager.int32_type;
5778
5779                         MethodInfo mi = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,
5780                                                         arg_types);
5781
5782                         if (mi == null) {
5783                                 Report.Error (-6, "New invocation: Can not find a constructor for " +
5784                                                   "this argument list");
5785                                 return null;
5786                         }
5787
5788                         return mi; 
5789                 }
5790
5791                 byte [] MakeByteBlob ()
5792                 {
5793                         int factor;
5794                         byte [] data;
5795                         byte [] element;
5796                         int count = array_data.Count;
5797
5798                         if (TypeManager.IsEnumType (array_element_type))
5799                                 array_element_type = TypeManager.GetEnumUnderlyingType (array_element_type);
5800                         
5801                         factor = GetTypeSize (array_element_type);
5802                         if (factor == 0)
5803                                 throw new Exception ("unrecognized type in MakeByteBlob: " + array_element_type);
5804
5805                         data = new byte [(count * factor + 3) & ~3];
5806                         int idx = 0;
5807
5808                         for (int i = 0; i < count; ++i) {
5809                                 object v = array_data [i];
5810
5811                                 if (v is EnumConstant)
5812                                         v = ((EnumConstant) v).Child;
5813                                 
5814                                 if (v is Constant && !(v is StringConstant))
5815                                         v = ((Constant) v).GetValue ();
5816                                 else {
5817                                         idx += factor;
5818                                         continue;
5819                                 }
5820                                 
5821                                 if (array_element_type == TypeManager.int64_type){
5822                                         if (!(v is Expression)){
5823                                                 long val = (long) v;
5824                                                 
5825                                                 for (int j = 0; j < factor; ++j) {
5826                                                         data [idx + j] = (byte) (val & 0xFF);
5827                                                         val = (val >> 8);
5828                                                 }
5829                                         }
5830                                 } else if (array_element_type == TypeManager.uint64_type){
5831                                         if (!(v is Expression)){
5832                                                 ulong val = (ulong) v;
5833
5834                                                 for (int j = 0; j < factor; ++j) {
5835                                                         data [idx + j] = (byte) (val & 0xFF);
5836                                                         val = (val >> 8);
5837                                                 }
5838                                         }
5839                                 } else if (array_element_type == TypeManager.float_type) {
5840                                         if (!(v is Expression)){
5841                                                 element = BitConverter.GetBytes ((float) v);
5842                                                         
5843                                                 for (int j = 0; j < factor; ++j)
5844                                                         data [idx + j] = element [j];
5845                                                 if (!BitConverter.IsLittleEndian)
5846                                                         System.Array.Reverse (data, idx, 4);
5847                                         }
5848                                 } else if (array_element_type == TypeManager.double_type) {
5849                                         if (!(v is Expression)){
5850                                                 element = BitConverter.GetBytes ((double) v);
5851
5852                                                 for (int j = 0; j < factor; ++j)
5853                                                         data [idx + j] = element [j];
5854
5855                                                 // FIXME: Handle the ARM float format.
5856                                                 if (!BitConverter.IsLittleEndian)
5857                                                         System.Array.Reverse (data, idx, 8);
5858                                         }
5859                                 } else if (array_element_type == TypeManager.char_type){
5860                                         if (!(v is Expression)){
5861                                                 int val = (int) ((char) v);
5862                                                 
5863                                                 data [idx] = (byte) (val & 0xff);
5864                                                 data [idx+1] = (byte) (val >> 8);
5865                                         }
5866                                 } else if (array_element_type == TypeManager.short_type){
5867                                         if (!(v is Expression)){
5868                                                 int val = (int) ((short) v);
5869                                         
5870                                                 data [idx] = (byte) (val & 0xff);
5871                                                 data [idx+1] = (byte) (val >> 8);
5872                                         }
5873                                 } else if (array_element_type == TypeManager.ushort_type){
5874                                         if (!(v is Expression)){
5875                                                 int val = (int) ((ushort) v);
5876                                         
5877                                                 data [idx] = (byte) (val & 0xff);
5878                                                 data [idx+1] = (byte) (val >> 8);
5879                                         }
5880                                 } else if (array_element_type == TypeManager.int32_type) {
5881                                         if (!(v is Expression)){
5882                                                 int val = (int) v;
5883                                         
5884                                                 data [idx]   = (byte) (val & 0xff);
5885                                                 data [idx+1] = (byte) ((val >> 8) & 0xff);
5886                                                 data [idx+2] = (byte) ((val >> 16) & 0xff);
5887                                                 data [idx+3] = (byte) (val >> 24);
5888                                         }
5889                                 } else if (array_element_type == TypeManager.uint32_type) {
5890                                         if (!(v is Expression)){
5891                                                 uint val = (uint) v;
5892                                         
5893                                                 data [idx]   = (byte) (val & 0xff);
5894                                                 data [idx+1] = (byte) ((val >> 8) & 0xff);
5895                                                 data [idx+2] = (byte) ((val >> 16) & 0xff);
5896                                                 data [idx+3] = (byte) (val >> 24);
5897                                         }
5898                                 } else if (array_element_type == TypeManager.sbyte_type) {
5899                                         if (!(v is Expression)){
5900                                                 sbyte val = (sbyte) v;
5901                                                 data [idx] = (byte) val;
5902                                         }
5903                                 } else if (array_element_type == TypeManager.byte_type) {
5904                                         if (!(v is Expression)){
5905                                                 byte val = (byte) v;
5906                                                 data [idx] = (byte) val;
5907                                         }
5908                                 } else if (array_element_type == TypeManager.bool_type) {
5909                                         if (!(v is Expression)){
5910                                                 bool val = (bool) v;
5911                                                 data [idx] = (byte) (val ? 1 : 0);
5912                                         }
5913                                 } else if (array_element_type == TypeManager.decimal_type){
5914                                         if (!(v is Expression)){
5915                                                 int [] bits = Decimal.GetBits ((decimal) v);
5916                                                 int p = idx;
5917
5918                                                 // FIXME: For some reason, this doesn't work on the MS runtime.
5919                                                 int [] nbits = new int [4];
5920                                                 nbits [0] = bits [3];
5921                                                 nbits [1] = bits [2];
5922                                                 nbits [2] = bits [0];
5923                                                 nbits [3] = bits [1];
5924                                                 
5925                                                 for (int j = 0; j < 4; j++){
5926                                                         data [p++] = (byte) (nbits [j] & 0xff);
5927                                                         data [p++] = (byte) ((nbits [j] >> 8) & 0xff);
5928                                                         data [p++] = (byte) ((nbits [j] >> 16) & 0xff);
5929                                                         data [p++] = (byte) (nbits [j] >> 24);
5930                                                 }
5931                                         }
5932                                 } else
5933                                         throw new Exception ("Unrecognized type in MakeByteBlob: " + array_element_type);
5934
5935                                 idx += factor;
5936                         }
5937
5938                         return data;
5939                 }
5940
5941                 //
5942                 // Emits the initializers for the array
5943                 //
5944                 void EmitStaticInitializers (EmitContext ec)
5945                 {
5946                         // FIXME: This should go to Resolve !
5947                         if (TypeManager.void_initializearray_array_fieldhandle == null) {
5948                                 TypeManager.void_initializearray_array_fieldhandle = TypeManager.GetPredefinedMethod (
5949                                         TypeManager.runtime_helpers_type, "InitializeArray", loc,
5950                                         TypeManager.array_type, TypeManager.runtime_field_handle_type);
5951                                 if (TypeManager.void_initializearray_array_fieldhandle == null)
5952                                         return;
5953                         }
5954
5955                         //
5956                         // First, the static data
5957                         //
5958                         FieldBuilder fb;
5959                         ILGenerator ig = ec.ig;
5960                         
5961                         byte [] data = MakeByteBlob ();
5962
5963                         fb = RootContext.MakeStaticData (data);
5964
5965                         ig.Emit (OpCodes.Dup);
5966                         ig.Emit (OpCodes.Ldtoken, fb);
5967                         ig.Emit (OpCodes.Call,
5968                                  TypeManager.void_initializearray_array_fieldhandle);
5969                 }
5970
5971                 //
5972                 // Emits pieces of the array that can not be computed at compile
5973                 // time (variables and string locations).
5974                 //
5975                 // This always expect the top value on the stack to be the array
5976                 //
5977                 void EmitDynamicInitializers (EmitContext ec, bool emitConstants)
5978                 {
5979                         ILGenerator ig = ec.ig;
5980                         int dims = bounds.Count;
5981                         int [] current_pos = new int [dims];
5982
5983                         MethodInfo set = null;
5984
5985                         if (dims != 1){
5986                                 Type [] args = new Type [dims + 1];
5987
5988                                 for (int j = 0; j < dims; j++)
5989                                         args [j] = TypeManager.int32_type;
5990                                 args [dims] = array_element_type;
5991                                 
5992                                 set = CodeGen.Module.Builder.GetArrayMethod (
5993                                         type, "Set",
5994                                         CallingConventions.HasThis | CallingConventions.Standard,
5995                                         TypeManager.void_type, args);
5996                         }
5997
5998                         for (int i = 0; i < array_data.Count; i++){
5999
6000                                 Expression e = (Expression)array_data [i];
6001
6002                                 // Constant can be initialized via StaticInitializer
6003                                 if (e != null && !(!emitConstants && e is Constant)) {
6004                                         Type etype = e.Type;
6005
6006                                         ig.Emit (OpCodes.Dup);
6007
6008                                         for (int idx = 0; idx < dims; idx++) 
6009                                                 IntConstant.EmitInt (ig, current_pos [idx]);
6010
6011                                         //
6012                                         // If we are dealing with a struct, get the
6013                                         // address of it, so we can store it.
6014                                         //
6015                                         if ((dims == 1) && etype.IsValueType &&
6016                                             (!TypeManager.IsBuiltinOrEnum (etype) ||
6017                                              etype == TypeManager.decimal_type)) {
6018                                                 if (e is New){
6019                                                         New n = (New) e;
6020
6021                                                         //
6022                                                         // Let new know that we are providing
6023                                                         // the address where to store the results
6024                                                         //
6025                                                         n.DisableTemporaryValueType ();
6026                                                 }
6027
6028                                                 ig.Emit (OpCodes.Ldelema, etype);
6029                                         }
6030
6031                                         e.Emit (ec);
6032
6033                                         if (dims == 1) {
6034                                                 bool is_stobj, has_type_arg;
6035                                                 OpCode op = ArrayAccess.GetStoreOpcode (etype, out is_stobj, out has_type_arg);
6036                                                 if (is_stobj)
6037                                                         ig.Emit (OpCodes.Stobj, etype);
6038                                                 else if (has_type_arg)
6039                                                         ig.Emit (op, etype);
6040                                                 else
6041                                                         ig.Emit (op);
6042                                         } else 
6043                                                 ig.Emit (OpCodes.Call, set);
6044
6045                                 }
6046                                 
6047                                 //
6048                                 // Advance counter
6049                                 //
6050                                 for (int j = dims - 1; j >= 0; j--){
6051                                         current_pos [j]++;
6052                                         if (current_pos [j] < (int) bounds [j])
6053                                                 break;
6054                                         current_pos [j] = 0;
6055                                 }
6056                         }
6057                 }
6058
6059                 public override void Emit (EmitContext ec)
6060                 {
6061                         ILGenerator ig = ec.ig;
6062
6063                         foreach (Argument a in arguments)
6064                                 a.Emit (ec);
6065
6066                         if (arguments.Count == 1)
6067                                 ig.Emit (OpCodes.Newarr, array_element_type);
6068                         else {
6069                                 ig.Emit (OpCodes.Newobj, GetArrayMethod (arguments.Count));
6070                         }
6071                         
6072                         if (initializers == null)
6073                                 return;
6074
6075                         // Emit static initializer for arrays which have contain more than 4 items and
6076                         // the static initializer will initialize at least 25% of array values.
6077                         // NOTE: const_initializers_count does not contain default constant values.
6078                         if (const_initializers_count >= 4 && const_initializers_count * 4 > (array_data.Count) &&
6079                                 TypeManager.IsPrimitiveType (array_element_type)) {
6080                                 EmitStaticInitializers (ec);
6081
6082                                 if (!only_constant_initializers)
6083                                         EmitDynamicInitializers (ec, false);
6084                         } else {
6085                                 EmitDynamicInitializers (ec, true);
6086                         }                               
6087                 }
6088
6089                 public override bool GetAttributableValue (Type value_type, out object value)
6090                 {
6091                         if (arguments.Count != 1) {
6092                                 // Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays");
6093                                 return base.GetAttributableValue (null, out value);
6094                         }
6095
6096                         if (array_data == null) {
6097                                 Constant c = (Constant)((Argument)arguments [0]).Expr;
6098                                 if (c.IsDefaultValue) {
6099                                         value = Array.CreateInstance (array_element_type, 0);
6100                                         return true;
6101                                 }
6102                                 // Report.Error (-212, Location, "array should be initialized when passing it to an attribute");
6103                                 return base.GetAttributableValue (null, out value);
6104                         }
6105                         
6106                         Array ret = Array.CreateInstance (array_element_type, array_data.Count);
6107                         object element_value;
6108                         for (int i = 0; i < ret.Length; ++i)
6109                         {
6110                                 Expression e = (Expression)array_data [i];
6111
6112                                 // Is null when an initializer is optimized (value == predefined value)
6113                                 if (e == null) 
6114                                         continue;
6115
6116                                 if (!e.GetAttributableValue (array_element_type, out element_value)) {
6117                                         value = null;
6118                                         return false;
6119                                 }
6120                                 ret.SetValue (element_value, i);
6121                         }
6122                         value = ret;
6123                         return true;
6124                 }
6125                 
6126                 protected override void CloneTo (CloneContext clonectx, Expression t)
6127                 {
6128                         ArrayCreation target = (ArrayCreation) t;
6129
6130                         if (requested_base_type != null)
6131                                 target.requested_base_type = requested_base_type.Clone (clonectx);
6132
6133                         if (arguments != null){
6134                                 target.arguments = new ArrayList (arguments.Count);
6135                                 foreach (Argument a in arguments)
6136                                         target.arguments.Add (a.Clone (clonectx));
6137                         }
6138
6139                         if (initializers != null){
6140                                 target.initializers = new ArrayList (initializers.Count);
6141                                 foreach (object initializer in initializers)
6142                                         if (initializer is ArrayList) {
6143                                                 ArrayList this_al = (ArrayList)initializer;
6144                                                 ArrayList al = new ArrayList (this_al.Count);
6145                                                 target.initializers.Add (al);
6146                                                 foreach (Expression e in this_al)
6147                                                         al.Add (e.Clone (clonectx));
6148                                         } else {
6149                                                 target.initializers.Add (((Expression)initializer).Clone (clonectx));
6150                                         }
6151                         }
6152                 }
6153         }
6154         
6155         //
6156         // Represents an implicitly typed array epxression
6157         //
6158         public class ImplicitlyTypedArrayCreation : ArrayCreation
6159         {
6160                 public ImplicitlyTypedArrayCreation (string rank, ArrayList initializers, Location loc)
6161                         : base (null, rank, initializers, loc)
6162                 {
6163                         if (RootContext.Version <= LanguageVersion.ISO_2)
6164                                 Report.FeatureIsNotAvailable (loc, "implicitly typed arrays");
6165                                 
6166                         if (rank.Length > 2) {
6167                                 while (rank [++dimensions] == ',');
6168                         } else {
6169                                 dimensions = 1;
6170                         }
6171                 }
6172
6173                 public override Expression DoResolve (EmitContext ec)
6174                 {
6175                         if (type != null)
6176                                 return this;
6177
6178                         if (!ResolveInitializers (ec))
6179                                 return null;
6180
6181                         if (array_element_type == null || array_element_type == TypeManager.null_type ||
6182                                 array_element_type == TypeManager.void_type || array_element_type == TypeManager.anonymous_method_type ||
6183                                 arguments.Count != dimensions) {
6184                                 Report.Error (826, loc, "The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
6185                                 return null;
6186                         }
6187
6188                         //
6189                         // At this point we found common base type for all initializer elements
6190                         // but we have to be sure that all static initializer elements are of
6191                         // same type
6192                         //
6193                         UnifyInitializerElement (ec);
6194
6195                         type = TypeManager.GetConstructedType (array_element_type, rank);
6196                         eclass = ExprClass.Value;
6197                         return this;
6198                 }
6199
6200                 //
6201                 // Converts static initializer only
6202                 //
6203                 void UnifyInitializerElement (EmitContext ec)
6204                 {
6205                         for (int i = 0; i < array_data.Count; ++i) {
6206                                 Expression e = (Expression)array_data[i];
6207                                 if (e != null)
6208                                         array_data [i] = Convert.ImplicitConversionStandard (ec, e, array_element_type, Location.Null);
6209                         }
6210                 }
6211
6212                 protected override Expression ResolveArrayElement (EmitContext ec, Expression element)
6213                 {
6214                         element = element.Resolve (ec);
6215                         if (element == null)
6216                                 return null;
6217                         
6218                         if (array_element_type == null) {
6219                                 array_element_type = element.Type;
6220                                 return element;
6221                         }
6222
6223                         if (Convert.ImplicitStandardConversionExists (element, array_element_type)) {
6224                                 return element;
6225                         }
6226
6227                         if (Convert.ImplicitStandardConversionExists (new TypeExpression (array_element_type, loc), element.Type)) {
6228                                 array_element_type = element.Type;
6229                                 return element;
6230                         }
6231
6232                         element.Error_ValueCannotBeConverted (ec, element.Location, array_element_type, false);
6233                         return element;
6234                 }
6235         }       
6236         
6237         public sealed class CompilerGeneratedThis : This
6238         {
6239                 public static This Instance = new CompilerGeneratedThis ();
6240
6241                 private CompilerGeneratedThis ()
6242                         : base (Location.Null)
6243                 {
6244                 }
6245
6246                 public override Expression DoResolve (EmitContext ec)
6247                 {
6248                         eclass = ExprClass.Variable;
6249                         type = ec.ContainerType;
6250                         variable = new SimpleThis (type);
6251                         return this;
6252                 }
6253         }
6254         
6255         /// <summary>
6256         ///   Represents the `this' construct
6257         /// </summary>
6258
6259         public class This : VariableReference, IVariable
6260         {
6261                 Block block;
6262                 VariableInfo variable_info;
6263                 protected Variable variable;
6264                 bool is_struct;
6265
6266                 public This (Block block, Location loc)
6267                 {
6268                         this.loc = loc;
6269                         this.block = block;
6270                 }
6271
6272                 public This (Location loc)
6273                 {
6274                         this.loc = loc;
6275                 }
6276
6277                 public VariableInfo VariableInfo {
6278                         get { return variable_info; }
6279                 }
6280
6281                 public bool VerifyFixed ()
6282                 {
6283                         return !TypeManager.IsValueType (Type);
6284                 }
6285
6286                 public override bool IsRef {
6287                         get { return is_struct; }
6288                 }
6289
6290                 public override Variable Variable {
6291                         get { return variable; }
6292                 }
6293
6294                 public bool ResolveBase (EmitContext ec)
6295                 {
6296                         eclass = ExprClass.Variable;
6297
6298                         if (ec.TypeContainer.CurrentType != null)
6299                                 type = ec.TypeContainer.CurrentType;
6300                         else
6301                                 type = ec.ContainerType;
6302
6303                         is_struct = ec.TypeContainer is Struct;
6304
6305                         if (ec.IsStatic) {
6306                                 Error (26, "Keyword `this' is not valid in a static property, " +
6307                                        "static method, or static field initializer");
6308                                 return false;
6309                         }
6310
6311                         if (block != null) {
6312                                 if (block.Toplevel.ThisVariable != null)
6313                                         variable_info = block.Toplevel.ThisVariable.VariableInfo;
6314
6315                                 AnonymousContainer am = ec.CurrentAnonymousMethod;
6316                                 if (is_struct && (am != null) && !am.IsIterator) {
6317                                         Report.Error (1673, loc, "Anonymous methods inside structs " +
6318                                                       "cannot access instance members of `this'. " +
6319                                                       "Consider copying `this' to a local variable " +
6320                                                       "outside the anonymous method and using the " +
6321                                                       "local instead.");
6322                                 }
6323
6324                                 RootScopeInfo host = block.Toplevel.RootScope;
6325                                 if ((host != null) && !ec.IsConstructor &&
6326                                     (!is_struct || host.IsIterator)) {
6327                                         variable = host.CaptureThis ();
6328                                         type = variable.Type;
6329                                         is_struct = false;
6330                                 }
6331                         }
6332
6333                         if (variable == null)
6334                                 variable = new SimpleThis (type);
6335                         
6336                         return true;
6337                 }
6338
6339                 //
6340                 // Called from Invocation to check if the invocation is correct
6341                 //
6342                 public override void CheckMarshalByRefAccess (EmitContext ec)
6343                 {
6344                         if ((variable_info != null) && !(type.IsValueType && ec.OmitStructFlowAnalysis) &&
6345                             !variable_info.IsAssigned (ec)) {
6346                                 Error (188, "The `this' object cannot be used before all of its " +
6347                                        "fields are assigned to");
6348                                 variable_info.SetAssigned (ec);
6349                         }
6350                 }
6351
6352                 public override Expression CreateExpressionTree (EmitContext ec)
6353                 {
6354                         ArrayList args = new ArrayList (2);
6355                         args.Add (new Argument (this));
6356                         args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
6357                         return CreateExpressionFactoryCall ("Constant", args);
6358                 }
6359                 
6360                 public override Expression DoResolve (EmitContext ec)
6361                 {
6362                         if (!ResolveBase (ec))
6363                                 return null;
6364
6365
6366                         if (ec.IsInFieldInitializer) {
6367                                 Error (27, "Keyword `this' is not available in the current context");
6368                                 return null;
6369                         }
6370                         
6371                         return this;
6372                 }
6373
6374                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
6375                 {
6376                         if (!ResolveBase (ec))
6377                                 return null;
6378
6379                         if (variable_info != null)
6380                                 variable_info.SetAssigned (ec);
6381                         
6382                         if (ec.TypeContainer is Class){
6383                                 Error (1604, "Cannot assign to 'this' because it is read-only");
6384                                 return null;
6385                         }
6386
6387                         return this;
6388                 }
6389                 public override int GetHashCode()
6390                 {
6391                         return block.GetHashCode ();
6392                 }
6393
6394                 public override bool Equals (object obj)
6395                 {
6396                         This t = obj as This;
6397                         if (t == null)
6398                                 return false;
6399
6400                         return block == t.block;
6401                 }
6402
6403                 protected class SimpleThis : Variable
6404                 {
6405                         Type type;
6406
6407                         public SimpleThis (Type type)
6408                         {
6409                                 this.type = type;
6410                         }
6411
6412                         public override Type Type {
6413                                 get { return type; }
6414                         }
6415
6416                         public override bool HasInstance {
6417                                 get { return false; }
6418                         }
6419
6420                         public override bool NeedsTemporary {
6421                                 get { return false; }
6422                         }
6423
6424                         public override void EmitInstance (EmitContext ec)
6425                         {
6426                                 // Do nothing.
6427                         }
6428
6429                         public override void Emit (EmitContext ec)
6430                         {
6431                                 ec.ig.Emit (OpCodes.Ldarg_0);
6432                         }
6433
6434                         public override void EmitAssign (EmitContext ec)
6435                         {
6436                                 throw new InvalidOperationException ();
6437                         }
6438
6439                         public override void EmitAddressOf (EmitContext ec)
6440                         {
6441                                 ec.ig.Emit (OpCodes.Ldarg_0);
6442                         }
6443                 }
6444
6445                 protected override void CloneTo (CloneContext clonectx, Expression t)
6446                 {
6447                         This target = (This) t;
6448
6449                         target.block = clonectx.LookupBlock (block);
6450                 }
6451         }
6452
6453         /// <summary>
6454         ///   Represents the `__arglist' construct
6455         /// </summary>
6456         public class ArglistAccess : Expression
6457         {
6458                 public ArglistAccess (Location loc)
6459                 {
6460                         this.loc = loc;
6461                 }
6462
6463                 public override Expression DoResolve (EmitContext ec)
6464                 {
6465                         eclass = ExprClass.Variable;
6466                         type = TypeManager.runtime_argument_handle_type;
6467
6468                         if (ec.IsInFieldInitializer || !ec.CurrentBlock.Toplevel.HasVarargs) 
6469                         {
6470                                 Error (190, "The __arglist construct is valid only within " +
6471                                        "a variable argument method");
6472                                 return null;
6473                         }
6474
6475                         return this;
6476                 }
6477
6478                 public override void Emit (EmitContext ec)
6479                 {
6480                         ec.ig.Emit (OpCodes.Arglist);
6481                 }
6482
6483                 protected override void CloneTo (CloneContext clonectx, Expression target)
6484                 {
6485                         // nothing.
6486                 }
6487         }
6488
6489         /// <summary>
6490         ///   Represents the `__arglist (....)' construct
6491         /// </summary>
6492         public class Arglist : Expression
6493         {
6494                 Argument[] Arguments;
6495
6496                 public Arglist (Location loc)
6497                         : this (Argument.Empty, loc)
6498                 {
6499                 }
6500
6501                 public Arglist (Argument[] args, Location l)
6502                 {
6503                         Arguments = args;
6504                         loc = l;
6505                 }
6506
6507                 public Type[] ArgumentTypes {
6508                         get {
6509                                 Type[] retval = new Type [Arguments.Length];
6510                                 for (int i = 0; i < Arguments.Length; i++)
6511                                         retval [i] = Arguments [i].Type;
6512                                 return retval;
6513                         }
6514                 }
6515                 
6516                 public override Expression CreateExpressionTree (EmitContext ec)
6517                 {
6518                         Report.Error (1952, loc, "An expression tree cannot contain a method with variable arguments");
6519                         return null;
6520                 }
6521
6522                 public override Expression DoResolve (EmitContext ec)
6523                 {
6524                         eclass = ExprClass.Variable;
6525                         type = TypeManager.runtime_argument_handle_type;
6526
6527                         foreach (Argument arg in Arguments) {
6528                                 if (!arg.Resolve (ec, loc))
6529                                         return null;
6530                         }
6531
6532                         return this;
6533                 }
6534
6535                 public override void Emit (EmitContext ec)
6536                 {
6537                         foreach (Argument arg in Arguments)
6538                                 arg.Emit (ec);
6539                 }
6540
6541                 protected override void CloneTo (CloneContext clonectx, Expression t)
6542                 {
6543                         Arglist target = (Arglist) t;
6544
6545                         target.Arguments = new Argument [Arguments.Length];
6546                         for (int i = 0; i < Arguments.Length; i++)
6547                                 target.Arguments [i] = Arguments [i].Clone (clonectx);
6548                 }
6549         }
6550
6551         //
6552         // This produces the value that renders an instance, used by the iterators code
6553         //
6554         public class ProxyInstance : Expression, IMemoryLocation  {
6555                 public override Expression DoResolve (EmitContext ec)
6556                 {
6557                         eclass = ExprClass.Variable;
6558                         type = ec.ContainerType;
6559                         return this;
6560                 }
6561                 
6562                 public override void Emit (EmitContext ec)
6563                 {
6564                         ec.ig.Emit (OpCodes.Ldarg_0);
6565
6566                 }
6567                 
6568                 public void AddressOf (EmitContext ec, AddressOp mode)
6569                 {
6570                         ec.ig.Emit (OpCodes.Ldarg_0);
6571                 }
6572         }
6573
6574         /// <summary>
6575         ///   Implements the typeof operator
6576         /// </summary>
6577         public class TypeOf : Expression {
6578                 Expression QueriedType;
6579                 protected Type typearg;
6580                 
6581                 public TypeOf (Expression queried_type, Location l)
6582                 {
6583                         QueriedType = queried_type;
6584                         loc = l;
6585                 }
6586
6587                 public override Expression DoResolve (EmitContext ec)
6588                 {
6589                         TypeExpr texpr = QueriedType.ResolveAsTypeTerminal (ec, false);
6590                         if (texpr == null)
6591                                 return null;
6592
6593                         typearg = texpr.Type;
6594
6595                         if (typearg == TypeManager.void_type) {
6596                                 Error (673, "System.Void cannot be used from C#. Use typeof (void) to get the void type object");
6597                                 return null;
6598                         }
6599
6600                         if (typearg.IsPointer && !ec.InUnsafe){
6601                                 UnsafeError (loc);
6602                                 return null;
6603                         }
6604
6605                         type = TypeManager.type_type;
6606
6607                         return DoResolveBase ();
6608                 }
6609
6610                 protected Expression DoResolveBase ()
6611                 {
6612                         if (TypeManager.system_type_get_type_from_handle == null) {
6613                                 TypeManager.system_type_get_type_from_handle = TypeManager.GetPredefinedMethod (
6614                                         TypeManager.type_type, "GetTypeFromHandle", loc, TypeManager.runtime_handle_type);
6615                         }
6616
6617                         // Even though what is returned is a type object, it's treated as a value by the compiler.
6618                         // In particular, 'typeof (Foo).X' is something totally different from 'Foo.X'.
6619                         eclass = ExprClass.Value;
6620                         return this;
6621                 }
6622
6623                 public override void Emit (EmitContext ec)
6624                 {
6625                         ec.ig.Emit (OpCodes.Ldtoken, typearg);
6626                         ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
6627                 }
6628
6629                 public override bool GetAttributableValue (Type value_type, out object value)
6630                 {
6631                         if (TypeManager.ContainsGenericParameters (typearg) &&
6632                                 !TypeManager.IsGenericTypeDefinition (typearg)) {
6633                                 Report.SymbolRelatedToPreviousError (typearg);
6634                                 Report.Error (416, loc, "`{0}': an attribute argument cannot use type parameters",
6635                                              TypeManager.CSharpName (typearg));
6636                                 value = null;
6637                                 return false;
6638                         }
6639
6640                         if (value_type == TypeManager.object_type) {
6641                                 value = (object)typearg;
6642                                 return true;
6643                         }
6644                         value = typearg;
6645                         return true;
6646                 }
6647
6648                 public Type TypeArgument
6649                 {
6650                         get
6651                         {
6652                                 return typearg;
6653                         }
6654                 }
6655
6656                 protected override void CloneTo (CloneContext clonectx, Expression t)
6657                 {
6658                         TypeOf target = (TypeOf) t;
6659
6660                         target.QueriedType = QueriedType.Clone (clonectx);
6661                 }
6662         }
6663
6664         /// <summary>
6665         ///   Implements the `typeof (void)' operator
6666         /// </summary>
6667         public class TypeOfVoid : TypeOf {
6668                 public TypeOfVoid (Location l) : base (null, l)
6669                 {
6670                         loc = l;
6671                 }
6672
6673                 public override Expression DoResolve (EmitContext ec)
6674                 {
6675                         type = TypeManager.type_type;
6676                         typearg = TypeManager.void_type;
6677
6678                         return DoResolveBase ();
6679                 }
6680         }
6681
6682         internal class TypeOfMethod : Expression
6683         {
6684                 readonly MethodBase method;
6685
6686                 public TypeOfMethod (MethodBase method, Location loc)
6687                 {
6688                         this.method = method;
6689                         this.loc = loc;
6690                 }
6691
6692                 public override Expression DoResolve (EmitContext ec)
6693                 {
6694                         bool is_generic = TypeManager.IsGenericType (method.DeclaringType);
6695                         MethodInfo mi = is_generic ?
6696                                 TypeManager.methodbase_get_type_from_handle_generic :
6697                                 TypeManager.methodbase_get_type_from_handle;
6698
6699                         if (mi == null) {
6700                                 Type t = TypeManager.CoreLookupType ("System.Reflection", "MethodBase", Kind.Class, true);
6701                                 Type handle_type = TypeManager.CoreLookupType ("System", "RuntimeMethodHandle", Kind.Class, true);
6702
6703                                 if (t == null || handle_type == null)
6704                                         return null;
6705
6706                                 mi = TypeManager.GetPredefinedMethod (t, "GetMethodFromHandle", loc,
6707                                         is_generic ?
6708                                         new Type[] { handle_type, TypeManager.runtime_handle_type } :
6709                                         new Type[] { handle_type } );
6710
6711                                 if (is_generic)
6712                                         TypeManager.methodbase_get_type_from_handle_generic = mi;
6713                                 else
6714                                         TypeManager.methodbase_get_type_from_handle = mi;
6715                         }
6716
6717                         type = typeof (MethodBase);
6718                         eclass = ExprClass.Value;
6719                         return this;
6720                 }
6721
6722                 public override void Emit (EmitContext ec)
6723                 {
6724                         if (method is MethodInfo)
6725                                 ec.ig.Emit (OpCodes.Ldtoken, (MethodInfo)method);
6726                         else
6727                                 ec.ig.Emit (OpCodes.Ldtoken, (ConstructorInfo) method);
6728
6729                         bool is_generic = TypeManager.IsGenericType (method.DeclaringType);
6730                         MethodInfo mi;
6731                         if (is_generic) {
6732                                 mi = TypeManager.methodbase_get_type_from_handle_generic;
6733                                 ec.ig.Emit (OpCodes.Ldtoken, method.DeclaringType);
6734                         } else {
6735                                 mi = TypeManager.methodbase_get_type_from_handle;
6736                         }
6737
6738                         ec.ig.Emit (OpCodes.Call, mi);
6739                 }
6740         }
6741
6742         internal class TypeOfField : Expression
6743         {
6744                 readonly FieldInfo field;
6745
6746                 public TypeOfField (FieldInfo field, Location loc)
6747                 {
6748                         this.field = field;
6749                         this.loc = loc;
6750                 }
6751
6752                 public override Expression DoResolve (EmitContext ec)
6753                 {
6754                         if (TypeManager.fieldinfo_get_field_from_handle == null) {
6755                                 Type t = TypeManager.CoreLookupType ("System.Reflection", "FieldInfo", Kind.Class, true);
6756                                 Type handle_type = TypeManager.CoreLookupType ("System", "RuntimeFieldHandle", Kind.Class, true);
6757
6758                                 if (t != null && handle_type != null)
6759                                         TypeManager.fieldinfo_get_field_from_handle = TypeManager.GetPredefinedMethod (t,
6760                                                 "GetFieldFromHandle", loc, handle_type);
6761                         }
6762
6763                         type = typeof (FieldInfo);
6764                         eclass = ExprClass.Value;
6765                         return this;
6766                 }
6767
6768                 public override void Emit (EmitContext ec)
6769                 {
6770                         ec.ig.Emit (OpCodes.Ldtoken, field);
6771                         ec.ig.Emit (OpCodes.Call, TypeManager.fieldinfo_get_field_from_handle);
6772                 }
6773         }
6774
6775         /// <summary>
6776         ///   Implements the sizeof expression
6777         /// </summary>
6778         public class SizeOf : Expression {
6779                 readonly Expression QueriedType;
6780                 Type type_queried;
6781                 
6782                 public SizeOf (Expression queried_type, Location l)
6783                 {
6784                         this.QueriedType = queried_type;
6785                         loc = l;
6786                 }
6787
6788                 public override Expression DoResolve (EmitContext ec)
6789                 {
6790                         TypeExpr texpr = QueriedType.ResolveAsTypeTerminal (ec, false);
6791                         if (texpr == null)
6792                                 return null;
6793
6794 #if GMCS_SOURCE
6795                         if (texpr is TypeParameterExpr){
6796                                 ((TypeParameterExpr)texpr).Error_CannotUseAsUnmanagedType (loc);
6797                                 return null;
6798                         }
6799 #endif
6800
6801                         type_queried = texpr.Type;
6802                         if (TypeManager.IsEnumType (type_queried))
6803                                 type_queried = TypeManager.GetEnumUnderlyingType (type_queried);
6804
6805                         if (type_queried == TypeManager.void_type) {
6806                                 Expression.Error_VoidInvalidInTheContext (loc);
6807                                 return null;
6808                         }
6809
6810                         int size_of = GetTypeSize (type_queried);
6811                         if (size_of > 0) {
6812                                 return new IntConstant (size_of, loc);
6813                         }
6814
6815                         if (!ec.InUnsafe) {
6816                                 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)",
6817                                          TypeManager.CSharpName (type_queried));
6818                                 return null;
6819                         }
6820
6821                         if (!TypeManager.VerifyUnManaged (type_queried, loc)){
6822                                 return null;
6823                         }
6824                         
6825                         type = TypeManager.int32_type;
6826                         eclass = ExprClass.Value;
6827                         return this;
6828                 }
6829
6830                 public override void Emit (EmitContext ec)
6831                 {
6832                         int size = GetTypeSize (type_queried);
6833
6834                         if (size == 0)
6835                                 ec.ig.Emit (OpCodes.Sizeof, type_queried);
6836                         else
6837                                 IntConstant.EmitInt (ec.ig, size);
6838                 }
6839
6840                 protected override void CloneTo (CloneContext clonectx, Expression t)
6841                 {
6842                 }
6843         }
6844
6845         /// <summary>
6846         ///   Implements the qualified-alias-member (::) expression.
6847         /// </summary>
6848         public class QualifiedAliasMember : Expression
6849         {
6850                 string alias, identifier;
6851
6852                 public QualifiedAliasMember (string alias, string identifier, Location l)
6853                 {
6854                         this.alias = alias;
6855                         this.identifier = identifier;
6856                         loc = l;
6857                 }
6858
6859                 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
6860                 {
6861                         if (alias == "global")
6862                                 return new MemberAccess (RootNamespace.Global, identifier, loc).ResolveAsTypeStep (ec, silent);
6863
6864                         int errors = Report.Errors;
6865                         FullNamedExpression fne = ec.DeclContainer.NamespaceEntry.LookupAlias (alias);
6866                         if (fne == null) {
6867                                 if (errors == Report.Errors)
6868                                         Report.Error (432, loc, "Alias `{0}' not found", alias);
6869                                 return null;
6870                         }
6871                         if (fne.eclass != ExprClass.Namespace) {
6872                                 if (!silent)
6873                                         Report.Error (431, loc, "`{0}' cannot be used with '::' since it denotes a type", alias);
6874                                 return null;
6875                         }
6876                         return new MemberAccess (fne, identifier).ResolveAsTypeStep (ec, silent);
6877                 }
6878
6879                 public override Expression DoResolve (EmitContext ec)
6880                 {
6881                         FullNamedExpression fne;
6882                         if (alias == "global") {
6883                                 fne = RootNamespace.Global;
6884                         } else {
6885                                 int errors = Report.Errors;
6886                                 fne = ec.DeclContainer.NamespaceEntry.LookupAlias (alias);
6887                                 if (fne == null) {
6888                                         if (errors == Report.Errors)
6889                                                 Report.Error (432, loc, "Alias `{0}' not found", alias);
6890                                         return null;
6891                                 }
6892                         }
6893
6894                         Expression retval = new MemberAccess (fne, identifier).DoResolve (ec);
6895                         if (retval == null)
6896                                 return null;
6897
6898                         if (!(retval is FullNamedExpression)) {
6899                                 Report.Error (687, loc, "The expression `{0}::{1}' did not resolve to a namespace or a type", alias, identifier);
6900                                 return null;
6901                         }
6902
6903                         // We defer this check till the end to match the behaviour of CSC
6904                         if (fne.eclass != ExprClass.Namespace) {
6905                                 Report.Error (431, loc, "`{0}' cannot be used with '::' since it denotes a type", alias);
6906                                 return null;
6907                         }
6908                         return retval;
6909                 }
6910
6911                 public override void Emit (EmitContext ec)
6912                 {
6913                         throw new InternalErrorException ("QualifiedAliasMember found in resolved tree");
6914                 }
6915
6916
6917                 public override string ToString ()
6918                 {
6919                         return alias + "::" + identifier;
6920                 }
6921
6922                 public override string GetSignatureForError ()
6923                 {
6924                         return ToString ();
6925                 }
6926
6927                 protected override void CloneTo (CloneContext clonectx, Expression t)
6928                 {
6929                         // Nothing 
6930                 }
6931         }
6932
6933         /// <summary>
6934         ///   Implements the member access expression
6935         /// </summary>
6936         public class MemberAccess : Expression {
6937                 public readonly string Identifier;
6938                 Expression expr;
6939                 readonly TypeArguments args;
6940
6941                 public MemberAccess (Expression expr, string id)
6942                         : this (expr, id, expr.Location)
6943                 {
6944                 }
6945
6946                 public MemberAccess (Expression expr, string identifier, Location loc)
6947                 {
6948                         this.expr = expr;
6949                         Identifier = identifier;
6950                         this.loc = loc;
6951                 }
6952
6953                 public MemberAccess (Expression expr, string identifier, TypeArguments args, Location loc)
6954                         : this (expr, identifier, loc)
6955                 {
6956                         this.args = args;
6957                 }
6958
6959                 protected string LookupIdentifier {
6960                         get { return MemberName.MakeName (Identifier, args); }
6961                 }
6962
6963                 // TODO: this method has very poor performace for Enum fields and
6964                 // probably for other constants as well
6965                 Expression DoResolve (EmitContext ec, Expression right_side)
6966                 {
6967                         if (type != null)
6968                                 throw new Exception ();
6969
6970                         //
6971                         // Resolve the expression with flow analysis turned off, we'll do the definite
6972                         // assignment checks later.  This is because we don't know yet what the expression
6973                         // will resolve to - it may resolve to a FieldExpr and in this case we must do the
6974                         // definite assignment check on the actual field and not on the whole struct.
6975                         //
6976
6977                         SimpleName original = expr as SimpleName;
6978                         Expression expr_resolved = expr.Resolve (ec,
6979                                 ResolveFlags.VariableOrValue | ResolveFlags.Type |
6980                                 ResolveFlags.Intermediate | ResolveFlags.DisableStructFlowAnalysis);
6981
6982                         if (expr_resolved == null)
6983                                 return null;
6984
6985                         if (expr_resolved is Namespace) {
6986                                 Namespace ns = (Namespace) expr_resolved;
6987                                 FullNamedExpression retval = ns.Lookup (ec.DeclContainer, LookupIdentifier, loc);
6988 #if GMCS_SOURCE
6989                                 if ((retval != null) && (args != null))
6990                                         retval = new ConstructedType (retval, args, loc).ResolveAsTypeStep (ec, false);
6991 #endif
6992
6993                                 if (retval == null)
6994                                         ns.Error_NamespaceDoesNotExist (ec.DeclContainer, loc, Identifier);
6995                                 return retval;
6996                         }
6997
6998                         Type expr_type = expr_resolved.Type;
6999                         if (expr_type.IsPointer || expr_type == TypeManager.void_type || expr_resolved is NullLiteral){
7000                                 Unary.Error_OperatorCannotBeApplied (loc, ".", expr_type);
7001                                 return null;
7002                         }
7003                         if (expr_type == TypeManager.anonymous_method_type){
7004                                 Unary.Error_OperatorCannotBeApplied (loc, ".", "anonymous method");
7005                                 return null;
7006                         }
7007
7008                         Constant c = expr_resolved as Constant;
7009                         if (c != null && c.GetValue () == null) {
7010                                 Report.Warning (1720, 1, loc, "Expression will always cause a `{0}'",
7011                                         "System.NullReferenceException");
7012                         }
7013
7014                         if (args != null) {
7015                                 if (!args.Resolve (ec))
7016                                         return null;
7017                         }
7018
7019                         Expression member_lookup;
7020                         member_lookup = MemberLookup (
7021                                 ec.ContainerType, expr_type, expr_type, Identifier, loc);
7022 #if GMCS_SOURCE
7023                         if ((member_lookup == null) && (args != null)) {
7024                                 member_lookup = MemberLookup (
7025                                         ec.ContainerType, expr_type, expr_type, LookupIdentifier, loc);
7026                         }
7027 #endif
7028                         if (member_lookup == null) {
7029                                 ExprClass expr_eclass = expr_resolved.eclass;
7030
7031                                 //
7032                                 // Extension methods are not allowed on all expression types
7033                                 //
7034                                 if (expr_eclass == ExprClass.Value || expr_eclass == ExprClass.Variable ||
7035                                         expr_eclass == ExprClass.IndexerAccess || expr_eclass == ExprClass.PropertyAccess ||
7036                                         expr_eclass == ExprClass.EventAccess) {
7037                                         ExtensionMethodGroupExpr ex_method_lookup = ec.TypeContainer.LookupExtensionMethod (expr_type, Identifier, loc);
7038                                         if (ex_method_lookup != null) {
7039                                                 ex_method_lookup.ExtensionExpression = expr_resolved;
7040
7041                                                 if (args != null) {
7042                                                         ex_method_lookup.SetTypeArguments (args);
7043                                                 }
7044
7045                                                 return ex_method_lookup.DoResolve (ec);
7046                                         }
7047                                 }
7048
7049                                 expr = expr_resolved;
7050                                 Error_MemberLookupFailed (
7051                                         ec.ContainerType, expr_type, expr_type, Identifier, null,
7052                                         AllMemberTypes, AllBindingFlags);
7053                                 return null;
7054                         }
7055
7056                         TypeExpr texpr = member_lookup as TypeExpr;
7057                         if (texpr != null) {
7058                                 if (!(expr_resolved is TypeExpr) && 
7059                                     (original == null || !original.IdenticalNameAndTypeName (ec, expr_resolved, loc))) {
7060                                         Report.Error (572, loc, "`{0}': cannot reference a type through an expression; try `{1}' instead",
7061                                                 Identifier, member_lookup.GetSignatureForError ());
7062                                         return null;
7063                                 }
7064
7065                                 if (!texpr.CheckAccessLevel (ec.DeclContainer)) {
7066                                         Report.SymbolRelatedToPreviousError (member_lookup.Type);
7067                                         ErrorIsInaccesible (loc, TypeManager.CSharpName (member_lookup.Type));
7068                                         return null;
7069                                 }
7070
7071 #if GMCS_SOURCE
7072                                 ConstructedType ct = expr_resolved as ConstructedType;
7073                                 if (ct != null) {
7074                                         //
7075                                         // When looking up a nested type in a generic instance
7076                                         // via reflection, we always get a generic type definition
7077                                         // and not a generic instance - so we have to do this here.
7078                                         //
7079                                         // See gtest-172-lib.cs and gtest-172.cs for an example.
7080                                         //
7081                                         ct = new ConstructedType (
7082                                                 member_lookup.Type, ct.TypeArguments, loc);
7083
7084                                         return ct.ResolveAsTypeStep (ec, false);
7085                                 }
7086 #endif
7087                                 return member_lookup;
7088                         }
7089
7090                         MemberExpr me = (MemberExpr) member_lookup;
7091                         me = me.ResolveMemberAccess (ec, expr_resolved, loc, original);
7092                         if (me == null)
7093                                 return null;
7094
7095                         if (args != null) {
7096                                 me.SetTypeArguments (args);
7097                         }
7098
7099                         if (original != null && !TypeManager.IsValueType (expr_type)) {
7100                                 if (me.IsInstance) {
7101                                         LocalVariableReference var = expr_resolved as LocalVariableReference;
7102                                         if (var != null && !var.VerifyAssigned (ec))
7103                                                 return null;
7104                                 }
7105                         }
7106
7107                         // The following DoResolve/DoResolveLValue will do the definite assignment
7108                         // check.
7109
7110                         if (right_side != null)
7111                                 return me.DoResolveLValue (ec, right_side);
7112                         else
7113                                 return me.DoResolve (ec);
7114                 }
7115
7116                 public override Expression DoResolve (EmitContext ec)
7117                 {
7118                         return DoResolve (ec, null);
7119                 }
7120
7121                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
7122                 {
7123                         return DoResolve (ec, right_side);
7124                 }
7125
7126                 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
7127                 {
7128                         return ResolveNamespaceOrType (ec, silent);
7129                 }
7130
7131                 public FullNamedExpression ResolveNamespaceOrType (IResolveContext rc, bool silent)
7132                 {
7133                         FullNamedExpression new_expr = expr.ResolveAsTypeStep (rc, silent);
7134
7135                         if (new_expr == null)
7136                                 return null;
7137
7138                         if (new_expr is Namespace) {
7139                                 Namespace ns = (Namespace) new_expr;
7140                                 FullNamedExpression retval = ns.Lookup (rc.DeclContainer, LookupIdentifier, loc);
7141 #if GMCS_SOURCE
7142                                 if ((retval != null) && (args != null))
7143                                         retval = new ConstructedType (retval, args, loc).ResolveAsTypeStep (rc, false);
7144 #endif
7145                                 if (!silent && retval == null)
7146                                         ns.Error_NamespaceDoesNotExist (rc.DeclContainer, loc, LookupIdentifier);
7147                                 return retval;
7148                         }
7149
7150                         TypeExpr tnew_expr = new_expr.ResolveAsTypeTerminal (rc, false);
7151                         if (tnew_expr == null)
7152                                 return null;
7153
7154                         Type expr_type = tnew_expr.Type;
7155
7156                         if (expr_type.IsPointer){
7157                                 Error (23, "The `.' operator can not be applied to pointer operands (" +
7158                                        TypeManager.CSharpName (expr_type) + ")");
7159                                 return null;
7160                         }
7161
7162                         Expression member_lookup = MemberLookup (
7163                                 rc.DeclContainer.TypeBuilder, expr_type, expr_type, LookupIdentifier,
7164                                 MemberTypes.NestedType, BindingFlags.Public | BindingFlags.NonPublic, loc);
7165                         if (member_lookup == null) {
7166                                 if (silent)
7167                                         return null;
7168
7169                                 member_lookup = MemberLookup (
7170                                         rc.DeclContainer.TypeBuilder, expr_type, expr_type, SimpleName.RemoveGenericArity (LookupIdentifier),
7171                                         MemberTypes.NestedType, BindingFlags.Public | BindingFlags.NonPublic, loc);
7172
7173                                 if (member_lookup != null) {
7174                                         tnew_expr = member_lookup.ResolveAsTypeTerminal (rc, false);
7175                                         if (tnew_expr == null)
7176                                                 return null;
7177
7178                                         Namespace.Error_TypeArgumentsCannotBeUsed (tnew_expr.Type, loc);
7179                                         return null;
7180                                 }
7181
7182                                 member_lookup = MemberLookup (
7183                                         rc.DeclContainer.TypeBuilder, expr_type, expr_type, LookupIdentifier,
7184                                                 MemberTypes.All, BindingFlags.Public | BindingFlags.NonPublic, loc);
7185
7186                                 if (member_lookup == null) {
7187                                         Report.Error (426, loc, "The nested type `{0}' does not exist in the type `{1}'",
7188                                                           Identifier, new_expr.GetSignatureForError ());
7189                                 } else {
7190                                         // TODO: Report.SymbolRelatedToPreviousError
7191                                         member_lookup.Error_UnexpectedKind (null, "type", loc);
7192                                 }
7193                                 return null;
7194                         }
7195
7196                         TypeExpr texpr = member_lookup.ResolveAsTypeTerminal (rc, false);
7197                         if (texpr == null)
7198                                 return null;
7199
7200 #if GMCS_SOURCE
7201                         TypeArguments the_args = args;
7202                         Type declaring_type = texpr.Type.DeclaringType;
7203                         if (TypeManager.HasGenericArguments (declaring_type)) {
7204                                 while (!TypeManager.IsEqual (TypeManager.DropGenericTypeArguments (expr_type), declaring_type)) {
7205                                         expr_type = expr_type.BaseType;
7206                                 }
7207                                 
7208                                 TypeArguments new_args = new TypeArguments (loc);
7209                                 foreach (Type decl in TypeManager.GetTypeArguments (expr_type))
7210                                         new_args.Add (new TypeExpression (decl, loc));
7211
7212                                 if (args != null)
7213                                         new_args.Add (args);
7214
7215                                 the_args = new_args;
7216                         }
7217
7218                         if (the_args != null) {
7219                                 ConstructedType ctype = new ConstructedType (texpr.Type, the_args, loc);
7220                                 return ctype.ResolveAsTypeStep (rc, false);
7221                         }
7222 #endif
7223
7224                         return texpr;
7225                 }
7226
7227                 public override void Emit (EmitContext ec)
7228                 {
7229                         throw new Exception ("Should not happen");
7230                 }
7231
7232                 protected override void Error_TypeDoesNotContainDefinition (Type type, string name)
7233                 {
7234                         if (RootContext.Version > LanguageVersion.ISO_2 &&
7235                                 ((expr.eclass & (ExprClass.Value | ExprClass.Variable)) != 0)) {
7236                                 Report.Error (1061, loc, "Type `{0}' does not contain a definition for `{1}' and no " +
7237                                         "extension method `{1}' of type `{0}' could be found " +
7238                                         "(are you missing a using directive or an assembly reference?)",
7239                                         TypeManager.CSharpName (type), name);
7240                                 return;
7241                         }
7242
7243                         base.Error_TypeDoesNotContainDefinition (type, name);
7244                 }
7245
7246                 public override string ToString ()
7247                 {
7248                         return expr + "." + MemberName.MakeName (Identifier, args);
7249                 }
7250
7251                 public override string GetSignatureForError ()
7252                 {
7253                         return expr.GetSignatureForError () + "." + Identifier;
7254                 }
7255
7256                 protected override void CloneTo (CloneContext clonectx, Expression t)
7257                 {
7258                         MemberAccess target = (MemberAccess) t;
7259
7260                         target.expr = expr.Clone (clonectx);
7261                 }
7262         }
7263
7264         /// <summary>
7265         ///   Implements checked expressions
7266         /// </summary>
7267         public class CheckedExpr : Expression {
7268
7269                 public Expression Expr;
7270
7271                 public CheckedExpr (Expression e, Location l)
7272                 {
7273                         Expr = e;
7274                         loc = l;
7275                 }
7276                 
7277                 public override Expression CreateExpressionTree (EmitContext ec)
7278                 {
7279                         using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
7280                                 return Expr.CreateExpressionTree (ec);
7281                 }
7282
7283                 public override Expression DoResolve (EmitContext ec)
7284                 {
7285                         using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
7286                                 Expr = Expr.Resolve (ec);
7287                         
7288                         if (Expr == null)
7289                                 return null;
7290
7291                         if (Expr is Constant)
7292                                 return Expr;
7293                         
7294                         eclass = Expr.eclass;
7295                         type = Expr.Type;
7296                         return this;
7297                 }
7298
7299                 public override void Emit (EmitContext ec)
7300                 {
7301                         using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
7302                                 Expr.Emit (ec);
7303                 }
7304
7305                 public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
7306                 {
7307                         using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
7308                                 Expr.EmitBranchable (ec, target, on_true);
7309                 }
7310
7311                 protected override void CloneTo (CloneContext clonectx, Expression t)
7312                 {
7313                         CheckedExpr target = (CheckedExpr) t;
7314
7315                         target.Expr = Expr.Clone (clonectx);
7316                 }
7317         }
7318
7319         /// <summary>
7320         ///   Implements the unchecked expression
7321         /// </summary>
7322         public class UnCheckedExpr : Expression {
7323
7324                 public Expression Expr;
7325
7326                 public UnCheckedExpr (Expression e, Location l)
7327                 {
7328                         Expr = e;
7329                         loc = l;
7330                 }
7331                 
7332                 public override Expression CreateExpressionTree (EmitContext ec)
7333                 {
7334                         using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
7335                                 return Expr.CreateExpressionTree (ec);
7336                 }
7337
7338                 public override Expression DoResolve (EmitContext ec)
7339                 {
7340                         using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
7341                                 Expr = Expr.Resolve (ec);
7342
7343                         if (Expr == null)
7344                                 return null;
7345
7346                         if (Expr is Constant)
7347                                 return Expr;
7348                         
7349                         eclass = Expr.eclass;
7350                         type = Expr.Type;
7351                         return this;
7352                 }
7353
7354                 public override void Emit (EmitContext ec)
7355                 {
7356                         using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
7357                                 Expr.Emit (ec);
7358                 }
7359                 
7360                 public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
7361                 {
7362                         using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
7363                                 Expr.EmitBranchable (ec, target, on_true);
7364                 }
7365
7366                 protected override void CloneTo (CloneContext clonectx, Expression t)
7367                 {
7368                         UnCheckedExpr target = (UnCheckedExpr) t;
7369
7370                         target.Expr = Expr.Clone (clonectx);
7371                 }
7372         }
7373
7374         /// <summary>
7375         ///   An Element Access expression.
7376         ///
7377         ///   During semantic analysis these are transformed into 
7378         ///   IndexerAccess, ArrayAccess or a PointerArithmetic.
7379         /// </summary>
7380         public class ElementAccess : Expression {
7381                 public ArrayList  Arguments;
7382                 public Expression Expr;
7383                 
7384                 public ElementAccess (Expression e, ArrayList e_list)
7385                 {
7386                         Expr = e;
7387
7388                         loc  = e.Location;
7389                         
7390                         if (e_list == null)
7391                                 return;
7392                         
7393                         Arguments = new ArrayList ();
7394                         foreach (Expression tmp in e_list)
7395                                 Arguments.Add (new Argument (tmp, Argument.AType.Expression));
7396                         
7397                 }
7398
7399                 bool CommonResolve (EmitContext ec)
7400                 {
7401                         Expr = Expr.Resolve (ec);
7402
7403                         if (Arguments == null)
7404                                 return false;
7405
7406                         foreach (Argument a in Arguments){
7407                                 if (!a.Resolve (ec, loc))
7408                                         return false;
7409                         }
7410
7411                         return Expr != null;
7412                 }
7413
7414                 public override Expression CreateExpressionTree (EmitContext ec)
7415                 {
7416                         ArrayList args = new ArrayList (Arguments.Count + 1);
7417                         args.Add (new Argument (Expr.CreateExpressionTree (ec)));
7418                         foreach (Argument a in Arguments)
7419                                 args.Add (new Argument (a.Expr.CreateExpressionTree (ec)));
7420
7421                         return CreateExpressionFactoryCall ("ArrayIndex", args);
7422                 }
7423
7424                 Expression MakePointerAccess (EmitContext ec, Type t)
7425                 {
7426                         if (t == TypeManager.void_ptr_type){
7427                                 Error (242, "The array index operation is not valid on void pointers");
7428                                 return null;
7429                         }
7430                         if (Arguments.Count != 1){
7431                                 Error (196, "A pointer must be indexed by only one value");
7432                                 return null;
7433                         }
7434                         Expression p;
7435
7436                         p = new PointerArithmetic (true, Expr, ((Argument)Arguments [0]).Expr, t, loc).Resolve (ec);
7437                         if (p == null)
7438                                 return null;
7439                         return new Indirection (p, loc).Resolve (ec);
7440                 }
7441                 
7442                 public override Expression DoResolve (EmitContext ec)
7443                 {
7444                         if (!CommonResolve (ec))
7445                                 return null;
7446
7447                         //
7448                         // We perform some simple tests, and then to "split" the emit and store
7449                         // code we create an instance of a different class, and return that.
7450                         //
7451                         // I am experimenting with this pattern.
7452                         //
7453                         Type t = Expr.Type;
7454
7455                         if (t == TypeManager.array_type){
7456                                 Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `System.Array'");
7457                                 return null;
7458                         }
7459                         
7460                         if (t.IsArray)
7461                                 return (new ArrayAccess (this, loc)).Resolve (ec);
7462                         if (t.IsPointer)
7463                                 return MakePointerAccess (ec, t);
7464
7465                         FieldExpr fe = Expr as FieldExpr;
7466                         if (fe != null) {
7467                                 IFixedBuffer ff = AttributeTester.GetFixedBuffer (fe.FieldInfo);
7468                                 if (ff != null) {
7469                                         return MakePointerAccess (ec, ff.ElementType);
7470                                 }
7471                         }
7472                         return (new IndexerAccess (this, loc)).Resolve (ec);
7473                 }
7474
7475                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
7476                 {
7477                         if (!CommonResolve (ec))
7478                                 return null;
7479
7480                         type = Expr.Type;
7481                         if (type.IsArray)
7482                                 return (new ArrayAccess (this, loc)).DoResolveLValue (ec, right_side);
7483
7484                         if (type.IsPointer)
7485                                 return MakePointerAccess (ec, type);
7486
7487                         if (Expr.eclass != ExprClass.Variable && type.IsValueType)
7488                                 Error_CannotModifyIntermediateExpressionValue (ec);
7489
7490                         return (new IndexerAccess (this, loc)).DoResolveLValue (ec, right_side);
7491                 }
7492                 
7493                 public override void Emit (EmitContext ec)
7494                 {
7495                         throw new Exception ("Should never be reached");
7496                 }
7497
7498                 public override string GetSignatureForError ()
7499                 {
7500                         return Expr.GetSignatureForError ();
7501                 }
7502
7503                 protected override void CloneTo (CloneContext clonectx, Expression t)
7504                 {
7505                         ElementAccess target = (ElementAccess) t;
7506
7507                         target.Expr = Expr.Clone (clonectx);
7508                         target.Arguments = new ArrayList (Arguments.Count);
7509                         foreach (Argument a in Arguments)
7510                                 target.Arguments.Add (a.Clone (clonectx));
7511                 }
7512         }
7513
7514         /// <summary>
7515         ///   Implements array access 
7516         /// </summary>
7517         public class ArrayAccess : Expression, IAssignMethod, IMemoryLocation {
7518                 //
7519                 // Points to our "data" repository
7520                 //
7521                 ElementAccess ea;
7522
7523                 LocalTemporary temp;
7524                 LocalTemporary prepared_value;
7525
7526                 bool prepared;
7527                 
7528                 public ArrayAccess (ElementAccess ea_data, Location l)
7529                 {
7530                         ea = ea_data;
7531                         eclass = ExprClass.Variable;
7532                         loc = l;
7533                 }
7534
7535                 public override Expression CreateExpressionTree (EmitContext ec)
7536                 {
7537                         return ea.CreateExpressionTree (ec);
7538                 }
7539
7540                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
7541                 {
7542                         return DoResolve (ec);
7543                 }
7544
7545                 public override Expression DoResolve (EmitContext ec)
7546                 {
7547 #if false
7548                         ExprClass eclass = ea.Expr.eclass;
7549
7550                         // As long as the type is valid
7551                         if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
7552                               eclass == ExprClass.Value)) {
7553                                 ea.Expr.Error_UnexpectedKind ("variable or value");
7554                                 return null;
7555                         }
7556 #endif
7557
7558                         Type t = ea.Expr.Type;
7559                         int rank = ea.Arguments.Count;
7560                         if (t.GetArrayRank () != rank) {
7561                                 Report.Error (22, ea.Location, "Wrong number of indexes `{0}' inside [], expected `{1}'",
7562                                           ea.Arguments.Count.ToString (), t.GetArrayRank ().ToString ());
7563                                 return null;
7564                         }
7565
7566                         if (rank != 1 && TypeManager.int_getlength_int == null) {
7567                                 TypeManager.int_getlength_int = TypeManager.GetPredefinedMethod (
7568                                         TypeManager.array_type, "GetLength", loc, TypeManager.int32_type);
7569                         }
7570
7571                         type = TypeManager.GetElementType (t);
7572                         if (type.IsPointer && !ec.InUnsafe) {
7573                                 UnsafeError (ea.Location);
7574                                 return null;
7575                         }
7576
7577                         foreach (Argument a in ea.Arguments) {
7578                                 a.Expr = ConvertExpressionToArrayIndex (ec, a.Expr);
7579                         }
7580                         
7581                         eclass = ExprClass.Variable;
7582
7583                         return this;
7584                 }
7585
7586                 /// <summary>
7587                 ///    Emits the right opcode to load an object of Type `t'
7588                 ///    from an array of T
7589                 /// </summary>
7590                 void EmitLoadOpcode (ILGenerator ig, Type type, int rank)
7591                 {
7592                         if (rank > 1) {
7593                                 MethodInfo get = FetchGetMethod ();
7594                                 ig.Emit (OpCodes.Call, get);
7595                                 return;
7596                         }
7597
7598                         if (type == TypeManager.byte_type || type == TypeManager.bool_type)
7599                                 ig.Emit (OpCodes.Ldelem_U1);
7600                         else if (type == TypeManager.sbyte_type)
7601                                 ig.Emit (OpCodes.Ldelem_I1);
7602                         else if (type == TypeManager.short_type)
7603                                 ig.Emit (OpCodes.Ldelem_I2);
7604                         else if (type == TypeManager.ushort_type || type == TypeManager.char_type)
7605                                 ig.Emit (OpCodes.Ldelem_U2);
7606                         else if (type == TypeManager.int32_type)
7607                                 ig.Emit (OpCodes.Ldelem_I4);
7608                         else if (type == TypeManager.uint32_type)
7609                                 ig.Emit (OpCodes.Ldelem_U4);
7610                         else if (type == TypeManager.uint64_type)
7611                                 ig.Emit (OpCodes.Ldelem_I8);
7612                         else if (type == TypeManager.int64_type)
7613                                 ig.Emit (OpCodes.Ldelem_I8);
7614                         else if (type == TypeManager.float_type)
7615                                 ig.Emit (OpCodes.Ldelem_R4);
7616                         else if (type == TypeManager.double_type)
7617                                 ig.Emit (OpCodes.Ldelem_R8);
7618                         else if (type == TypeManager.intptr_type)
7619                                 ig.Emit (OpCodes.Ldelem_I);
7620                         else if (TypeManager.IsEnumType (type)){
7621                                 EmitLoadOpcode (ig, TypeManager.GetEnumUnderlyingType (type), rank);
7622                         } else if (type.IsValueType){
7623                                 ig.Emit (OpCodes.Ldelema, type);
7624                                 ig.Emit (OpCodes.Ldobj, type);
7625 #if GMCS_SOURCE
7626                         } else if (type.IsGenericParameter) {
7627                                 ig.Emit (OpCodes.Ldelem, type);
7628 #endif
7629                         } else if (type.IsPointer)
7630                                 ig.Emit (OpCodes.Ldelem_I);
7631                         else
7632                                 ig.Emit (OpCodes.Ldelem_Ref);
7633                 }
7634
7635                 protected override void Error_NegativeArrayIndex (Location loc)
7636                 {
7637                         Report.Warning (251, 2, loc, "Indexing an array with a negative index (array indices always start at zero)");
7638                 }
7639
7640                 /// <summary>
7641                 ///    Returns the right opcode to store an object of Type `t'
7642                 ///    from an array of T.  
7643                 /// </summary>
7644                 static public OpCode GetStoreOpcode (Type t, out bool is_stobj, out bool has_type_arg)
7645                 {
7646                         //Console.WriteLine (new System.Diagnostics.StackTrace ());
7647                         has_type_arg = false; is_stobj = false;
7648                         t = TypeManager.TypeToCoreType (t);
7649                         if (TypeManager.IsEnumType (t))
7650                                 t = TypeManager.GetEnumUnderlyingType (t);
7651                         if (t == TypeManager.byte_type || t == TypeManager.sbyte_type ||
7652                             t == TypeManager.bool_type)
7653                                 return OpCodes.Stelem_I1;
7654                         else if (t == TypeManager.short_type || t == TypeManager.ushort_type ||
7655                                  t == TypeManager.char_type)
7656                                 return OpCodes.Stelem_I2;
7657                         else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
7658                                 return OpCodes.Stelem_I4;
7659                         else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
7660                                 return OpCodes.Stelem_I8;
7661                         else if (t == TypeManager.float_type)
7662                                 return OpCodes.Stelem_R4;
7663                         else if (t == TypeManager.double_type)
7664                                 return OpCodes.Stelem_R8;
7665                         else if (t == TypeManager.intptr_type) {
7666                                 has_type_arg = true;
7667                                 is_stobj = true;
7668                                 return OpCodes.Stobj;
7669                         } else if (t.IsValueType) {
7670                                 has_type_arg = true;
7671                                 is_stobj = true;
7672                                 return OpCodes.Stobj;
7673 #if GMCS_SOURCE
7674                         } else if (t.IsGenericParameter) {
7675                                 has_type_arg = true;
7676                                 return OpCodes.Stelem;
7677 #endif
7678
7679                         } else if (t.IsPointer)
7680                                 return OpCodes.Stelem_I;
7681                         else
7682                                 return OpCodes.Stelem_Ref;
7683                 }
7684
7685                 MethodInfo FetchGetMethod ()
7686                 {
7687                         ModuleBuilder mb = CodeGen.Module.Builder;
7688                         int arg_count = ea.Arguments.Count;
7689                         Type [] args = new Type [arg_count];
7690                         MethodInfo get;
7691                         
7692                         for (int i = 0; i < arg_count; i++){
7693                                 //args [i++] = a.Type;
7694                                 args [i] = TypeManager.int32_type;
7695                         }
7696                         
7697                         get = mb.GetArrayMethod (
7698                                 ea.Expr.Type, "Get",
7699                                 CallingConventions.HasThis |
7700                                 CallingConventions.Standard,
7701                                 type, args);
7702                         return get;
7703                 }
7704                                 
7705
7706                 MethodInfo FetchAddressMethod ()
7707                 {
7708                         ModuleBuilder mb = CodeGen.Module.Builder;
7709                         int arg_count = ea.Arguments.Count;
7710                         Type [] args = new Type [arg_count];
7711                         MethodInfo address;
7712                         Type ret_type;
7713                         
7714                         ret_type = TypeManager.GetReferenceType (type);
7715                         
7716                         for (int i = 0; i < arg_count; i++){
7717                                 //args [i++] = a.Type;
7718                                 args [i] = TypeManager.int32_type;
7719                         }
7720                         
7721                         address = mb.GetArrayMethod (
7722                                 ea.Expr.Type, "Address",
7723                                 CallingConventions.HasThis |
7724                                 CallingConventions.Standard,
7725                                 ret_type, args);
7726
7727                         return address;
7728                 }
7729
7730                 //
7731                 // Load the array arguments into the stack.
7732                 //
7733                 // If we have been requested to cache the values (cached_locations array
7734                 // initialized), then load the arguments the first time and store them
7735                 // in locals.  otherwise load from local variables.
7736                 //
7737                 // prepare_for_load is used in compound assignments to cache original index
7738                 // values ( label[idx++] += s )
7739                 //
7740                 LocalTemporary [] LoadArrayAndArguments (EmitContext ec, bool prepare_for_load)
7741                 {
7742                         ea.Expr.Emit (ec);
7743
7744                         LocalTemporary[] indexes = null;
7745                         if (prepare_for_load) {
7746                                 ec.ig.Emit (OpCodes.Dup);
7747                                 indexes = new LocalTemporary [ea.Arguments.Count];
7748                         }
7749
7750                         for (int i = 0; i < ea.Arguments.Count; ++i) {
7751                                 ((Argument)ea.Arguments [i]).Emit (ec);
7752                                 if (!prepare_for_load)
7753                                         continue;
7754
7755                                 // Keep original array index value on the stack
7756                                 ec.ig.Emit (OpCodes.Dup);
7757
7758                                 indexes [i] = new LocalTemporary (TypeManager.intptr_type);
7759                                 indexes [i].Store (ec);
7760                         }
7761
7762                         return indexes;
7763                 }
7764
7765                 public void Emit (EmitContext ec, bool leave_copy)
7766                 {
7767                         int rank = ea.Expr.Type.GetArrayRank ();
7768                         ILGenerator ig = ec.ig;
7769
7770                         if (prepared_value != null) {
7771                                 prepared_value.Emit (ec);
7772                         } else if (prepared) {
7773                                 LoadFromPtr (ig, this.type);
7774                         } else {
7775                                 LoadArrayAndArguments (ec, false);
7776                                 EmitLoadOpcode (ig, type, rank);
7777                         }       
7778
7779                         if (leave_copy) {
7780                                 ig.Emit (OpCodes.Dup);
7781                                 temp = new LocalTemporary (this.type);
7782                                 temp.Store (ec);
7783                         }
7784                 }
7785                 
7786                 public override void Emit (EmitContext ec)
7787                 {
7788                         Emit (ec, false);
7789                 }
7790
7791                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
7792                 {
7793                         int rank = ea.Expr.Type.GetArrayRank ();
7794                         ILGenerator ig = ec.ig;
7795                         Type t = source.Type;
7796                         prepared = prepare_for_load && !(source is StringConcat);
7797
7798                         if (prepared) {
7799                                 AddressOf (ec, AddressOp.LoadStore);
7800                                 ec.ig.Emit (OpCodes.Dup);
7801                         } else {
7802                                 LocalTemporary[] original_indexes_values = LoadArrayAndArguments (ec,
7803                                         prepare_for_load && (source is StringConcat));
7804
7805                                 if (original_indexes_values != null) {
7806                                         prepared_value = new LocalTemporary (type);
7807                                         EmitLoadOpcode (ig, type, rank);
7808                                         prepared_value.Store (ec);
7809                                         foreach (LocalTemporary lt in original_indexes_values) {
7810                                                 lt.Emit (ec);
7811                                                 lt.Release (ec);
7812                                         }
7813                                 }
7814                         }
7815
7816                         if (rank == 1) {
7817                                 bool is_stobj, has_type_arg;
7818                                 OpCode op = GetStoreOpcode (t, out is_stobj, out has_type_arg);
7819
7820                                 if (!prepared) {
7821                                         //
7822                                         // The stobj opcode used by value types will need
7823                                         // an address on the stack, not really an array/array
7824                                         // pair
7825                                         //
7826                                         if (is_stobj)
7827                                                 ig.Emit (OpCodes.Ldelema, t);
7828                                 }
7829                                 
7830                                 source.Emit (ec);
7831                                 if (leave_copy) {
7832                                         ec.ig.Emit (OpCodes.Dup);
7833                                         temp = new LocalTemporary (this.type);
7834                                         temp.Store (ec);
7835                                 }
7836                                 
7837                                 if (prepared)
7838                                         StoreFromPtr (ig, t);
7839                                 else if (is_stobj)
7840                                         ig.Emit (OpCodes.Stobj, t);
7841                                 else if (has_type_arg)
7842                                         ig.Emit (op, t);
7843                                 else
7844                                         ig.Emit (op);
7845                         } else {
7846                                 source.Emit (ec);
7847                                 if (leave_copy) {
7848                                         ec.ig.Emit (OpCodes.Dup);
7849                                         temp = new LocalTemporary (this.type);
7850                                         temp.Store (ec);
7851                                 }
7852
7853                                 if (prepared) {
7854                                         StoreFromPtr (ig, t);
7855                                 } else {
7856                                         int arg_count = ea.Arguments.Count;
7857                                         Type [] args = new Type [arg_count + 1];
7858                                         for (int i = 0; i < arg_count; i++) {
7859                                                 //args [i++] = a.Type;
7860                                                 args [i] = TypeManager.int32_type;
7861                                         }
7862                                         args [arg_count] = type;
7863
7864                                         MethodInfo set = CodeGen.Module.Builder.GetArrayMethod (
7865                                                 ea.Expr.Type, "Set",
7866                                                 CallingConventions.HasThis |
7867                                                 CallingConventions.Standard,
7868                                                 TypeManager.void_type, args);
7869
7870                                         ig.Emit (OpCodes.Call, set);
7871                                 }
7872                         }
7873                         
7874                         if (temp != null) {
7875                                 temp.Emit (ec);
7876                                 temp.Release (ec);
7877                         }
7878                 }
7879
7880                 public void AddressOf (EmitContext ec, AddressOp mode)
7881                 {
7882                         int rank = ea.Expr.Type.GetArrayRank ();
7883                         ILGenerator ig = ec.ig;
7884
7885                         LoadArrayAndArguments (ec, false);
7886
7887                         if (rank == 1){
7888                                 ig.Emit (OpCodes.Ldelema, type);
7889                         } else {
7890                                 MethodInfo address = FetchAddressMethod ();
7891                                 ig.Emit (OpCodes.Call, address);
7892                         }
7893                 }
7894
7895                 public void EmitGetLength (EmitContext ec, int dim)
7896                 {
7897                         int rank = ea.Expr.Type.GetArrayRank ();
7898                         ILGenerator ig = ec.ig;
7899
7900                         ea.Expr.Emit (ec);
7901                         if (rank == 1) {
7902                                 ig.Emit (OpCodes.Ldlen);
7903                                 ig.Emit (OpCodes.Conv_I4);
7904                         } else {
7905                                 IntLiteral.EmitInt (ig, dim);
7906                                 ig.Emit (OpCodes.Callvirt, TypeManager.int_getlength_int);
7907                         }
7908                 }
7909         }
7910
7911         /// <summary>
7912         ///   Expressions that represent an indexer call.
7913         /// </summary>
7914         public class IndexerAccess : Expression, IAssignMethod
7915         {
7916                 class IndexerMethodGroupExpr : MethodGroupExpr
7917                 {
7918                         public IndexerMethodGroupExpr (Indexers indexers, Location loc)
7919                                 : base (null, loc)
7920                         {
7921                                 Methods = (MethodBase []) indexers.Methods.ToArray (typeof (MethodBase));
7922                         }
7923
7924                         public override string Name {
7925                                 get {
7926                                         return "this";
7927                                 }
7928                         }
7929
7930                         protected override int GetApplicableParametersCount (MethodBase method, ParameterData parameters)
7931                         {
7932                                 //
7933                                 // Here is the trick, decrease number of arguments by 1 when only
7934                                 // available property method is setter. This makes overload resolution
7935                                 // work correctly for indexers.
7936                                 //
7937                                 
7938                                 if (method.Name [0] == 'g')
7939                                         return parameters.Count;
7940
7941                                 return parameters.Count - 1;
7942                         }
7943                 }
7944
7945                 class Indexers
7946                 {
7947                         // Contains either property getter or setter
7948                         public ArrayList Methods;
7949                         public ArrayList Properties;
7950
7951                         Indexers ()
7952                         {
7953                         }
7954
7955                         void Append (Type caller_type, MemberInfo [] mi)
7956                         {
7957                                 if (mi == null)
7958                                         return;
7959
7960                                 foreach (PropertyInfo property in mi) {
7961                                         MethodInfo accessor = property.GetGetMethod (true);
7962                                         if (accessor == null)
7963                                                 accessor = property.GetSetMethod (true);
7964
7965                                         if (Methods == null) {
7966                                                 Methods = new ArrayList ();
7967                                                 Properties = new ArrayList ();
7968                                         }
7969
7970                                         Methods.Add (accessor);
7971                                         Properties.Add (property);
7972                                 }
7973                         }
7974
7975                         static MemberInfo [] GetIndexersForTypeOrInterface (Type caller_type, Type lookup_type)
7976                         {
7977                                 string p_name = TypeManager.IndexerPropertyName (lookup_type);
7978
7979                                 return TypeManager.MemberLookup (
7980                                         caller_type, caller_type, lookup_type, MemberTypes.Property,
7981                                         BindingFlags.Public | BindingFlags.Instance |
7982                                         BindingFlags.DeclaredOnly, p_name, null);
7983                         }
7984                         
7985                         public static Indexers GetIndexersForType (Type caller_type, Type lookup_type) 
7986                         {
7987                                 Indexers ix = new Indexers ();
7988
7989         #if GMCS_SOURCE
7990                                 if (lookup_type.IsGenericParameter) {
7991                                         GenericConstraints gc = TypeManager.GetTypeParameterConstraints (lookup_type);
7992                                         if (gc == null)
7993                                                 return ix;
7994
7995                                         if (gc.HasClassConstraint)
7996                                                 ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, gc.ClassConstraint));
7997
7998                                         Type[] ifaces = gc.InterfaceConstraints;
7999                                         foreach (Type itype in ifaces)
8000                                                 ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, itype));
8001
8002                                         return ix;
8003                                 }
8004         #endif
8005
8006                                 Type copy = lookup_type;
8007                                 while (copy != TypeManager.object_type && copy != null){
8008                                         ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, copy));
8009                                         copy = copy.BaseType;
8010                                 }
8011
8012                                 if (lookup_type.IsInterface) {
8013                                         Type [] ifaces = TypeManager.GetInterfaces (lookup_type);
8014                                         if (ifaces != null) {
8015                                                 foreach (Type itype in ifaces)
8016                                                         ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, itype));
8017                                         }
8018                                 }
8019
8020                                 return ix;
8021                         }
8022                 }
8023
8024                 enum AccessorType
8025                 {
8026                         Get,
8027                         Set
8028                 }
8029
8030                 //
8031                 // Points to our "data" repository
8032                 //
8033                 MethodInfo get, set;
8034                 bool is_base_indexer;
8035                 bool prepared;
8036                 LocalTemporary temp;
8037                 LocalTemporary prepared_value;
8038                 Expression set_expr;
8039
8040                 protected Type indexer_type;
8041                 protected Type current_type;
8042                 protected Expression instance_expr;
8043                 protected ArrayList arguments;
8044                 
8045                 public IndexerAccess (ElementAccess ea, Location loc)
8046                         : this (ea.Expr, false, loc)
8047                 {
8048                         this.arguments = ea.Arguments;
8049                 }
8050
8051                 protected IndexerAccess (Expression instance_expr, bool is_base_indexer,
8052                                          Location loc)
8053                 {
8054                         this.instance_expr = instance_expr;
8055                         this.is_base_indexer = is_base_indexer;
8056                         this.eclass = ExprClass.Value;
8057                         this.loc = loc;
8058                 }
8059
8060                 static string GetAccessorName (AccessorType at)
8061                 {
8062                         if (at == AccessorType.Set)
8063                                 return "set";
8064
8065                         if (at == AccessorType.Get)
8066                                 return "get";
8067
8068                         throw new NotImplementedException (at.ToString ());
8069                 }
8070
8071                 protected virtual bool CommonResolve (EmitContext ec)
8072                 {
8073                         indexer_type = instance_expr.Type;
8074                         current_type = ec.ContainerType;
8075
8076                         return true;
8077                 }
8078
8079                 public override Expression DoResolve (EmitContext ec)
8080                 {
8081                         return ResolveAccessor (ec, AccessorType.Get);
8082                 }
8083
8084                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
8085                 {
8086                         if (right_side == EmptyExpression.OutAccess) {
8087                                 Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter",
8088                                               GetSignatureForError ());
8089                                 return null;
8090                         }
8091
8092                         // if the indexer returns a value type, and we try to set a field in it
8093                         if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) {
8094                                 Error_CannotModifyIntermediateExpressionValue (ec);
8095                         }
8096
8097                         Expression e = ResolveAccessor (ec, AccessorType.Set);
8098                         if (e == null)
8099                                 return null;
8100
8101                         set_expr = Convert.ImplicitConversion (ec, right_side, type, loc);
8102                         return e;
8103                 }
8104
8105                 Expression ResolveAccessor (EmitContext ec, AccessorType accessorType)
8106                 {
8107                         if (!CommonResolve (ec))
8108                                 return null;
8109
8110                         Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type);
8111                         if (ilist.Methods == null) {
8112                                 Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `{0}'",
8113                                                   TypeManager.CSharpName (indexer_type));
8114                                 return null;
8115                         }
8116
8117                         MethodGroupExpr mg = new IndexerMethodGroupExpr (ilist, loc);
8118                         mg = mg.OverloadResolve (ec, ref arguments, false, loc);
8119                         if (mg == null)
8120                                 return null;
8121
8122                         MethodInfo mi = (MethodInfo) mg;
8123                         PropertyInfo pi = null;
8124                         for (int i = 0; i < ilist.Methods.Count; ++i) {
8125                                 if (ilist.Methods [i] == mi) {
8126                                         pi = (PropertyInfo) ilist.Properties [i];
8127                                         break;
8128                                 }
8129                         }
8130
8131                         type = TypeManager.TypeToCoreType (pi.PropertyType);
8132                         if (type.IsPointer && !ec.InUnsafe)
8133                                 UnsafeError (loc);
8134
8135                         MethodInfo accessor;
8136                         if (accessorType == AccessorType.Get) {
8137                                 accessor = get = pi.GetGetMethod (true);
8138                         } else {
8139                                 accessor = set = pi.GetSetMethod (true);
8140                                 if (accessor == null && pi.GetGetMethod (true) != null) {
8141                                         Report.SymbolRelatedToPreviousError (pi);
8142                                         Report.Error (200, loc, "The read only property or indexer `{0}' cannot be assigned to",
8143                                                 TypeManager.GetFullNameSignature (pi));
8144                                         return null;
8145                                 }
8146                         }
8147
8148                         if (accessor == null) {
8149                                 Report.SymbolRelatedToPreviousError (pi);
8150                                 Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks a `{1}' accessor",
8151                                         TypeManager.GetFullNameSignature (pi), GetAccessorName (accessorType));
8152                                 return null;
8153                         }
8154
8155                         //
8156                         // Only base will allow this invocation to happen.
8157                         //
8158                         if (accessor.IsAbstract && this is BaseIndexerAccess) {
8159                                 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (pi));
8160                         }
8161
8162                         bool must_do_cs1540_check;
8163                         if (!IsAccessorAccessible (ec.ContainerType, accessor, out must_do_cs1540_check)) {
8164                                 if (set == null)
8165                                         set = pi.GetSetMethod (true);
8166                                 else
8167                                         get = pi.GetGetMethod (true);
8168
8169                                 if (set != null && get != null &&
8170                                         (set.Attributes & MethodAttributes.MemberAccessMask) != (get.Attributes & MethodAttributes.MemberAccessMask)) {
8171                                         Report.SymbolRelatedToPreviousError (accessor);
8172                                         Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because a `{1}' accessor is inaccessible",
8173                                                 TypeManager.GetFullNameSignature (pi), GetAccessorName (accessorType));
8174                                 } else {
8175                                         Report.SymbolRelatedToPreviousError (pi);
8176                                         ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (pi));
8177                                 }
8178                         }
8179
8180                         instance_expr.CheckMarshalByRefAccess (ec);
8181                         eclass = ExprClass.IndexerAccess;
8182                         return this;
8183                 }
8184                 
8185                 public void Emit (EmitContext ec, bool leave_copy)
8186                 {
8187                         if (prepared) {
8188                                 prepared_value.Emit (ec);
8189                         } else {
8190                                 Invocation.EmitCall (ec, is_base_indexer, instance_expr, get,
8191                                         arguments, loc, false, false);
8192                         }
8193
8194                         if (leave_copy) {
8195                                 ec.ig.Emit (OpCodes.Dup);
8196                                 temp = new LocalTemporary (Type);
8197                                 temp.Store (ec);
8198                         }
8199                 }
8200                 
8201                 //
8202                 // source is ignored, because we already have a copy of it from the
8203                 // LValue resolution and we have already constructed a pre-cached
8204                 // version of the arguments (ea.set_arguments);
8205                 //
8206                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
8207                 {
8208                         prepared = prepare_for_load;
8209                         Expression value = set_expr;
8210
8211                         if (prepared) {
8212                                 Invocation.EmitCall (ec, is_base_indexer, instance_expr, get,
8213                                         arguments, loc, true, false);
8214
8215                                 prepared_value = new LocalTemporary (type);
8216                                 prepared_value.Store (ec);
8217                                 source.Emit (ec);
8218                                 prepared_value.Release (ec);
8219
8220                                 if (leave_copy) {
8221                                         ec.ig.Emit (OpCodes.Dup);
8222                                         temp = new LocalTemporary (Type);
8223                                         temp.Store (ec);
8224                                 }
8225                         } else if (leave_copy) {
8226                                 temp = new LocalTemporary (Type);
8227                                 source.Emit (ec);
8228                                 temp.Store (ec);
8229                                 value = temp;
8230                         }
8231                         
8232                         arguments.Add (new Argument (value, Argument.AType.Expression));
8233                         Invocation.EmitCall (ec, is_base_indexer, instance_expr, set, arguments, loc, false, prepared);
8234                         
8235                         if (temp != null) {
8236                                 temp.Emit (ec);
8237                                 temp.Release (ec);
8238                         }
8239                 }
8240                 
8241                 public override void Emit (EmitContext ec)
8242                 {
8243                         Emit (ec, false);
8244                 }
8245
8246                 public override string GetSignatureForError ()
8247                 {
8248                         return TypeManager.CSharpSignature (get != null ? get : set, false);
8249                 }
8250
8251                 protected override void CloneTo (CloneContext clonectx, Expression t)
8252                 {
8253                         IndexerAccess target = (IndexerAccess) t;
8254
8255                         if (arguments != null){
8256                                 target.arguments = new ArrayList ();
8257                                 foreach (Argument a in arguments)
8258                                         target.arguments.Add (a.Clone (clonectx));
8259                         }
8260                         if (instance_expr != null)
8261                                 target.instance_expr = instance_expr.Clone (clonectx);
8262                 }
8263         }
8264
8265         /// <summary>
8266         ///   The base operator for method names
8267         /// </summary>
8268         public class BaseAccess : Expression {
8269                 public readonly string Identifier;
8270                 TypeArguments args;
8271
8272                 public BaseAccess (string member, Location l)
8273                 {
8274                         this.Identifier = member;
8275                         loc = l;
8276                 }
8277
8278                 public BaseAccess (string member, TypeArguments args, Location l)
8279                         : this (member, l)
8280                 {
8281                         this.args = args;
8282                 }
8283
8284                 public override Expression DoResolve (EmitContext ec)
8285                 {
8286                         Expression c = CommonResolve (ec);
8287
8288                         if (c == null)
8289                                 return null;
8290
8291                         //
8292                         // MethodGroups use this opportunity to flag an error on lacking ()
8293                         //
8294                         if (!(c is MethodGroupExpr))
8295                                 return c.Resolve (ec);
8296                         return c;
8297                 }
8298
8299                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
8300                 {
8301                         Expression c = CommonResolve (ec);
8302
8303                         if (c == null)
8304                                 return null;
8305
8306                         //
8307                         // MethodGroups use this opportunity to flag an error on lacking ()
8308                         //
8309                         if (! (c is MethodGroupExpr))
8310                                 return c.DoResolveLValue (ec, right_side);
8311
8312                         return c;
8313                 }
8314
8315                 Expression CommonResolve (EmitContext ec)
8316                 {
8317                         Expression member_lookup;
8318                         Type current_type = ec.ContainerType;
8319                         Type base_type = current_type.BaseType;
8320
8321                         if (ec.IsStatic){
8322                                 Error (1511, "Keyword `base' is not available in a static method");
8323                                 return null;
8324                         }
8325
8326                         if (ec.IsInFieldInitializer){
8327                                 Error (1512, "Keyword `base' is not available in the current context");
8328                                 return null;
8329                         }
8330                         
8331                         member_lookup = MemberLookup (ec.ContainerType, null, base_type, Identifier,
8332                                                       AllMemberTypes, AllBindingFlags, loc);
8333                         if (member_lookup == null) {
8334                                 Error_MemberLookupFailed (ec.ContainerType, base_type, base_type, Identifier,
8335                                         null, AllMemberTypes, AllBindingFlags);
8336                                 return null;
8337                         }
8338
8339                         Expression left;
8340                         
8341                         if (ec.IsStatic)
8342                                 left = new TypeExpression (base_type, loc);
8343                         else
8344                                 left = ec.GetThis (loc);
8345
8346                         MemberExpr me = (MemberExpr) member_lookup;
8347                         me = me.ResolveMemberAccess (ec, left, loc, null);
8348                         if (me == null)
8349                                 return null;
8350
8351                         me.IsBase = true;
8352                         if (args != null) {
8353                                 args.Resolve (ec);
8354                                 me.SetTypeArguments (args);
8355                         }
8356
8357                         return me;
8358                 }
8359
8360                 public override void Emit (EmitContext ec)
8361                 {
8362                         throw new Exception ("Should never be called"); 
8363                 }
8364
8365                 protected override void CloneTo (CloneContext clonectx, Expression t)
8366                 {
8367                         BaseAccess target = (BaseAccess) t;
8368
8369                         if (args != null)
8370                                 target.args = args.Clone ();
8371                 }
8372         }
8373
8374         /// <summary>
8375         ///   The base indexer operator
8376         /// </summary>
8377         public class BaseIndexerAccess : IndexerAccess {
8378                 public BaseIndexerAccess (ArrayList args, Location loc)
8379                         : base (null, true, loc)
8380                 {
8381                         arguments = new ArrayList ();
8382                         foreach (Expression tmp in args)
8383                                 arguments.Add (new Argument (tmp, Argument.AType.Expression));
8384                 }
8385
8386                 protected override bool CommonResolve (EmitContext ec)
8387                 {
8388                         instance_expr = ec.GetThis (loc);
8389
8390                         current_type = ec.ContainerType.BaseType;
8391                         indexer_type = current_type;
8392
8393                         foreach (Argument a in arguments){
8394                                 if (!a.Resolve (ec, loc))
8395                                         return false;
8396                         }
8397
8398                         return true;
8399                 }
8400         }
8401         
8402         /// <summary>
8403         ///   This class exists solely to pass the Type around and to be a dummy
8404         ///   that can be passed to the conversion functions (this is used by
8405         ///   foreach implementation to typecast the object return value from
8406         ///   get_Current into the proper type.  All code has been generated and
8407         ///   we only care about the side effect conversions to be performed
8408         ///
8409         ///   This is also now used as a placeholder where a no-action expression
8410         ///   is needed (the `New' class).
8411         /// </summary>
8412         public class EmptyExpression : Expression {
8413                 public static readonly EmptyExpression Null = new EmptyExpression ();
8414
8415                 public static readonly EmptyExpression OutAccess = new EmptyExpression ();
8416                 public static readonly EmptyExpression LValueMemberAccess = new EmptyExpression ();
8417                 public static readonly EmptyExpression LValueMemberOutAccess = new EmptyExpression ();
8418
8419                 static EmptyExpression temp = new EmptyExpression ();
8420                 public static EmptyExpression Grab ()
8421                 {
8422                         EmptyExpression retval = temp == null ? new EmptyExpression () : temp;
8423                         temp = null;
8424                         return retval;
8425                 }
8426
8427                 public static void Release (EmptyExpression e)
8428                 {
8429                         temp = e;
8430                 }
8431
8432                 // TODO: should be protected
8433                 public EmptyExpression ()
8434                 {
8435                         type = TypeManager.object_type;
8436                         eclass = ExprClass.Value;
8437                         loc = Location.Null;
8438                 }
8439
8440                 public EmptyExpression (Type t)
8441                 {
8442                         type = t;
8443                         eclass = ExprClass.Value;
8444                         loc = Location.Null;
8445                 }
8446                 
8447                 public override Expression DoResolve (EmitContext ec)
8448                 {
8449                         return this;
8450                 }
8451
8452                 public override void Emit (EmitContext ec)
8453                 {
8454                         // nothing, as we only exist to not do anything.
8455                 }
8456
8457                 //
8458                 // This is just because we might want to reuse this bad boy
8459                 // instead of creating gazillions of EmptyExpressions.
8460                 // (CanImplicitConversion uses it)
8461                 //
8462                 public void SetType (Type t)
8463                 {
8464                         type = t;
8465                 }
8466         }
8467         
8468         //
8469         // Empty statement expression
8470         //
8471         public sealed class EmptyExpressionStatement : ExpressionStatement
8472         {
8473                 public static readonly EmptyExpressionStatement Instance = new EmptyExpressionStatement ();
8474
8475                 private EmptyExpressionStatement ()
8476                 {
8477                         type = TypeManager.object_type;
8478                         eclass = ExprClass.Value;
8479                         loc = Location.Null;
8480                 }
8481
8482                 public override void EmitStatement (EmitContext ec)
8483                 {
8484                         // Do nothing
8485                 }
8486
8487                 public override Expression DoResolve (EmitContext ec)
8488                 {
8489                         return this;
8490                 }
8491
8492                 public override void Emit (EmitContext ec)
8493                 {
8494                         // Do nothing
8495                 }
8496         }       
8497
8498         public class UserCast : Expression {
8499                 MethodInfo method;
8500                 Expression source;
8501                 
8502                 public UserCast (MethodInfo method, Expression source, Location l)
8503                 {
8504                         this.method = method;
8505                         this.source = source;
8506                         type = TypeManager.TypeToCoreType (method.ReturnType);
8507                         eclass = ExprClass.Value;
8508                         loc = l;
8509                 }
8510
8511                 public Expression Source {
8512                         get {
8513                                 return source;
8514                         }
8515                 }
8516
8517                 public override Expression CreateExpressionTree (EmitContext ec)
8518                 {
8519                         ArrayList args = new ArrayList (2);
8520                         args.Add (new Argument (source.CreateExpressionTree (ec)));
8521                         args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
8522                         args.Add (new Argument (new Cast (new TypeExpression (typeof (MethodInfo), loc),
8523                                 new TypeOfMethod (method, loc))));
8524                         return CreateExpressionFactoryCall ("Convert", args);
8525                 }
8526                         
8527                 public override Expression DoResolve (EmitContext ec)
8528                 {
8529                         //
8530                         // We are born fully resolved
8531                         //
8532                         return this;
8533                 }
8534
8535                 public override void Emit (EmitContext ec)
8536                 {
8537                         source.Emit (ec);
8538                         ec.ig.Emit (OpCodes.Call, method);
8539                 }
8540         }
8541
8542         // <summary>
8543         //   This class is used to "construct" the type during a typecast
8544         //   operation.  Since the Type.GetType class in .NET can parse
8545         //   the type specification, we just use this to construct the type
8546         //   one bit at a time.
8547         // </summary>
8548         public class ComposedCast : TypeExpr {
8549                 Expression left;
8550                 string dim;
8551                 
8552                 public ComposedCast (Expression left, string dim)
8553                         : this (left, dim, left.Location)
8554                 {
8555                 }
8556
8557                 public ComposedCast (Expression left, string dim, Location l)
8558                 {
8559                         this.left = left;
8560                         this.dim = dim;
8561                         loc = l;
8562                 }
8563
8564                 public Expression RemoveNullable ()
8565                 {
8566                         if (dim.EndsWith ("?")) {
8567                                 dim = dim.Substring (0, dim.Length - 1);
8568                                 if (dim.Length == 0)
8569                                         return left;
8570                         }
8571
8572                         return this;
8573                 }
8574
8575                 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
8576                 {
8577                         TypeExpr lexpr = left.ResolveAsTypeTerminal (ec, false);
8578                         if (lexpr == null)
8579                                 return null;
8580
8581                         Type ltype = lexpr.Type;
8582                         if ((ltype == TypeManager.void_type) && (dim != "*")) {
8583                                 Error_VoidInvalidInTheContext (loc);
8584                                 return null;
8585                         }
8586
8587 #if GMCS_SOURCE
8588                         if ((dim.Length > 0) && (dim [0] == '?')) {
8589                                 TypeExpr nullable = new Nullable.NullableType (left, loc);
8590                                 if (dim.Length > 1)
8591                                         nullable = new ComposedCast (nullable, dim.Substring (1), loc);
8592                                 return nullable.ResolveAsTypeTerminal (ec, false);
8593                         }
8594 #endif
8595
8596                         if (dim == "*" && !TypeManager.VerifyUnManaged (ltype, loc))
8597                                 return null;
8598
8599                         if (dim != "" && dim [0] == '[' &&
8600                             (ltype == TypeManager.arg_iterator_type || ltype == TypeManager.typed_reference_type)) {
8601                                 Report.Error (611, loc, "Array elements cannot be of type `{0}'", TypeManager.CSharpName (ltype));
8602                                 return null;
8603                         }
8604
8605                         if (dim != "")
8606                                 type = TypeManager.GetConstructedType (ltype, dim);
8607                         else
8608                                 type = ltype;
8609
8610                         if (type == null)
8611                                 throw new InternalErrorException ("Couldn't create computed type " + ltype + dim);
8612
8613                         if (type.IsPointer && !ec.IsInUnsafeScope){
8614                                 UnsafeError (loc);
8615                                 return null;
8616                         }
8617
8618                         eclass = ExprClass.Type;
8619                         return this;
8620                 }
8621
8622                 public override string Name {
8623                         get { return left + dim; }
8624                 }
8625
8626                 public override string FullName {
8627                         get { return type.FullName; }
8628                 }
8629
8630                 public override string GetSignatureForError ()
8631                 {
8632                         return left.GetSignatureForError () + dim;
8633                 }
8634
8635                 protected override void CloneTo (CloneContext clonectx, Expression t)
8636                 {
8637                         ComposedCast target = (ComposedCast) t;
8638
8639                         target.left = left.Clone (clonectx);
8640                 }
8641         }
8642
8643         public class FixedBufferPtr : Expression {
8644                 Expression array;
8645
8646                 public FixedBufferPtr (Expression array, Type array_type, Location l)
8647                 {
8648                         this.array = array;
8649                         this.loc = l;
8650
8651                         type = TypeManager.GetPointerType (array_type);
8652                         eclass = ExprClass.Value;
8653                 }
8654
8655                 public override void Emit(EmitContext ec)
8656                 {
8657                         array.Emit (ec);
8658                 }
8659
8660                 public override Expression DoResolve (EmitContext ec)
8661                 {
8662                         //
8663                         // We are born fully resolved
8664                         //
8665                         return this;
8666                 }
8667         }
8668
8669
8670         //
8671         // This class is used to represent the address of an array, used
8672         // only by the Fixed statement, this generates "&a [0]" construct
8673         // for fixed (char *pa = a)
8674         //
8675         public class ArrayPtr : FixedBufferPtr {
8676                 Type array_type;
8677                 
8678                 public ArrayPtr (Expression array, Type array_type, Location l):
8679                         base (array, array_type, l)
8680                 {
8681                         this.array_type = array_type;
8682                 }
8683
8684                 public override void Emit (EmitContext ec)
8685                 {
8686                         base.Emit (ec);
8687                         
8688                         ILGenerator ig = ec.ig;
8689                         IntLiteral.EmitInt (ig, 0);
8690                         ig.Emit (OpCodes.Ldelema, array_type);
8691                 }
8692         }
8693
8694         //
8695         // Encapsulates a conversion rules required for array indexes
8696         //
8697         public class ArrayIndexCast : Expression
8698         {
8699                 Expression expr;
8700
8701                 public ArrayIndexCast (Expression expr)
8702                 {
8703                         this.expr = expr;
8704                         this.loc = expr.Location;
8705                 }
8706
8707                 public override Expression CreateExpressionTree (EmitContext ec)
8708                 {
8709                         ArrayList args = new ArrayList (2);
8710                         args.Add (new Argument (expr.CreateExpressionTree (ec)));
8711                         args.Add (new Argument (new TypeOf (new TypeExpression (TypeManager.int32_type, loc), loc)));
8712                         return CreateExpressionFactoryCall ("ConvertChecked", args);
8713                 }
8714
8715                 public override Expression DoResolve (EmitContext ec)
8716                 {
8717                         type = expr.Type;
8718                         eclass = expr.eclass;
8719                         return this;
8720                 }
8721
8722                 public override void Emit (EmitContext ec)
8723                 {
8724                         expr.Emit (ec);
8725                                 
8726                         if (type == TypeManager.int32_type)
8727                                 return;
8728
8729                         if (type == TypeManager.uint32_type)
8730                                 ec.ig.Emit (OpCodes.Conv_U);
8731                         else if (type == TypeManager.int64_type)
8732                                 ec.ig.Emit (OpCodes.Conv_Ovf_I);
8733                         else if (type == TypeManager.uint64_type)
8734                                 ec.ig.Emit (OpCodes.Conv_Ovf_I_Un);
8735                         else
8736                                 throw new InternalErrorException ("Cannot emit cast to unknown array element type", type);
8737                 }
8738         }
8739
8740         //
8741         // Used by the fixed statement
8742         //
8743         public class StringPtr : Expression {
8744                 LocalBuilder b;
8745                 
8746                 public StringPtr (LocalBuilder b, Location l)
8747                 {
8748                         this.b = b;
8749                         eclass = ExprClass.Value;
8750                         type = TypeManager.char_ptr_type;
8751                         loc = l;
8752                 }
8753
8754                 public override Expression DoResolve (EmitContext ec)
8755                 {
8756                         // This should never be invoked, we are born in fully
8757                         // initialized state.
8758
8759                         return this;
8760                 }
8761
8762                 public override void Emit (EmitContext ec)
8763                 {
8764                         if (TypeManager.int_get_offset_to_string_data == null) {
8765                                 // TODO: Move to resolve !!
8766                                 TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedMethod (
8767                                         TypeManager.runtime_helpers_type, "get_OffsetToStringData", loc, Type.EmptyTypes);
8768                         }
8769
8770                         ILGenerator ig = ec.ig;
8771
8772                         ig.Emit (OpCodes.Ldloc, b);
8773                         ig.Emit (OpCodes.Conv_I);
8774                         ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
8775                         ig.Emit (OpCodes.Add);
8776                 }
8777         }
8778         
8779         //
8780         // Implements the `stackalloc' keyword
8781         //
8782         public class StackAlloc : Expression {
8783                 Type otype;
8784                 Expression t;
8785                 Expression count;
8786                 
8787                 public StackAlloc (Expression type, Expression count, Location l)
8788                 {
8789                         t = type;
8790                         this.count = count;
8791                         loc = l;
8792                 }
8793
8794                 public override Expression DoResolve (EmitContext ec)
8795                 {
8796                         count = count.Resolve (ec);
8797                         if (count == null)
8798                                 return null;
8799                         
8800                         if (count.Type != TypeManager.int32_type){
8801                                 count = Convert.ImplicitConversionRequired (ec, count, TypeManager.int32_type, loc);
8802                                 if (count == null)
8803                                         return null;
8804                         }
8805
8806                         Constant c = count as Constant;
8807                         if (c != null && c.IsNegative) {
8808                                 Report.Error (247, loc, "Cannot use a negative size with stackalloc");
8809                                 return null;
8810                         }
8811
8812                         if (ec.InCatch || ec.InFinally) {
8813                                 Error (255, "Cannot use stackalloc in finally or catch");
8814                                 return null;
8815                         }
8816
8817                         TypeExpr texpr = t.ResolveAsTypeTerminal (ec, false);
8818                         if (texpr == null)
8819                                 return null;
8820
8821                         otype = texpr.Type;
8822
8823                         if (!TypeManager.VerifyUnManaged (otype, loc))
8824                                 return null;
8825
8826                         type = TypeManager.GetPointerType (otype);
8827                         eclass = ExprClass.Value;
8828
8829                         return this;
8830                 }
8831
8832                 public override void Emit (EmitContext ec)
8833                 {
8834                         int size = GetTypeSize (otype);
8835                         ILGenerator ig = ec.ig;
8836                                 
8837                         if (size == 0)
8838                                 ig.Emit (OpCodes.Sizeof, otype);
8839                         else
8840                                 IntConstant.EmitInt (ig, size);
8841                         count.Emit (ec);
8842                         ig.Emit (OpCodes.Mul);
8843                         ig.Emit (OpCodes.Localloc);
8844                 }
8845
8846                 protected override void CloneTo (CloneContext clonectx, Expression t)
8847                 {
8848                         StackAlloc target = (StackAlloc) t;
8849                         target.count = count.Clone (clonectx);
8850                         target.t = t.Clone (clonectx);
8851                 }
8852         }
8853
8854         //
8855         // An object initializer expression
8856         //
8857         public class ElementInitializer : Expression
8858         {
8859                 Expression initializer;
8860                 public readonly string Name;
8861
8862                 public ElementInitializer (string name, Expression initializer, Location loc)
8863                 {
8864                         this.Name = name;
8865                         this.initializer = initializer;
8866                         this.loc = loc;
8867                 }
8868
8869                 protected override void CloneTo (CloneContext clonectx, Expression t)
8870                 {
8871                         if (initializer == null)
8872                                 return;
8873
8874                         ElementInitializer target = (ElementInitializer) t;
8875                         target.initializer = initializer.Clone (clonectx);
8876                 }
8877
8878                 public override Expression DoResolve (EmitContext ec)
8879                 {
8880                         if (initializer == null)
8881                                 return EmptyExpressionStatement.Instance;
8882                         
8883                         MemberExpr element_member = MemberLookupFinal (ec, ec.CurrentInitializerVariable.Type, ec.CurrentInitializerVariable.Type,
8884                                 Name, MemberTypes.Field | MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance, loc) as MemberExpr;
8885
8886                         if (element_member == null)
8887                                 return null;
8888
8889                         element_member.InstanceExpression = ec.CurrentInitializerVariable;
8890
8891                         if (initializer is CollectionOrObjectInitializers) {
8892                                 Expression previous = ec.CurrentInitializerVariable;
8893                                 ec.CurrentInitializerVariable = element_member;
8894                                 initializer = initializer.Resolve (ec);
8895                                 ec.CurrentInitializerVariable = previous;
8896                                 return initializer;
8897                         }
8898
8899                         Assign a = new Assign (element_member, initializer, loc);
8900                         if (a.Resolve (ec) == null)
8901                                 return null;
8902
8903                         //
8904                         // Ignore field initializers with default value
8905                         //
8906                         Constant c = a.Source as Constant;
8907                         if (c != null && c.IsDefaultInitializer (a.Type) && a.Target.eclass == ExprClass.Variable)
8908                                 return EmptyExpressionStatement.Instance;
8909
8910                         return a;
8911                 }
8912
8913                 protected override Expression Error_MemberLookupFailed (MemberInfo[] members)
8914                 {
8915                         MemberInfo member = members [0];
8916                         if (member.MemberType != MemberTypes.Property && member.MemberType != MemberTypes.Field)
8917                                 Report.Error (1913, loc, "Member `{0}' cannot be initialized. An object " +
8918                                         "initializer may only be used for fields, or properties", TypeManager.GetFullNameSignature (member));
8919                         else
8920                                 Report.Error (1914, loc, " Static field or property `{0}' cannot be assigned in an object initializer",
8921                                         TypeManager.GetFullNameSignature (member));
8922
8923                         return null;
8924                 }
8925
8926                 public override void Emit (EmitContext ec)
8927                 {
8928                         throw new NotSupportedException ("Should not be reached");
8929                 }
8930         }
8931         
8932         //
8933         // A collection initializer expression
8934         //
8935         public class CollectionElementInitializer : Invocation
8936         {
8937                 public class ElementInitializerArgument : Argument
8938                 {
8939                         public ElementInitializerArgument (Expression e)
8940                                 : base (e)
8941                         {
8942                         }
8943                 }
8944
8945                 public CollectionElementInitializer (Expression argument)
8946                         : base (null, new ArrayList (1), true)
8947                 {
8948                         Arguments.Add (argument);
8949                         this.loc = argument.Location;
8950                 }
8951
8952                 public CollectionElementInitializer (ArrayList arguments, Location loc)
8953                         : base (null, arguments, true)
8954                 {
8955                         this.loc = loc;
8956                 }
8957
8958                 public override Expression CreateExpressionTree (EmitContext ec)
8959                 {
8960                         ArrayList args = new ArrayList (2);
8961                         args.Add (new Argument (mg.CreateExpressionTree (ec)));
8962
8963                         ArrayList expr_initializers = new ArrayList (Arguments.Count);
8964                         foreach (Argument a in Arguments)
8965                                 expr_initializers.Add (a.Expr.CreateExpressionTree (ec));
8966
8967                         args.Add (new Argument (new ArrayCreation (
8968                                 CreateExpressionTypeExpression (loc), "[]", expr_initializers, loc)));
8969                         return CreateExpressionFactoryCall ("ElementInit", args);
8970                 }
8971
8972                 public override Expression DoResolve (EmitContext ec)
8973                 {
8974                         if (eclass != ExprClass.Invalid)
8975                                 return this;
8976
8977                         // TODO: We could call a constructor which takes element count argument,
8978                         // for known types like List<T>, Dictionary<T, U>
8979                         
8980                         for (int i = 0; i < Arguments.Count; ++i) {
8981                                 Expression expr = ((Expression) Arguments [i]).Resolve (ec);
8982                                 if (expr == null)
8983                                         return null;
8984
8985                                 Arguments [i] = new ElementInitializerArgument (expr);
8986                         }
8987
8988                         base.expr = new MemberAccess (ec.CurrentInitializerVariable, "Add", loc);
8989
8990                         return base.DoResolve (ec);
8991                 }
8992         }
8993         
8994         //
8995         // A block of object or collection initializers
8996         //
8997         public class CollectionOrObjectInitializers : ExpressionStatement
8998         {
8999                 ArrayList initializers;
9000                 
9001                 public static readonly CollectionOrObjectInitializers Empty = 
9002                         new CollectionOrObjectInitializers (new ArrayList (0), Location.Null);
9003
9004                 public CollectionOrObjectInitializers (ArrayList initializers, Location loc)
9005                 {
9006                         this.initializers = initializers;
9007                         this.loc = loc;
9008                 }
9009                 
9010                 public bool IsEmpty {
9011                         get {
9012                                 return initializers.Count == 0;
9013                         }
9014                 }
9015
9016                 protected override void CloneTo (CloneContext clonectx, Expression target)
9017                 {
9018                         CollectionOrObjectInitializers t = (CollectionOrObjectInitializers) target;
9019
9020                         t.initializers = new ArrayList (initializers.Count);
9021                         foreach (Expression e in initializers)
9022                                 t.initializers.Add (e.Clone (clonectx));
9023                 }
9024
9025                 public override Expression CreateExpressionTree (EmitContext ec)
9026                 {
9027                         ArrayList expr_initializers = new ArrayList (initializers.Count);
9028                         foreach (Expression e in initializers) {
9029                                 Expression expr = e.CreateExpressionTree (ec);
9030                                 if (expr != null)
9031                                         expr_initializers.Add (expr);
9032                         }
9033
9034                         return new ImplicitlyTypedArrayCreation ("[]", expr_initializers, loc);
9035                 }
9036                 
9037                 public override Expression DoResolve (EmitContext ec)
9038                 {
9039                         if (eclass != ExprClass.Invalid)
9040                                 return this;
9041
9042                         bool is_elements_initialization = false;
9043                         ArrayList element_names = null;
9044                         for (int i = 0; i < initializers.Count; ++i) {
9045                                 Expression initializer = (Expression) initializers [i];
9046                                 ElementInitializer element_initializer = initializer as ElementInitializer;
9047
9048                                 if (i == 0) {
9049                                         if (element_initializer != null) {
9050                                                 is_elements_initialization = true;
9051                                                 element_names = new ArrayList (initializers.Count);
9052                                                 element_names.Add (element_initializer.Name);
9053                                         } else {
9054                                                 if (!TypeManager.ImplementsInterface (ec.CurrentInitializerVariable.Type,
9055                                                         TypeManager.ienumerable_type)) {
9056                                                         Report.Error (1922, loc, "A field or property `{0}' cannot be initialized with a collection " +
9057                                                                 "object initializer because type `{1}' does not implement `{2}' interface",
9058                                                                 ec.CurrentInitializerVariable.GetSignatureForError (),
9059                                                                 TypeManager.CSharpName (ec.CurrentInitializerVariable.Type),
9060                                                                 TypeManager.CSharpName (TypeManager.ienumerable_type));
9061                                                         return null;
9062                                                 }
9063                                         }
9064                                 } else {
9065                                         if (is_elements_initialization == (element_initializer == null)) {
9066                                                 Report.Error (747, initializer.Location, "Inconsistent `{0}' member declaration",
9067                                                         is_elements_initialization ? "object initializer" : "collection initializer");
9068                                                 continue;
9069                                         }
9070                                         
9071                                         if (is_elements_initialization) {
9072                                                 if (element_names.Contains (element_initializer.Name)) {
9073                                                         Report.Error (1912, element_initializer.Location,
9074                                                                 "An object initializer includes more than one member `{0}' initialization",
9075                                                                 element_initializer.Name);
9076                                                 } else {
9077                                                         element_names.Add (element_initializer.Name);
9078                                                 }
9079                                         }
9080                                 }
9081
9082                                 Expression e = initializer.Resolve (ec);
9083                                 if (e == EmptyExpressionStatement.Instance)
9084                                         initializers.RemoveAt (i--);
9085                                 else
9086                                         initializers [i] = e;
9087                         }
9088
9089                         type = typeof (CollectionOrObjectInitializers);
9090                         eclass = ExprClass.Variable;
9091                         return this;
9092                 }
9093
9094                 public override void Emit (EmitContext ec)
9095                 {
9096                         EmitStatement (ec);
9097                 }
9098
9099                 public override void EmitStatement (EmitContext ec)
9100                 {
9101                         foreach (ExpressionStatement e in initializers)
9102                                 e.EmitStatement (ec);
9103                 }
9104         }
9105         
9106         //
9107         // New expression with element/object initializers
9108         //
9109         public class NewInitialize : New
9110         {
9111                 //
9112                 // This class serves as a proxy for variable initializer target instances.
9113                 // A real variable is assigned later when we resolve left side of an
9114                 // assignment
9115                 //
9116                 sealed class InitializerTargetExpression : Expression, IMemoryLocation
9117                 {
9118                         NewInitialize new_instance;
9119
9120                         public InitializerTargetExpression (NewInitialize newInstance)
9121                         {
9122                                 this.type = newInstance.type;
9123                                 this.loc = newInstance.loc;
9124                                 this.eclass = newInstance.eclass;
9125                                 this.new_instance = newInstance;
9126                         }
9127
9128                         public override Expression DoResolve (EmitContext ec)
9129                         {
9130                                 return this;
9131                         }
9132
9133                         public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
9134                         {
9135                                 return this;
9136                         }
9137
9138                         public override void Emit (EmitContext ec)
9139                         {
9140                                 new_instance.value_target.Emit (ec);
9141                         }
9142
9143                         #region IMemoryLocation Members
9144
9145                         public void AddressOf (EmitContext ec, AddressOp mode)
9146                         {
9147                                 ((IMemoryLocation)new_instance.value_target).AddressOf (ec, mode);
9148                         }
9149
9150                         #endregion
9151                 }
9152
9153                 CollectionOrObjectInitializers initializers;
9154
9155                 public NewInitialize (Expression requested_type, ArrayList arguments, CollectionOrObjectInitializers initializers, Location l)
9156                         : base (requested_type, arguments, l)
9157                 {
9158                         this.initializers = initializers;
9159                 }
9160
9161                 protected override void CloneTo (CloneContext clonectx, Expression t)
9162                 {
9163                         base.CloneTo (clonectx, t);
9164
9165                         NewInitialize target = (NewInitialize) t;
9166                         target.initializers = (CollectionOrObjectInitializers) initializers.Clone (clonectx);
9167                 }
9168
9169                 public override Expression CreateExpressionTree (EmitContext ec)
9170                 {
9171                         ArrayList args = new ArrayList (2);
9172                         args.Add (new Argument (base.CreateExpressionTree (ec)));
9173                         args.Add (new Argument (initializers.CreateExpressionTree (ec)));
9174
9175                         return CreateExpressionFactoryCall ("ListInit", args);
9176                 }
9177
9178                 public override Expression DoResolve (EmitContext ec)
9179                 {
9180                         if (eclass != ExprClass.Invalid)
9181                                 return this;
9182                         
9183                         Expression e = base.DoResolve (ec);
9184                         if (type == null)
9185                                 return null;
9186
9187                         // Empty initializer can be optimized to simple new
9188                         if (initializers.IsEmpty)
9189                                 return e;
9190
9191                         Expression previous = ec.CurrentInitializerVariable;
9192                         ec.CurrentInitializerVariable = new InitializerTargetExpression (this);
9193                         initializers.Resolve (ec);
9194                         ec.CurrentInitializerVariable = previous;
9195                         return this;
9196                 }
9197
9198                 public override void Emit (EmitContext ec)
9199                 {
9200                         base.Emit (ec);
9201
9202                         //
9203                         // If target is a value, let's use it
9204                         //
9205                         VariableReference variable = value_target as VariableReference;
9206                         if (variable != null) {
9207                                 if (variable.IsRef)
9208                                         StoreFromPtr (ec.ig, type);
9209                                 else
9210                                         variable.Variable.EmitAssign (ec);
9211                         } else {
9212                                 if (value_target == null || value_target_set)
9213                                         value_target = new LocalTemporary (type);
9214
9215                                 ((LocalTemporary) value_target).Store (ec);
9216                         }
9217
9218                         initializers.Emit (ec);
9219
9220                         if (variable == null)
9221                                 value_target.Emit (ec);
9222                 }
9223
9224                 public override void EmitStatement (EmitContext ec)
9225                 {
9226                         if (initializers.IsEmpty) {
9227                                 base.EmitStatement (ec);
9228                                 return;
9229                         }
9230
9231                         base.Emit (ec);
9232
9233                         if (value_target == null) {
9234                                 LocalTemporary variable = new LocalTemporary (type);
9235                                 variable.Store (ec);
9236                                 value_target = variable;
9237                         }
9238
9239                         initializers.EmitStatement (ec);
9240                 }
9241
9242                 public override bool HasInitializer {
9243                         get {
9244                                 return !initializers.IsEmpty;
9245                         }
9246                 }
9247         }
9248
9249         public class AnonymousTypeDeclaration : Expression
9250         {
9251                 ArrayList parameters;
9252                 readonly TypeContainer parent;
9253                 static readonly ArrayList EmptyParameters = new ArrayList (0);
9254
9255                 public AnonymousTypeDeclaration (ArrayList parameters, TypeContainer parent, Location loc)
9256                 {
9257                         this.parameters = parameters;
9258                         this.parent = parent;
9259                         this.loc = loc;
9260                 }
9261
9262                 protected override void CloneTo (CloneContext clonectx, Expression target)
9263                 {
9264                         if (parameters == null)
9265                                 return;
9266
9267                         AnonymousTypeDeclaration t = (AnonymousTypeDeclaration) target;
9268                         t.parameters = new ArrayList (parameters.Count);
9269                         foreach (AnonymousTypeParameter atp in parameters)
9270                                 t.parameters.Add (atp.Clone (clonectx));
9271                 }
9272
9273                 AnonymousTypeClass CreateAnonymousType (ArrayList parameters)
9274                 {
9275                         AnonymousTypeClass type = RootContext.ToplevelTypes.GetAnonymousType (parameters);
9276                         if (type != null)
9277                                 return type;
9278
9279                         type = AnonymousTypeClass.Create (parent, parameters, loc);
9280                         if (type == null)
9281                                 return null;
9282
9283                         type.DefineType ();
9284                         type.DefineMembers ();
9285                         type.Define ();
9286                         type.EmitType ();
9287
9288                         RootContext.ToplevelTypes.AddAnonymousType (type);
9289                         return type;
9290                 }
9291
9292                 public override Expression DoResolve (EmitContext ec)
9293                 {
9294                         AnonymousTypeClass anonymous_type;
9295
9296                         if (parameters == null) {
9297                                 anonymous_type = CreateAnonymousType (EmptyParameters);
9298                                 return new New (new TypeExpression (anonymous_type.TypeBuilder, loc),
9299                                         null, loc).Resolve (ec);
9300                         }
9301
9302                         bool error = false;
9303                         ArrayList arguments = new ArrayList (parameters.Count);
9304                         TypeExpression [] t_args = new TypeExpression [parameters.Count];
9305                         for (int i = 0; i < parameters.Count; ++i) {
9306                                 Expression e = ((AnonymousTypeParameter) parameters [i]).Resolve (ec);
9307                                 if (e == null) {
9308                                         error = true;
9309                                         continue;
9310                                 }
9311
9312                                 arguments.Add (new Argument (e));
9313                                 t_args [i] = new TypeExpression (e.Type, e.Location);
9314                         }
9315
9316                         if (error)
9317                                 return null;
9318
9319                         anonymous_type = CreateAnonymousType (parameters);
9320                         if (anonymous_type == null)
9321                                 return null;
9322
9323                         ConstructedType te = new ConstructedType (anonymous_type.TypeBuilder,
9324                                 new TypeArguments (loc, t_args), loc);
9325
9326                         return new New (te, arguments, loc).Resolve (ec);
9327                 }
9328
9329                 public override void Emit (EmitContext ec)
9330                 {
9331                         throw new InternalErrorException ("Should not be reached");
9332                 }
9333         }
9334
9335         public class AnonymousTypeParameter : Expression
9336         {
9337                 public readonly string Name;
9338                 Expression initializer;
9339
9340                 public AnonymousTypeParameter (Expression initializer, string name, Location loc)
9341                 {
9342                         this.Name = name;
9343                         this.loc = loc;
9344                         this.initializer = initializer;
9345                 }
9346                 
9347                 public AnonymousTypeParameter (Parameter parameter)
9348                 {
9349                         this.Name = parameter.Name;
9350                         this.loc = parameter.Location;
9351                         this.initializer = new SimpleName (Name, loc);
9352                 }               
9353
9354                 protected override void CloneTo (CloneContext clonectx, Expression target)
9355                 {
9356                         AnonymousTypeParameter t = (AnonymousTypeParameter) target;
9357                         t.initializer = initializer.Clone (clonectx);
9358                 }
9359
9360                 public override bool Equals (object o)
9361                 {
9362                         AnonymousTypeParameter other = o as AnonymousTypeParameter;
9363                         return other != null && Name == other.Name;
9364                 }
9365
9366                 public override int GetHashCode ()
9367                 {
9368                         return Name.GetHashCode ();
9369                 }
9370
9371                 public override Expression DoResolve (EmitContext ec)
9372                 {
9373                         Expression e = initializer.Resolve (ec);
9374                         if (e == null)
9375                                 return null;
9376
9377                         type = e.Type;
9378                         if (type == TypeManager.void_type || type == TypeManager.null_type ||
9379                                 type == TypeManager.anonymous_method_type || type.IsPointer) {
9380                                 Error_InvalidInitializer (e);
9381                                 return null;
9382                         }
9383
9384                         return e;
9385                 }
9386
9387                 protected virtual void Error_InvalidInitializer (Expression initializer)
9388                 {
9389                         Report.Error (828, loc, "An anonymous type property `{0}' cannot be initialized with `{1}'",
9390                                 Name, initializer.GetSignatureForError ());
9391                 }
9392
9393                 public override void Emit (EmitContext ec)
9394                 {
9395                         throw new InternalErrorException ("Should not be reached");
9396                 }
9397         }
9398 }