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