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