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