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