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