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