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