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