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