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