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