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