More tests.
[mono.git] / mcs / mcs / ecore.cs
1 //
2 // ecore.cs: Core of the Expression representation for the intermediate 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 //
12
13 namespace Mono.CSharp {
14         using System;
15         using System.Collections;
16         using System.Diagnostics;
17         using System.Reflection;
18         using System.Reflection.Emit;
19         using System.Text;
20
21 #if NET_4_0
22         using SLE = System.Linq.Expressions;
23 #endif
24
25         /// <remarks>
26         ///   The ExprClass class contains the is used to pass the 
27         ///   classification of an expression (value, variable, namespace,
28         ///   type, method group, property access, event access, indexer access,
29         ///   nothing).
30         /// </remarks>
31         public enum ExprClass : byte {
32                 Invalid,
33                 
34                 Value,
35                 Variable,
36                 Namespace,
37                 Type,
38                 TypeParameter,
39                 MethodGroup,
40                 PropertyAccess,
41                 EventAccess,
42                 IndexerAccess,
43                 Nothing, 
44         }
45
46         /// <remarks>
47         ///   This is used to tell Resolve in which types of expressions we're
48         ///   interested.
49         /// </remarks>
50         [Flags]
51         public enum ResolveFlags {
52                 // Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess.
53                 VariableOrValue         = 1,
54
55                 // Returns a type expression.
56                 Type                    = 1 << 1,
57
58                 // Returns a method group.
59                 MethodGroup             = 1 << 2,
60
61                 TypeParameter   = 1 << 3,
62
63                 // Mask of all the expression class flags.
64                 MaskExprClass = VariableOrValue | Type | MethodGroup | TypeParameter,
65
66                 // Disable control flow analysis while resolving the expression.
67                 // This is used when resolving the instance expression of a field expression.
68                 DisableFlowAnalysis     = 1 << 10,
69
70                 // Set if this is resolving the first part of a MemberAccess.
71                 Intermediate            = 1 << 11,
72
73                 // Disable control flow analysis _of struct_ while resolving the expression.
74                 // This is used when resolving the instance expression of a field expression.
75                 DisableStructFlowAnalysis       = 1 << 12,
76
77         }
78
79         //
80         // This is just as a hint to AddressOf of what will be done with the
81         // address.
82         [Flags]
83         public enum AddressOp {
84                 Store = 1,
85                 Load  = 2,
86                 LoadStore = 3
87         };
88         
89         /// <summary>
90         ///   This interface is implemented by variables
91         /// </summary>
92         public interface IMemoryLocation {
93                 /// <summary>
94                 ///   The AddressOf method should generate code that loads
95                 ///   the address of the object and leaves it on the stack.
96                 ///
97                 ///   The `mode' argument is used to notify the expression
98                 ///   of whether this will be used to read from the address or
99                 ///   write to the address.
100                 ///
101                 ///   This is just a hint that can be used to provide good error
102                 ///   reporting, and should have no other side effects. 
103                 /// </summary>
104                 void AddressOf (EmitContext ec, AddressOp mode);
105         }
106
107         //
108         // An expressions resolved as a direct variable reference
109         //
110         public interface IVariableReference : IFixedExpression
111         {
112                 bool IsHoisted { get; }
113                 string Name { get; }
114                 VariableInfo VariableInfo { get; }
115
116                 void SetHasAddressTaken ();
117         }
118
119         //
120         // Implemented by an expression which could be or is always
121         // fixed
122         //
123         public interface IFixedExpression
124         {
125                 bool IsFixed { get; }
126         }
127
128         /// <remarks>
129         ///   Base class for expressions
130         /// </remarks>
131         public abstract class Expression {
132                 public ExprClass eclass;
133                 protected Type type;
134                 protected Location loc;
135                 
136                 public Type Type {
137                         get { return type; }
138                         set { type = value; }
139                 }
140
141                 public virtual Location Location {
142                         get { return loc; }
143                 }
144
145                 // Not nice but we have broken hierarchy.
146                 public virtual void CheckMarshalByRefAccess (ResolveContext ec)
147                 {
148                 }
149
150                 public virtual bool GetAttributableValue (ResolveContext ec, Type value_type, out object value)
151                 {
152                         Attribute.Error_AttributeArgumentNotValid (ec, loc);
153                         value = null;
154                         return false;
155                 }
156
157                 public virtual string GetSignatureForError ()
158                 {
159                         return TypeManager.CSharpName (type);
160                 }
161
162                 public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check)
163                 {
164                         MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
165
166                         must_do_cs1540_check = false; // by default we do not check for this
167
168                         if (ma == MethodAttributes.Public)
169                                 return true;
170                         
171                         //
172                         // If only accessible to the current class or children
173                         //
174                         if (ma == MethodAttributes.Private)
175                                 return TypeManager.IsPrivateAccessible (invocation_type, mi.DeclaringType) ||
176                                         TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
177
178                         if (TypeManager.IsThisOrFriendAssembly (invocation_type.Assembly, mi.DeclaringType.Assembly)) {
179                                 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
180                                         return true;
181                         } else {
182                                 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
183                                         return false;
184                         }
185
186                         // Family and FamANDAssem require that we derive.
187                         // FamORAssem requires that we derive if in different assemblies.
188                         if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
189                                 return false;
190
191                         if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
192                                 must_do_cs1540_check = true;
193
194                         return true;
195                 }
196
197                 public virtual bool IsNull {
198                         get {
199                                 return false;
200                         }
201                 }
202
203                 /// <summary>
204                 ///   Performs semantic analysis on the Expression
205                 /// </summary>
206                 ///
207                 /// <remarks>
208                 ///   The Resolve method is invoked to perform the semantic analysis
209                 ///   on the node.
210                 ///
211                 ///   The return value is an expression (it can be the
212                 ///   same expression in some cases) or a new
213                 ///   expression that better represents this node.
214                 ///   
215                 ///   For example, optimizations of Unary (LiteralInt)
216                 ///   would return a new LiteralInt with a negated
217                 ///   value.
218                 ///   
219                 ///   If there is an error during semantic analysis,
220                 ///   then an error should be reported (using Report)
221                 ///   and a null value should be returned.
222                 ///   
223                 ///   There are two side effects expected from calling
224                 ///   Resolve(): the the field variable "eclass" should
225                 ///   be set to any value of the enumeration
226                 ///   `ExprClass' and the type variable should be set
227                 ///   to a valid type (this is the type of the
228                 ///   expression).
229                 /// </remarks>
230                 public abstract Expression DoResolve (ResolveContext ec);
231
232                 public virtual Expression DoResolveLValue (ResolveContext ec, Expression right_side)
233                 {
234                         return null;
235                 }
236
237                 //
238                 // This is used if the expression should be resolved as a type or namespace name.
239                 // the default implementation fails.   
240                 //
241                 public virtual FullNamedExpression ResolveAsTypeStep (IMemberContext rc,  bool silent)
242                 {
243                         if (!silent) {
244                                 ResolveContext ec = new ResolveContext (rc);
245                                 Expression e = Resolve (ec);
246                                 if (e != null)
247                                         e.Error_UnexpectedKind (ec, ResolveFlags.Type, loc);
248                         }
249
250                         return null;
251                 }
252
253                 //
254                 // C# 3.0 introduced contextual keywords (var) which behaves like a type if type with
255                 // same name exists or as a keyword when no type was found
256                 // 
257                 public virtual TypeExpr ResolveAsContextualType (IMemberContext rc, bool silent)
258                 {
259                         return ResolveAsTypeTerminal (rc, silent);
260                 }               
261                 
262                 //
263                 // This is used to resolve the expression as a type, a null
264                 // value will be returned if the expression is not a type
265                 // reference
266                 //
267                 public virtual TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent)
268                 {
269                         TypeExpr te = ResolveAsBaseTerminal (ec, silent);
270                         if (te == null)
271                                 return null;
272
273                         if (!silent) { // && !(te is TypeParameterExpr)) {
274                                 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (te.Type);
275                                 if (obsolete_attr != null && !ec.IsObsolete) {
276                                         AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location, ec.Compiler.Report);
277                                 }
278                         }
279
280                         GenericTypeExpr ct = te as GenericTypeExpr;
281                         if (ct != null) {
282                                 //
283                                 // TODO: Constrained type parameters check for parameters of generic method overrides is broken
284                                 // There are 2 solutions.
285                                 // 1, Skip this check completely when we are in override/explicit impl scope
286                                 // 2, Copy type parameters constraints from base implementation and pass (they have to be emitted anyway)
287                                 //
288                                 MemberCore gm = ec as GenericMethod;
289                                 if (gm == null)
290                                         gm = ec as Method;
291                                 if (gm != null && ((gm.ModFlags & Modifiers.OVERRIDE) != 0 || gm.MemberName.Left != null)) {
292                                         te.loc = loc;
293                                         return te;
294                                 }
295
296                                 // TODO: silent flag is ignored
297                                 ct.CheckConstraints (ec);
298                         }
299
300                         return te;
301                 }
302         
303                 public TypeExpr ResolveAsBaseTerminal (IMemberContext ec, bool silent)
304                 {
305                         int errors = ec.Compiler.Report.Errors;
306
307                         FullNamedExpression fne = ResolveAsTypeStep (ec, silent);
308
309                         if (fne == null)
310                                 return null;
311                                 
312                         TypeExpr te = fne as TypeExpr;                          
313                         if (te == null) {
314                                 if (!silent && errors == ec.Compiler.Report.Errors)
315                                         fne.Error_UnexpectedKind (ec.Compiler.Report, null, "type", loc);
316                                 return null;
317                         }
318
319                         if (!te.CheckAccessLevel (ec)) {
320                                 ec.Compiler.Report.SymbolRelatedToPreviousError (te.Type);
321                                 ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type), ec.Compiler.Report);
322                                 return null;
323                         }
324
325                         te.loc = loc;
326                         return te;
327                 }
328
329                 public static void ErrorIsInaccesible (Location loc, string name, Report Report)
330                 {
331                         Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name);
332                 }
333
334                 protected static void Error_CannotAccessProtected (ResolveContext ec, Location loc, MemberInfo m, Type qualifier, Type container)
335                 {
336                         ec.Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}'."
337                                 + " The qualifier must be of type `{2}' or derived from it", 
338                                 TypeManager.GetFullNameSignature (m),
339                                 TypeManager.CSharpName (qualifier),
340                                 TypeManager.CSharpName (container));
341
342                 }
343
344                 public static void Error_InvalidExpressionStatement (Report Report, Location loc)
345                 {
346                         Report.Error (201, loc, "Only assignment, call, increment, decrement, and new object " +
347                                        "expressions can be used as a statement");
348                 }
349                 
350                 public void Error_InvalidExpressionStatement (BlockContext ec)
351                 {
352                         Error_InvalidExpressionStatement (ec.Report, loc);
353                 }
354
355                 public static void Error_VoidInvalidInTheContext (Location loc, Report Report)
356                 {
357                         Report.Error (1547, loc, "Keyword `void' cannot be used in this context");
358                 }
359
360                 public virtual void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, Type target, bool expl)
361                 {
362                         Error_ValueCannotBeConvertedCore (ec, loc, target, expl);
363                 }
364
365                 protected void Error_ValueCannotBeConvertedCore (ResolveContext ec, Location loc, Type target, bool expl)
366                 {
367                         // The error was already reported as CS1660
368                         if (type == InternalType.AnonymousMethod)
369                                 return;
370
371                         if (TypeManager.IsGenericParameter (Type) && TypeManager.IsGenericParameter (target) && type.Name == target.Name) {
372                                 string sig1 = type.DeclaringMethod == null ?
373                                         TypeManager.CSharpName (type.DeclaringType) :
374                                         TypeManager.CSharpSignature (type.DeclaringMethod);
375                                 string sig2 = target.DeclaringMethod == null ?
376                                         TypeManager.CSharpName (target.DeclaringType) :
377                                         TypeManager.CSharpSignature (target.DeclaringMethod);
378                                 ec.Report.ExtraInformation (loc,
379                                         String.Format (
380                                                 "The generic parameter `{0}' of `{1}' cannot be converted to the generic parameter `{0}' of `{2}' (in the previous ",
381                                                 Type.Name, sig1, sig2));
382                         } else if (Type.FullName == target.FullName){
383                                 ec.Report.ExtraInformation (loc,
384                                         String.Format (
385                                         "The type `{0}' has two conflicting definitions, one comes from `{1}' and the other from `{2}' (in the previous ",
386                                         Type.FullName, Type.Assembly.FullName, target.Assembly.FullName));
387                         }
388
389                         if (expl) {
390                                 ec.Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
391                                         TypeManager.CSharpName (type), TypeManager.CSharpName (target));
392                                 return;
393                         }
394
395                         ec.Report.DisableReporting ();
396                         bool expl_exists = Convert.ExplicitConversion (ec, this, target, Location.Null) != null;
397                         ec.Report.EnableReporting ();
398
399                         if (expl_exists) {
400                                 ec.Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. " +
401                                               "An explicit conversion exists (are you missing a cast?)",
402                                         TypeManager.CSharpName (Type), TypeManager.CSharpName (target));
403                                 return;
404                         }
405
406                         ec.Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'",
407                                 TypeManager.CSharpName (type),
408                                 TypeManager.CSharpName (target));
409                 }
410
411                 public virtual void Error_VariableIsUsedBeforeItIsDeclared (Report Report, string name)
412                 {
413                         Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", name);
414                 }
415
416                 public void Error_TypeArgumentsCannotBeUsed (Report report, Location loc)
417                 {
418                         // Better message for possible generic expressions
419                         if (eclass == ExprClass.MethodGroup || eclass == ExprClass.Type) {
420                                 if (this is TypeExpr)
421                                         report.SymbolRelatedToPreviousError (type);
422
423                                 string name = eclass == ExprClass.Type ? ExprClassName : "method";
424                                 report.Error (308, loc, "The non-generic {0} `{1}' cannot be used with the type arguments",
425                                         name, GetSignatureForError ());
426                         } else {
427                                 report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments",
428                                         ExprClassName, GetSignatureForError ());
429                         }
430                 }
431
432                 protected virtual void Error_TypeDoesNotContainDefinition (ResolveContext ec, Type type, string name)
433                 {
434                         Error_TypeDoesNotContainDefinition (ec, loc, type, name);
435                 }
436
437                 public static void Error_TypeDoesNotContainDefinition (ResolveContext ec, Location loc, Type type, string name)
438                 {
439                         ec.Report.SymbolRelatedToPreviousError (type);
440                         ec.Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
441                                 TypeManager.CSharpName (type), name);
442                 }
443
444                 protected static void Error_ValueAssignment (ResolveContext ec, Location loc)
445                 {
446                         ec.Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer");
447                 }
448
449                 ResolveFlags ExprClassToResolveFlags
450                 {
451                         get {
452                                 switch (eclass) {
453                                 case ExprClass.Type:
454                                 case ExprClass.Namespace:
455                                         return ResolveFlags.Type;
456                                         
457                                 case ExprClass.MethodGroup:
458                                         return ResolveFlags.MethodGroup;
459                                         
460                                 case ExprClass.TypeParameter:
461                                         return ResolveFlags.TypeParameter;
462                                         
463                                 case ExprClass.Value:
464                                 case ExprClass.Variable:
465                                 case ExprClass.PropertyAccess:
466                                 case ExprClass.EventAccess:
467                                 case ExprClass.IndexerAccess:
468                                         return ResolveFlags.VariableOrValue;
469                                         
470                                 default:
471                                         throw new InternalErrorException (loc.ToString () + " " +  GetType () + " ExprClass is Invalid after resolve");
472                                 }
473                         }
474                 }
475                
476                 /// <summary>
477                 ///   Resolves an expression and performs semantic analysis on it.
478                 /// </summary>
479                 ///
480                 /// <remarks>
481                 ///   Currently Resolve wraps DoResolve to perform sanity
482                 ///   checking and assertion checking on what we expect from Resolve.
483                 /// </remarks>
484                 public Expression Resolve (ResolveContext ec, ResolveFlags flags)
485                 {
486                         if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) 
487                                 return ResolveAsTypeStep (ec, false);
488
489                         bool do_flow_analysis = ec.DoFlowAnalysis;
490                         bool omit_struct_analysis = ec.OmitStructFlowAnalysis;
491                         if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
492                                 do_flow_analysis = false;
493                         if ((flags & ResolveFlags.DisableStructFlowAnalysis) != 0)
494                                 omit_struct_analysis = true;
495
496                         Expression e;
497                         using (ec.WithFlowAnalysis (do_flow_analysis, omit_struct_analysis)) {
498                                 if (this is SimpleName) {
499                                         bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate;
500                                         e = ((SimpleName) this).DoResolve (ec, intermediate);
501                                 } else {
502                                         e = DoResolve (ec);
503                                 }
504                         }
505
506                         if (e == null)
507                                 return null;
508
509                         if ((flags & e.ExprClassToResolveFlags) == 0) {
510                                 e.Error_UnexpectedKind (ec, flags, loc);
511                                 return null;
512                         }
513
514                         if (e.type == null && !(e is Namespace)) {
515                                 throw new Exception (
516                                         "Expression " + e.GetType () +
517                                         " did not set its type after Resolve\n" +
518                                         "called from: " + this.GetType ());
519                         }
520
521                         return e;
522                 }
523
524                 /// <summary>
525                 ///   Resolves an expression and performs semantic analysis on it.
526                 /// </summary>
527                 public Expression Resolve (ResolveContext ec)
528                 {
529                         Expression e = Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
530
531                         if (e != null && e.eclass == ExprClass.MethodGroup && RootContext.Version == LanguageVersion.ISO_1) {
532                                 ((MethodGroupExpr) e).ReportUsageError (ec);
533                                 return null;
534                         }
535                         return e;
536                 }
537
538                 public Constant ResolveAsConstant (ResolveContext ec, MemberCore mc)
539                 {
540                         Expression e = Resolve (ec);
541                         if (e == null)
542                                 return null;
543
544                         Constant c = e as Constant;
545                         if (c != null)
546                                 return c;
547
548                         if (type != null && TypeManager.IsReferenceType (type))
549                                 Const.Error_ConstantCanBeInitializedWithNullOnly (type, loc, mc.GetSignatureForError (), ec.Report);
550                         else
551                                 Const.Error_ExpressionMustBeConstant (loc, mc.GetSignatureForError (), ec.Report);
552
553                         return null;
554                 }
555
556                 /// <summary>
557                 ///   Resolves an expression for LValue assignment
558                 /// </summary>
559                 ///
560                 /// <remarks>
561                 ///   Currently ResolveLValue wraps DoResolveLValue to perform sanity
562                 ///   checking and assertion checking on what we expect from Resolve
563                 /// </remarks>
564                 public Expression ResolveLValue (ResolveContext ec, Expression right_side)
565                 {
566                         int errors = ec.Report.Errors;
567                         bool out_access = right_side == EmptyExpression.OutAccess.Instance;
568
569                         Expression e = DoResolveLValue (ec, right_side);
570
571                         if (e != null && out_access && !(e is IMemoryLocation)) {
572                                 // FIXME: There's no problem with correctness, the 'Expr = null' handles that.
573                                 //        Enabling this 'throw' will "only" result in deleting useless code elsewhere,
574
575                                 //throw new InternalErrorException ("ResolveLValue didn't return an IMemoryLocation: " +
576                                 //                                e.GetType () + " " + e.GetSignatureForError ());
577                                 e = null;
578                         }
579
580                         if (e == null) {
581                                 if (errors == ec.Report.Errors) {
582                                         if (out_access)
583                                                 ec.Report.Error (1510, loc, "A ref or out argument must be an assignable variable");
584                                         else
585                                                 Error_ValueAssignment (ec, loc);
586                                 }
587                                 return null;
588                         }
589
590                         if (e.eclass == ExprClass.Invalid)
591                                 throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve");
592
593                         if ((e.type == null) && !(e is GenericTypeExpr))
594                                 throw new Exception ("Expression " + e + " did not set its type after Resolve");
595
596                         return e;
597                 }
598
599                 /// <summary>
600                 ///   Emits the code for the expression
601                 /// </summary>
602                 ///
603                 /// <remarks>
604                 ///   The Emit method is invoked to generate the code
605                 ///   for the expression.  
606                 /// </remarks>
607                 public abstract void Emit (EmitContext ec);
608
609                 // Emit code to branch to @target if this expression is equivalent to @on_true.
610                 // The default implementation is to emit the value, and then emit a brtrue or brfalse.
611                 // Subclasses can provide more efficient implementations, but those MUST be equivalent,
612                 // including the use of conditional branches.  Note also that a branch MUST be emitted
613                 public virtual void EmitBranchable (EmitContext ec, Label target, bool on_true)
614                 {
615                         Emit (ec);
616                         ec.ig.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
617                 }
618
619                 // Emit this expression for its side effects, not for its value.
620                 // The default implementation is to emit the value, and then throw it away.
621                 // Subclasses can provide more efficient implementations, but those MUST be equivalent
622                 public virtual void EmitSideEffect (EmitContext ec)
623                 {
624                         Emit (ec);
625                         ec.ig.Emit (OpCodes.Pop);
626                 }
627
628                 /// <summary>
629                 ///   Protected constructor.  Only derivate types should
630                 ///   be able to be created
631                 /// </summary>
632
633                 protected Expression ()
634                 {
635                         eclass = ExprClass.Invalid;
636                         type = null;
637                 }
638
639                 /// <summary>
640                 ///   Returns a fully formed expression after a MemberLookup
641                 /// </summary>
642                 /// 
643                 public static Expression ExprClassFromMemberInfo (Type container_type, MemberInfo mi, Location loc)
644                 {
645                         if (mi is EventInfo)
646                                 return new EventExpr ((EventInfo) mi, loc);
647                         else if (mi is FieldInfo) {
648                                 FieldInfo fi = (FieldInfo) mi;
649                                 if (fi.IsLiteral || (fi.IsInitOnly && fi.FieldType == TypeManager.decimal_type))
650                                         return new ConstantExpr (fi, loc);
651                                 return new FieldExpr (fi, loc);
652                         } else if (mi is PropertyInfo)
653                                 return new PropertyExpr (container_type, (PropertyInfo) mi, loc);
654                         else if (mi is Type) {
655                                 return new TypeExpression ((System.Type) mi, loc);
656                         }
657
658                         return null;
659                 }
660
661                 // TODO: [Obsolete ("Can be removed")]
662                 protected static ArrayList almost_matched_members = new ArrayList (4);
663
664                 //
665                 // FIXME: Probably implement a cache for (t,name,current_access_set)?
666                 //
667                 // This code could use some optimizations, but we need to do some
668                 // measurements.  For example, we could use a delegate to `flag' when
669                 // something can not any longer be a method-group (because it is something
670                 // else).
671                 //
672                 // Return values:
673                 //     If the return value is an Array, then it is an array of
674                 //     MethodBases
675                 //   
676                 //     If the return value is an MemberInfo, it is anything, but a Method
677                 //
678                 //     null on error.
679                 //
680                 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
681                 // the arguments here and have MemberLookup return only the methods that
682                 // match the argument count/type, unlike we are doing now (we delay this
683                 // decision).
684                 //
685                 // This is so we can catch correctly attempts to invoke instance methods
686                 // from a static body (scan for error 120 in ResolveSimpleName).
687                 //
688                 //
689                 // FIXME: Potential optimization, have a static ArrayList
690                 //
691
692                 public static Expression MemberLookup (CompilerContext ctx, Type container_type, Type queried_type, string name,
693                                                        MemberTypes mt, BindingFlags bf, Location loc)
694                 {
695                         return MemberLookup (ctx, container_type, null, queried_type, name, mt, bf, loc);
696                 }
697
698                 //
699                 // Lookup type `queried_type' for code in class `container_type' with a qualifier of
700                 // `qualifier_type' or null to lookup members in the current class.
701                 //
702
703                 public static Expression MemberLookup (CompilerContext ctx, Type container_type,
704                                                        Type qualifier_type, Type queried_type,
705                                                        string name, MemberTypes mt,
706                                                        BindingFlags bf, Location loc)
707                 {
708                         almost_matched_members.Clear ();
709
710                         MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type,
711                                                                      queried_type, mt, bf, name, almost_matched_members);
712
713                         if (mi == null)
714                                 return null;
715
716                         if (mi.Length > 1) {
717                                 bool is_interface = qualifier_type != null && qualifier_type.IsInterface;
718                                 ArrayList methods = new ArrayList (2);
719                                 ArrayList non_methods = null;
720
721                                 foreach (MemberInfo m in mi) {
722                                         if (m is MethodBase) {
723                                                 methods.Add (m);
724                                                 continue;
725                                         }
726
727                                         if (non_methods == null)
728                                                 non_methods = new ArrayList (2);
729
730                                         bool is_candidate = true;
731                                         for (int i = 0; i < non_methods.Count; ++i) {
732                                                 MemberInfo n_m = (MemberInfo) non_methods [i];
733                                                 if (n_m.DeclaringType.IsInterface && TypeManager.ImplementsInterface (m.DeclaringType, n_m.DeclaringType)) {
734                                                         non_methods.Remove (n_m);
735                                                         --i;
736                                                 } else if (m.DeclaringType.IsInterface && TypeManager.ImplementsInterface (n_m.DeclaringType, m.DeclaringType)) {
737                                                         is_candidate = false;
738                                                         break;
739                                                 }
740                                         }
741                                         
742                                         if (is_candidate) {
743                                                 non_methods.Add (m);
744                                         }
745                                 }
746                                 
747                                 if (methods.Count == 0 && non_methods != null && non_methods.Count > 1) {
748                                         ctx.Report.SymbolRelatedToPreviousError ((MemberInfo)non_methods [1]);
749                                         ctx.Report.SymbolRelatedToPreviousError ((MemberInfo)non_methods [0]);
750                                         ctx.Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
751                                                 TypeManager.GetFullNameSignature ((MemberInfo)non_methods [1]),
752                                                 TypeManager.GetFullNameSignature ((MemberInfo)non_methods [0]));
753                                         return null;
754                                 }
755
756                                 if (methods.Count == 0)
757                                         return ExprClassFromMemberInfo (container_type, (MemberInfo)non_methods [0], loc);
758
759                                 if (non_methods != null && non_methods.Count > 0) {
760                                         MethodBase method = (MethodBase) methods [0];
761                                         MemberInfo non_method = (MemberInfo) non_methods [0];
762                                         if (method.DeclaringType == non_method.DeclaringType) {
763                                                 // Cannot happen with C# code, but is valid in IL
764                                                 ctx.Report.SymbolRelatedToPreviousError (method);
765                                                 ctx.Report.SymbolRelatedToPreviousError (non_method);
766                                                 ctx.Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
767                                                               TypeManager.GetFullNameSignature (non_method),
768                                                               TypeManager.CSharpSignature (method));
769                                                 return null;
770                                         }
771
772                                         if (is_interface) {
773                                                 ctx.Report.SymbolRelatedToPreviousError (method);
774                                                 ctx.Report.SymbolRelatedToPreviousError (non_method);
775                                                 ctx.Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and non-method `{1}'. Using method `{0}'",
776                                                                 TypeManager.CSharpSignature (method), TypeManager.GetFullNameSignature (non_method));
777                                         }
778                                 }
779
780                                 return new MethodGroupExpr (methods, queried_type, loc);
781                         }
782
783                         if (mi [0] is MethodBase)
784                                 return new MethodGroupExpr (mi, queried_type, loc);
785
786                         return ExprClassFromMemberInfo (container_type, mi [0], loc);
787                 }
788
789                 public const MemberTypes AllMemberTypes =
790                         MemberTypes.Constructor |
791                         MemberTypes.Event       |
792                         MemberTypes.Field       |
793                         MemberTypes.Method      |
794                         MemberTypes.NestedType  |
795                         MemberTypes.Property;
796                 
797                 public const BindingFlags AllBindingFlags =
798                         BindingFlags.Public |
799                         BindingFlags.Static |
800                         BindingFlags.Instance;
801
802                 public static Expression MemberLookup (CompilerContext ctx, Type container_type, Type queried_type,
803                                                        string name, Location loc)
804                 {
805                         return MemberLookup (ctx, container_type, null, queried_type, name,
806                                              AllMemberTypes, AllBindingFlags, loc);
807                 }
808
809                 public static Expression MemberLookup (CompilerContext ctx, Type container_type, Type qualifier_type,
810                                                        Type queried_type, string name, Location loc)
811                 {
812                         return MemberLookup (ctx, container_type, qualifier_type, queried_type,
813                                              name, AllMemberTypes, AllBindingFlags, loc);
814                 }
815
816                 public static MethodGroupExpr MethodLookup (CompilerContext ctx, Type container_type, Type queried_type,
817                                                        string name, Location loc)
818                 {
819                         return (MethodGroupExpr)MemberLookup (ctx, container_type, null, queried_type, name,
820                                              MemberTypes.Method, AllBindingFlags, loc);
821                 }
822
823                 /// <summary>
824                 ///   This is a wrapper for MemberLookup that is not used to "probe", but
825                 ///   to find a final definition.  If the final definition is not found, we
826                 ///   look for private members and display a useful debugging message if we
827                 ///   find it.
828                 /// </summary>
829                 protected Expression MemberLookupFinal (ResolveContext ec, Type qualifier_type,
830                                                             Type queried_type, string name,
831                                                             MemberTypes mt, BindingFlags bf,
832                                                             Location loc)
833                 {
834                         Expression e;
835
836                         int errors = ec.Report.Errors;
837                         e = MemberLookup (ec.Compiler, ec.CurrentType, qualifier_type, queried_type, name, mt, bf, loc);
838
839                         if (e != null || errors != ec.Report.Errors)
840                                 return e;
841
842                         // No errors were reported by MemberLookup, but there was an error.
843                         return Error_MemberLookupFailed (ec, ec.CurrentType, qualifier_type, queried_type,
844                                         name, null, mt, bf);
845                 }
846
847                 protected virtual Expression Error_MemberLookupFailed (ResolveContext ec, Type container_type, Type qualifier_type,
848                                                        Type queried_type, string name, string class_name,
849                                                            MemberTypes mt, BindingFlags bf)
850                 {
851                         MemberInfo[] lookup = null;
852                         if (queried_type == null) {
853                                 class_name = "global::";
854                         } else {
855                                 lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
856                                         mt, (bf & ~BindingFlags.Public) | BindingFlags.NonPublic,
857                                         name, null);
858
859                                 if (lookup != null) {
860                                         Expression e = Error_MemberLookupFailed (ec, queried_type, lookup);
861
862                                         //
863                                         // FIXME: This is still very wrong, it should be done inside
864                                         // OverloadResolve to do correct arguments matching.
865                                         // Requires MemberLookup accessiblity check removal
866                                         //
867                                         if (e == null || (mt & (MemberTypes.Method | MemberTypes.Constructor)) == 0) {
868                                                 MemberInfo mi = lookup[0];
869                                                 ec.Report.SymbolRelatedToPreviousError (mi);
870                                                 if (qualifier_type != null && container_type != null && qualifier_type != container_type &&
871                                                         TypeManager.IsNestedFamilyAccessible (container_type, mi.DeclaringType)) {
872                                                         // Although a derived class can access protected members of
873                                                         // its base class it cannot do so through an instance of the
874                                                         // base class (CS1540).  If the qualifier_type is a base of the
875                                                         // ec.CurrentType and the lookup succeeds with the latter one,
876                                                         // then we are in this situation.
877                                                         Error_CannotAccessProtected (ec, loc, mi, qualifier_type, container_type);
878                                                 } else {
879                                                         ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (mi), ec.Report);
880                                                 }
881                                         }
882
883                                         return e;
884                                 }
885
886                                 lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
887                                         AllMemberTypes, AllBindingFlags | BindingFlags.NonPublic,
888                                         name, null);
889                         }
890
891                         if (lookup == null) {
892                                 if (class_name != null) {
893                                         ec.Report.Error (103, loc, "The name `{0}' does not exist in the current context",
894                                                 name);
895                                 } else {
896                                         Error_TypeDoesNotContainDefinition (ec, queried_type, name);
897                                 }
898                                 return null;
899                         }
900
901                         if (TypeManager.MemberLookup (queried_type, null, queried_type,
902                                                       AllMemberTypes, AllBindingFlags |
903                                                       BindingFlags.NonPublic, name, null) == null) {
904                                 if ((lookup.Length == 1) && (lookup [0] is Type)) {
905                                         Type t = (Type) lookup [0];
906
907                                         ec.Report.Error (305, loc,
908                                                       "Using the generic type `{0}' " +
909                                                       "requires {1} type arguments",
910                                                       TypeManager.CSharpName (t),
911                                                       TypeManager.GetNumberOfTypeArguments (t).ToString ());
912                                         return null;
913                                 }
914                         }
915
916                         return Error_MemberLookupFailed (ec, queried_type, lookup);
917                 }
918
919                 protected virtual Expression Error_MemberLookupFailed (ResolveContext ec, Type type, MemberInfo[] members)
920                 {
921                         for (int i = 0; i < members.Length; ++i) {
922                                 if (!(members [i] is MethodBase))
923                                         return null;
924                         }
925
926                         // By default propagate the closest candidates upwards
927                         return new MethodGroupExpr (members, type, loc, true);
928                 }
929
930                 protected virtual void Error_NegativeArrayIndex (ResolveContext ec, Location loc)
931                 {
932                         throw new NotImplementedException ();
933                 }
934
935                 protected void Error_PointerInsideExpressionTree (ResolveContext ec)
936                 {
937                         ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
938                 }
939
940                 /// <summary>
941                 ///   Returns an expression that can be used to invoke operator true
942                 ///   on the expression if it exists.
943                 /// </summary>
944                 protected static Expression GetOperatorTrue (ResolveContext ec, Expression e, Location loc)
945                 {
946                         return GetOperatorTrueOrFalse (ec, e, true, loc);
947                 }
948
949                 /// <summary>
950                 ///   Returns an expression that can be used to invoke operator false
951                 ///   on the expression if it exists.
952                 /// </summary>
953                 static public Expression GetOperatorFalse (ResolveContext ec, Expression e, Location loc)
954                 {
955                         return GetOperatorTrueOrFalse (ec, e, false, loc);
956                 }
957
958                 static Expression GetOperatorTrueOrFalse (ResolveContext ec, Expression e, bool is_true, Location loc)
959                 {
960                         MethodGroupExpr operator_group;
961                         string mname = Operator.GetMetadataName (is_true ? Operator.OpType.True : Operator.OpType.False);
962                         operator_group = MethodLookup (ec.Compiler, ec.CurrentType, e.Type, mname, loc) as MethodGroupExpr;
963                         if (operator_group == null)
964                                 return null;
965
966                         Arguments arguments = new Arguments (1);
967                         arguments.Add (new Argument (e));
968                         operator_group = operator_group.OverloadResolve (
969                                 ec, ref arguments, false, loc);
970
971                         if (operator_group == null)
972                                 return null;
973
974                         return new UserOperatorCall (operator_group, arguments, null, loc);
975                 }
976
977                 public virtual string ExprClassName
978                 {
979                         get {
980                                 switch (eclass){
981                                 case ExprClass.Invalid:
982                                         return "Invalid";
983                                 case ExprClass.Value:
984                                         return "value";
985                                 case ExprClass.Variable:
986                                         return "variable";
987                                 case ExprClass.Namespace:
988                                         return "namespace";
989                                 case ExprClass.Type:
990                                         return "type";
991                                 case ExprClass.MethodGroup:
992                                         return "method group";
993                                 case ExprClass.PropertyAccess:
994                                         return "property access";
995                                 case ExprClass.EventAccess:
996                                         return "event access";
997                                 case ExprClass.IndexerAccess:
998                                         return "indexer access";
999                                 case ExprClass.Nothing:
1000                                         return "null";
1001                                 case ExprClass.TypeParameter:
1002                                         return "type parameter";
1003                                 }
1004                                 throw new Exception ("Should not happen");
1005                         }
1006                 }
1007                 
1008                 /// <summary>
1009                 ///   Reports that we were expecting `expr' to be of class `expected'
1010                 /// </summary>
1011                 public void Error_UnexpectedKind (Report r, MemberCore mc, string expected, Location loc)
1012                 {
1013                         Error_UnexpectedKind (r, mc, expected, ExprClassName, loc);
1014                 }
1015
1016                 public void Error_UnexpectedKind (Report r, MemberCore mc, string expected, string was, Location loc)
1017                 {
1018                         string name;
1019                         if (mc != null)
1020                                 name = mc.GetSignatureForError ();
1021                         else
1022                                 name = GetSignatureForError ();
1023
1024                         r.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected",
1025                               name, was, expected);
1026                 }
1027
1028                 public void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc)
1029                 {
1030                         string [] valid = new string [4];
1031                         int count = 0;
1032
1033                         if ((flags & ResolveFlags.VariableOrValue) != 0) {
1034                                 valid [count++] = "variable";
1035                                 valid [count++] = "value";
1036                         }
1037
1038                         if ((flags & ResolveFlags.Type) != 0)
1039                                 valid [count++] = "type";
1040
1041                         if ((flags & ResolveFlags.MethodGroup) != 0)
1042                                 valid [count++] = "method group";
1043
1044                         if (count == 0)
1045                                 valid [count++] = "unknown";
1046
1047                         StringBuilder sb = new StringBuilder (valid [0]);
1048                         for (int i = 1; i < count - 1; i++) {
1049                                 sb.Append ("', `");
1050                                 sb.Append (valid [i]);
1051                         }
1052                         if (count > 1) {
1053                                 sb.Append ("' or `");
1054                                 sb.Append (valid [count - 1]);
1055                         }
1056
1057                         ec.Report.Error (119, loc, 
1058                                 "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ());
1059                 }
1060                 
1061                 public static void UnsafeError (ResolveContext ec, Location loc)
1062                 {
1063                         UnsafeError (ec.Report, loc);
1064                 }
1065
1066                 public static void UnsafeError (Report Report, Location loc)
1067                 {
1068                         Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
1069                 }
1070
1071                 //
1072                 // Load the object from the pointer.  
1073                 //
1074                 public static void LoadFromPtr (ILGenerator ig, Type t)
1075                 {
1076                         if (t == TypeManager.int32_type)
1077                                 ig.Emit (OpCodes.Ldind_I4);
1078                         else if (t == TypeManager.uint32_type)
1079                                 ig.Emit (OpCodes.Ldind_U4);
1080                         else if (t == TypeManager.short_type)
1081                                 ig.Emit (OpCodes.Ldind_I2);
1082                         else if (t == TypeManager.ushort_type)
1083                                 ig.Emit (OpCodes.Ldind_U2);
1084                         else if (t == TypeManager.char_type)
1085                                 ig.Emit (OpCodes.Ldind_U2);
1086                         else if (t == TypeManager.byte_type)
1087                                 ig.Emit (OpCodes.Ldind_U1);
1088                         else if (t == TypeManager.sbyte_type)
1089                                 ig.Emit (OpCodes.Ldind_I1);
1090                         else if (t == TypeManager.uint64_type)
1091                                 ig.Emit (OpCodes.Ldind_I8);
1092                         else if (t == TypeManager.int64_type)
1093                                 ig.Emit (OpCodes.Ldind_I8);
1094                         else if (t == TypeManager.float_type)
1095                                 ig.Emit (OpCodes.Ldind_R4);
1096                         else if (t == TypeManager.double_type)
1097                                 ig.Emit (OpCodes.Ldind_R8);
1098                         else if (t == TypeManager.bool_type)
1099                                 ig.Emit (OpCodes.Ldind_I1);
1100                         else if (t == TypeManager.intptr_type)
1101                                 ig.Emit (OpCodes.Ldind_I);
1102                         else if (TypeManager.IsEnumType (t)) {
1103                                 if (t == TypeManager.enum_type)
1104                                         ig.Emit (OpCodes.Ldind_Ref);
1105                                 else
1106                                         LoadFromPtr (ig, TypeManager.GetEnumUnderlyingType (t));
1107                         } else if (TypeManager.IsStruct (t) || TypeManager.IsGenericParameter (t))
1108                                 ig.Emit (OpCodes.Ldobj, t);
1109                         else if (t.IsPointer)
1110                                 ig.Emit (OpCodes.Ldind_I);
1111                         else
1112                                 ig.Emit (OpCodes.Ldind_Ref);
1113                 }
1114
1115                 //
1116                 // The stack contains the pointer and the value of type `type'
1117                 //
1118                 public static void StoreFromPtr (ILGenerator ig, Type type)
1119                 {
1120                         if (TypeManager.IsEnumType (type))
1121                                 type = TypeManager.GetEnumUnderlyingType (type);
1122                         if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
1123                                 ig.Emit (OpCodes.Stind_I4);
1124                         else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
1125                                 ig.Emit (OpCodes.Stind_I8);
1126                         else if (type == TypeManager.char_type || type == TypeManager.short_type ||
1127                                  type == TypeManager.ushort_type)
1128                                 ig.Emit (OpCodes.Stind_I2);
1129                         else if (type == TypeManager.float_type)
1130                                 ig.Emit (OpCodes.Stind_R4);
1131                         else if (type == TypeManager.double_type)
1132                                 ig.Emit (OpCodes.Stind_R8);
1133                         else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
1134                                  type == TypeManager.bool_type)
1135                                 ig.Emit (OpCodes.Stind_I1);
1136                         else if (type == TypeManager.intptr_type)
1137                                 ig.Emit (OpCodes.Stind_I);
1138                         else if (TypeManager.IsStruct (type) || TypeManager.IsGenericParameter (type))
1139                                 ig.Emit (OpCodes.Stobj, type);
1140                         else
1141                                 ig.Emit (OpCodes.Stind_Ref);
1142                 }
1143                 
1144                 //
1145                 // Returns the size of type `t' if known, otherwise, 0
1146                 //
1147                 public static int GetTypeSize (Type t)
1148                 {
1149                         t = TypeManager.TypeToCoreType (t);
1150                         if (t == TypeManager.int32_type ||
1151                             t == TypeManager.uint32_type ||
1152                             t == TypeManager.float_type)
1153                                 return 4;
1154                         else if (t == TypeManager.int64_type ||
1155                                  t == TypeManager.uint64_type ||
1156                                  t == TypeManager.double_type)
1157                                 return 8;
1158                         else if (t == TypeManager.byte_type ||
1159                                  t == TypeManager.sbyte_type ||
1160                                  t == TypeManager.bool_type)    
1161                                 return 1;
1162                         else if (t == TypeManager.short_type ||
1163                                  t == TypeManager.char_type ||
1164                                  t == TypeManager.ushort_type)
1165                                 return 2;
1166                         else if (t == TypeManager.decimal_type)
1167                                 return 16;
1168                         else
1169                                 return 0;
1170                 }
1171
1172                 protected void Error_CannotCallAbstractBase (ResolveContext ec, string name)
1173                 {
1174                         ec.Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
1175                 }
1176                 
1177                 protected void Error_CannotModifyIntermediateExpressionValue (ResolveContext ec)
1178                 {
1179                         ec.Report.SymbolRelatedToPreviousError (type);
1180                         if (ec.CurrentInitializerVariable != null) {
1181                                 ec.Report.Error (1918, loc, "Members of value type `{0}' cannot be assigned using a property `{1}' object initializer",
1182                                         TypeManager.CSharpName (type), GetSignatureForError ());
1183                         } else {
1184                                 ec.Report.Error (1612, loc, "Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable",
1185                                         GetSignatureForError ());
1186                         }
1187                 }
1188
1189                 //
1190                 // Converts `source' to an int, uint, long or ulong.
1191                 //
1192                 protected Expression ConvertExpressionToArrayIndex (ResolveContext ec, Expression source)
1193                 {
1194                         if (TypeManager.IsDynamicType (source.type)) {
1195                                 Arguments args = new Arguments (1);
1196                                 args.Add (new Argument (source));
1197                                 return new DynamicConversion (TypeManager.int32_type, CSharpBinderFlags.ConvertArrayIndex, args, loc).Resolve (ec);
1198                         }
1199
1200                         Expression converted;
1201                         
1202                         using (ec.Set (ResolveContext.Options.CheckedScope)) {
1203                                 converted = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, source.loc);
1204                                 if (converted == null)
1205                                         converted = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, source.loc);
1206                                 if (converted == null)
1207                                         converted = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, source.loc);
1208                                 if (converted == null)
1209                                         converted = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, source.loc);
1210
1211                                 if (converted == null) {
1212                                         source.Error_ValueCannotBeConverted (ec, source.loc, TypeManager.int32_type, false);
1213                                         return null;
1214                                 }
1215                         }
1216
1217                         //
1218                         // Only positive constants are allowed at compile time
1219                         //
1220                         Constant c = converted as Constant;
1221                         if (c != null && c.IsNegative)
1222                                 Error_NegativeArrayIndex (ec, source.loc);
1223
1224                         // No conversion needed to array index
1225                         if (converted.Type == TypeManager.int32_type)
1226                                 return converted;
1227
1228                         return new ArrayIndexCast (converted).Resolve (ec);
1229                 }
1230
1231                 //
1232                 // Derived classes implement this method by cloning the fields that
1233                 // could become altered during the Resolve stage
1234                 //
1235                 // Only expressions that are created for the parser need to implement
1236                 // this.
1237                 //
1238                 protected virtual void CloneTo (CloneContext clonectx, Expression target)
1239                 {
1240                         throw new NotImplementedException (
1241                                 String.Format (
1242                                         "CloneTo not implemented for expression {0}", this.GetType ()));
1243                 }
1244
1245                 //
1246                 // Clones an expression created by the parser.
1247                 //
1248                 // We only support expressions created by the parser so far, not
1249                 // expressions that have been resolved (many more classes would need
1250                 // to implement CloneTo).
1251                 //
1252                 // This infrastructure is here merely for Lambda expressions which
1253                 // compile the same code using different type values for the same
1254                 // arguments to find the correct overload
1255                 //
1256                 public Expression Clone (CloneContext clonectx)
1257                 {
1258                         Expression cloned = (Expression) MemberwiseClone ();
1259                         CloneTo (clonectx, cloned);
1260
1261                         return cloned;
1262                 }
1263
1264                 //
1265                 // Implementation of expression to expression tree conversion
1266                 //
1267                 public abstract Expression CreateExpressionTree (ResolveContext ec);
1268
1269                 protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, Arguments args)
1270                 {
1271                         return CreateExpressionFactoryCall (ec, name, null, args, loc);
1272                 }
1273
1274                 protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args)
1275                 {
1276                         return CreateExpressionFactoryCall (ec, name, typeArguments, args, loc);
1277                 }
1278
1279                 public static Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args, Location loc)
1280                 {
1281                         return new Invocation (new MemberAccess (CreateExpressionTypeExpression (ec, loc), name, typeArguments, loc), args);
1282                 }
1283
1284                 protected static TypeExpr CreateExpressionTypeExpression (ResolveContext ec, Location loc)
1285                 {
1286                         TypeExpr texpr = TypeManager.expression_type_expr;
1287                         if (texpr == null) {
1288                                 Type t = TypeManager.CoreLookupType (ec.Compiler, "System.Linq.Expressions", "Expression", Kind.Class, true);
1289                                 if (t == null)
1290                                         return null;
1291
1292                                 TypeManager.expression_type_expr = texpr = new TypeExpression (t, Location.Null);
1293                         }
1294
1295                         return texpr;
1296                 }
1297
1298 #if NET_4_0
1299                 //
1300                 // Implemented by all expressions which support conversion from
1301                 // compiler expression to invokable runtime expression. Used by
1302                 // dynamic C# binder.
1303                 //
1304                 public virtual SLE.Expression MakeExpression (BuilderContext ctx)
1305                 {
1306                         throw new NotImplementedException ("MakeExpression for " + GetType ());
1307                 }
1308 #endif
1309
1310                 public virtual void MutateHoistedGenericType (AnonymousMethodStorey storey)
1311                 {
1312                         // TODO: It should probably be type = storey.MutateType (type);
1313                 }
1314         }
1315
1316         /// <summary>
1317         ///   This is just a base class for expressions that can
1318         ///   appear on statements (invocations, object creation,
1319         ///   assignments, post/pre increment and decrement).  The idea
1320         ///   being that they would support an extra Emition interface that
1321         ///   does not leave a result on the stack.
1322         /// </summary>
1323         public abstract class ExpressionStatement : Expression {
1324
1325                 public virtual ExpressionStatement ResolveStatement (BlockContext ec)
1326                 {
1327                         Expression e = Resolve (ec);
1328                         if (e == null)
1329                                 return null;
1330
1331                         ExpressionStatement es = e as ExpressionStatement;
1332                         if (es == null)
1333                                 Error_InvalidExpressionStatement (ec);
1334
1335                         return es;
1336                 }
1337
1338                 /// <summary>
1339                 ///   Requests the expression to be emitted in a `statement'
1340                 ///   context.  This means that no new value is left on the
1341                 ///   stack after invoking this method (constrasted with
1342                 ///   Emit that will always leave a value on the stack).
1343                 /// </summary>
1344                 public abstract void EmitStatement (EmitContext ec);
1345
1346                 public override void EmitSideEffect (EmitContext ec)
1347                 {
1348                         EmitStatement (ec);
1349                 }
1350         }
1351
1352         /// <summary>
1353         ///   This kind of cast is used to encapsulate the child
1354         ///   whose type is child.Type into an expression that is
1355         ///   reported to return "return_type".  This is used to encapsulate
1356         ///   expressions which have compatible types, but need to be dealt
1357         ///   at higher levels with.
1358         ///
1359         ///   For example, a "byte" expression could be encapsulated in one
1360         ///   of these as an "unsigned int".  The type for the expression
1361         ///   would be "unsigned int".
1362         ///
1363         /// </summary>
1364         public abstract class TypeCast : Expression
1365         {
1366                 protected readonly Expression child;
1367
1368                 protected TypeCast (Expression child, Type return_type)
1369                 {
1370                         eclass = child.eclass;
1371                         loc = child.Location;
1372                         type = return_type;
1373                         this.child = child;
1374                 }
1375
1376                 public override Expression CreateExpressionTree (ResolveContext ec)
1377                 {
1378                         Arguments args = new Arguments (2);
1379                         args.Add (new Argument (child.CreateExpressionTree (ec)));
1380                         args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
1381
1382                         if (type.IsPointer || child.Type.IsPointer)
1383                                 Error_PointerInsideExpressionTree (ec);
1384
1385                         return CreateExpressionFactoryCall (ec, ec.HasSet (ResolveContext.Options.CheckedScope) ? "ConvertChecked" : "Convert", args);
1386                 }
1387
1388                 public override Expression DoResolve (ResolveContext ec)
1389                 {
1390                         // This should never be invoked, we are born in fully
1391                         // initialized state.
1392
1393                         return this;
1394                 }
1395
1396                 public override void Emit (EmitContext ec)
1397                 {
1398                         child.Emit (ec);
1399                 }
1400
1401                 public override bool GetAttributableValue (ResolveContext ec, Type value_type, out object value)
1402                 {
1403                         return child.GetAttributableValue (ec, value_type, out value);
1404                 }
1405
1406 #if NET_4_0
1407                 public override SLE.Expression MakeExpression (BuilderContext ctx)
1408                 {
1409                         return ctx.HasSet (BuilderContext.Options.CheckedScope) ?
1410                                 SLE.Expression.ConvertChecked (child.MakeExpression (ctx), type) :
1411                                 SLE.Expression.Convert (child.MakeExpression (ctx), type);
1412                 }
1413 #endif
1414
1415                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
1416                 {
1417                         type = storey.MutateType (type);
1418                         child.MutateHoistedGenericType (storey);
1419                 }
1420
1421                 protected override void CloneTo (CloneContext clonectx, Expression t)
1422                 {
1423                         // Nothing to clone
1424                 }
1425
1426                 public override bool IsNull {
1427                         get { return child.IsNull; }
1428                 }
1429         }
1430
1431         public class EmptyCast : TypeCast {
1432                 EmptyCast (Expression child, Type target_type)
1433                         : base (child, target_type)
1434                 {
1435                 }
1436
1437                 public static Expression Create (Expression child, Type type)
1438                 {
1439                         Constant c = child as Constant;
1440                         if (c != null)
1441                                 return new EmptyConstantCast (c, type);
1442
1443                         EmptyCast e = child as EmptyCast;
1444                         if (e != null)
1445                                 return new EmptyCast (e.child, type);
1446
1447                         return new EmptyCast (child, type);
1448                 }
1449
1450                 public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
1451                 {
1452                         child.EmitBranchable (ec, label, on_true);
1453                 }
1454
1455                 public override void EmitSideEffect (EmitContext ec)
1456                 {
1457                         child.EmitSideEffect (ec);
1458                 }
1459         }
1460
1461         //
1462         // Used for predefined class library user casts (no obsolete check, etc.)
1463         //
1464         public class OperatorCast : TypeCast {
1465                 MethodInfo conversion_operator;
1466                         
1467                 public OperatorCast (Expression child, Type target_type) 
1468                         : this (child, target_type, false)
1469                 {
1470                 }
1471
1472                 public OperatorCast (Expression child, Type target_type, bool find_explicit)
1473                         : base (child, target_type)
1474                 {
1475                         conversion_operator = GetConversionOperator (find_explicit);
1476                         if (conversion_operator == null)
1477                                 throw new InternalErrorException ("Outer conversion routine is out of sync");
1478                 }
1479
1480                 // Returns the implicit operator that converts from
1481                 // 'child.Type' to our target type (type)
1482                 MethodInfo GetConversionOperator (bool find_explicit)
1483                 {
1484                         string operator_name = find_explicit ? "op_Explicit" : "op_Implicit";
1485
1486                         MemberInfo [] mi;
1487
1488                         mi = TypeManager.MemberLookup (child.Type, child.Type, child.Type, MemberTypes.Method,
1489                                 BindingFlags.Static | BindingFlags.Public, operator_name, null);
1490
1491                         if (mi == null){
1492                                 mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method,
1493                                                                BindingFlags.Static | BindingFlags.Public, operator_name, null);
1494                         }
1495                         
1496                         foreach (MethodInfo oper in mi) {
1497                                 AParametersCollection pd = TypeManager.GetParameterData (oper);
1498
1499                                 if (pd.Types [0] == child.Type && TypeManager.TypeToCoreType (oper.ReturnType) == type)
1500                                         return oper;
1501                         }
1502
1503                         return null;
1504                 }
1505
1506                 public override void Emit (EmitContext ec)
1507                 {
1508                         child.Emit (ec);
1509                         ec.ig.Emit (OpCodes.Call, conversion_operator);
1510                 }
1511         }
1512         
1513         /// <summary>
1514         ///     This is a numeric cast to a Decimal
1515         /// </summary>
1516         public class CastToDecimal : OperatorCast {
1517                 public CastToDecimal (Expression child)
1518                         : this (child, false)
1519                 {
1520                 }
1521
1522                 public CastToDecimal (Expression child, bool find_explicit)
1523                         : base (child, TypeManager.decimal_type, find_explicit)
1524                 {
1525                 }
1526         }
1527
1528         /// <summary>
1529         ///     This is an explicit numeric cast from a Decimal
1530         /// </summary>
1531         public class CastFromDecimal : TypeCast
1532         {
1533                 static IDictionary operators;
1534
1535                 public CastFromDecimal (Expression child, Type return_type)
1536                         : base (child, return_type)
1537                 {
1538                         if (child.Type != TypeManager.decimal_type)
1539                                 throw new InternalErrorException (
1540                                         "The expected type is Decimal, instead it is " + child.Type.FullName);
1541                 }
1542
1543                 // Returns the explicit operator that converts from an
1544                 // express of type System.Decimal to 'type'.
1545                 public Expression Resolve ()
1546                 {
1547                         if (operators == null) {
1548                                  MemberInfo[] all_oper = TypeManager.MemberLookup (TypeManager.decimal_type,
1549                                         TypeManager.decimal_type, TypeManager.decimal_type, MemberTypes.Method,
1550                                         BindingFlags.Static | BindingFlags.Public, "op_Explicit", null);
1551
1552                                 operators = new System.Collections.Specialized.HybridDictionary ();
1553                                 foreach (MethodInfo oper in all_oper) {
1554                                         AParametersCollection pd = TypeManager.GetParameterData (oper);
1555                                         if (pd.Types [0] == TypeManager.decimal_type)
1556                                                 operators.Add (TypeManager.TypeToCoreType (oper.ReturnType), oper);
1557                                 }
1558                         }
1559
1560                         return operators.Contains (type) ? this : null;
1561                 }
1562
1563                 public override void Emit (EmitContext ec)
1564                 {
1565                         ILGenerator ig = ec.ig;
1566                         child.Emit (ec);
1567
1568                         ig.Emit (OpCodes.Call, (MethodInfo)operators [type]);
1569                 }
1570         }
1571
1572         
1573         //
1574         // Constant specialization of EmptyCast.
1575         // We need to special case this since an empty cast of
1576         // a constant is still a constant. 
1577         //
1578         public class EmptyConstantCast : Constant
1579         {
1580                 public readonly Constant child;
1581
1582                 public EmptyConstantCast(Constant child, Type type)
1583                         : base (child.Location)
1584                 {
1585                         eclass = child.eclass;
1586                         this.child = child;
1587                         this.type = type;
1588                 }
1589
1590                 public override string AsString ()
1591                 {
1592                         return child.AsString ();
1593                 }
1594
1595                 public override object GetValue ()
1596                 {
1597                         return child.GetValue ();
1598                 }
1599
1600                 public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
1601                 {
1602                         // FIXME: check that 'type' can be converted to 'target_type' first
1603                         return child.ConvertExplicitly (in_checked_context, target_type);
1604                 }
1605
1606                 public override Expression CreateExpressionTree (ResolveContext ec)
1607                 {
1608                         Arguments args = Arguments.CreateForExpressionTree (ec, null,
1609                                 child.CreateExpressionTree (ec),
1610                                 new TypeOf (new TypeExpression (type, loc), loc));
1611
1612                         if (type.IsPointer)
1613                                 Error_PointerInsideExpressionTree (ec);
1614
1615                         return CreateExpressionFactoryCall (ec, "Convert", args);
1616                 }
1617
1618                 public override Constant Increment ()
1619                 {
1620                         return child.Increment ();
1621                 }
1622
1623                 public override bool IsDefaultValue {
1624                         get { return child.IsDefaultValue; }
1625                 }
1626
1627                 public override bool IsNegative {
1628                         get { return child.IsNegative; }
1629                 }
1630
1631                 public override bool IsNull {
1632                         get { return child.IsNull; }
1633                 }
1634
1635                 public override bool IsZeroInteger {
1636                         get { return child.IsZeroInteger; }
1637                 }
1638                 
1639                 public override void Emit (EmitContext ec)
1640                 {
1641                         child.Emit (ec);                        
1642                 }
1643
1644                 public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
1645                 {
1646                         child.EmitBranchable (ec, label, on_true);
1647
1648                         // Only to make verifier happy
1649                         if (TypeManager.IsGenericParameter (type) && child.IsNull)
1650                                 ec.ig.Emit (OpCodes.Unbox_Any, type);
1651                 }
1652
1653                 public override void EmitSideEffect (EmitContext ec)
1654                 {
1655                         child.EmitSideEffect (ec);
1656                 }
1657
1658                 public override Constant ConvertImplicitly (Type target_type)
1659                 {
1660                         // FIXME: Do we need to check user conversions?
1661                         if (!Convert.ImplicitStandardConversionExists (this, target_type))
1662                                 return null;
1663                         return child.ConvertImplicitly (target_type);
1664                 }
1665
1666                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
1667                 {
1668                         child.MutateHoistedGenericType (storey);
1669                 }
1670         }
1671
1672
1673         /// <summary>
1674         ///  This class is used to wrap literals which belong inside Enums
1675         /// </summary>
1676         public class EnumConstant : Constant {
1677                 public Constant Child;
1678
1679                 public EnumConstant (Constant child, Type enum_type):
1680                         base (child.Location)
1681                 {
1682                         eclass = child.eclass;
1683                         this.Child = child;
1684                         type = enum_type;
1685                 }
1686
1687                 protected EnumConstant ()
1688                         : base (Location.Null)
1689                 {
1690                 }
1691                 
1692                 public override Expression DoResolve (ResolveContext ec)
1693                 {
1694                         // This should never be invoked, we are born in fully
1695                         // initialized state.
1696
1697                         return this;
1698                 }
1699
1700                 public override void Emit (EmitContext ec)
1701                 {
1702                         Child.Emit (ec);
1703                 }
1704
1705                 public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
1706                 {
1707                         Child.EmitBranchable (ec, label, on_true);
1708                 }
1709
1710                 public override void EmitSideEffect (EmitContext ec)
1711                 {
1712                         Child.EmitSideEffect (ec);
1713                 }
1714
1715                 public override bool GetAttributableValue (ResolveContext ec, Type value_type, out object value)
1716                 {
1717                         value = GetTypedValue ();
1718                         return true;
1719                 }
1720
1721                 public override string GetSignatureForError()
1722                 {
1723                         return TypeManager.CSharpName (Type);
1724                 }
1725
1726                 public override object GetValue ()
1727                 {
1728                         return Child.GetValue ();
1729                 }
1730
1731                 public override object GetTypedValue ()
1732                 {
1733                         // FIXME: runtime is not ready to work with just emited enums
1734                         if (!RootContext.StdLib) {
1735                                 return Child.GetValue ();
1736                         }
1737
1738 #if MS_COMPATIBLE
1739                         // Small workaround for big problem
1740                         // System.Enum.ToObject cannot be called on dynamic types
1741                         // EnumBuilder has to be used, but we cannot use EnumBuilder
1742                         // because it does not properly support generics
1743                         //
1744                         // This works only sometimes
1745                         //
1746                         if (TypeManager.IsBeingCompiled (type))
1747                                 return Child.GetValue ();
1748 #endif
1749
1750                         return System.Enum.ToObject (type, Child.GetValue ());
1751                 }
1752                 
1753                 public override string AsString ()
1754                 {
1755                         return Child.AsString ();
1756                 }
1757
1758                 public override Constant Increment()
1759                 {
1760                         return new EnumConstant (Child.Increment (), type);
1761                 }
1762
1763                 public override bool IsDefaultValue {
1764                         get {
1765                                 return Child.IsDefaultValue;
1766                         }
1767                 }
1768
1769                 public override bool IsZeroInteger {
1770                         get { return Child.IsZeroInteger; }
1771                 }
1772
1773                 public override bool IsNegative {
1774                         get {
1775                                 return Child.IsNegative;
1776                         }
1777                 }
1778
1779                 public override Constant ConvertExplicitly(bool in_checked_context, Type target_type)
1780                 {
1781                         if (Child.Type == target_type)
1782                                 return Child;
1783
1784                         return Child.ConvertExplicitly (in_checked_context, target_type);
1785                 }
1786
1787                 public override Constant ConvertImplicitly (Type type)
1788                 {
1789                         Type this_type = TypeManager.DropGenericTypeArguments (Type);
1790                         type = TypeManager.DropGenericTypeArguments (type);
1791
1792                         if (this_type == type) {
1793                                 // This is workaround of mono bug. It can be removed when the latest corlib spreads enough
1794                                 if (TypeManager.IsEnumType (type.UnderlyingSystemType))
1795                                         return this;
1796
1797                                 Type child_type = TypeManager.DropGenericTypeArguments (Child.Type);
1798                                 if (type.UnderlyingSystemType != child_type)
1799                                         Child = Child.ConvertImplicitly (type.UnderlyingSystemType);
1800                                 return this;
1801                         }
1802
1803                         if (!Convert.ImplicitStandardConversionExists (this, type)){
1804                                 return null;
1805                         }
1806
1807                         return Child.ConvertImplicitly(type);
1808                 }
1809
1810         }
1811
1812         /// <summary>
1813         ///   This kind of cast is used to encapsulate Value Types in objects.
1814         ///
1815         ///   The effect of it is to box the value type emitted by the previous
1816         ///   operation.
1817         /// </summary>
1818         public class BoxedCast : TypeCast {
1819
1820                 public BoxedCast (Expression expr, Type target_type)
1821                         : base (expr, target_type)
1822                 {
1823                         eclass = ExprClass.Value;
1824                 }
1825                 
1826                 public override Expression DoResolve (ResolveContext ec)
1827                 {
1828                         // This should never be invoked, we are born in fully
1829                         // initialized state.
1830
1831                         return this;
1832                 }
1833
1834                 public override void Emit (EmitContext ec)
1835                 {
1836                         base.Emit (ec);
1837                         
1838                         ec.ig.Emit (OpCodes.Box, child.Type);
1839                 }
1840
1841                 public override void EmitSideEffect (EmitContext ec)
1842                 {
1843                         // boxing is side-effectful, since it involves runtime checks, except when boxing to Object or ValueType
1844                         // so, we need to emit the box+pop instructions in most cases
1845                         if (TypeManager.IsStruct (child.Type) &&
1846                             (type == TypeManager.object_type || type == TypeManager.value_type))
1847                                 child.EmitSideEffect (ec);
1848                         else
1849                                 base.EmitSideEffect (ec);
1850                 }
1851         }
1852
1853         public class UnboxCast : TypeCast {
1854                 public UnboxCast (Expression expr, Type return_type)
1855                         : base (expr, return_type)
1856                 {
1857                 }
1858
1859                 public override Expression DoResolve (ResolveContext ec)
1860                 {
1861                         // This should never be invoked, we are born in fully
1862                         // initialized state.
1863
1864                         return this;
1865                 }
1866
1867                 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
1868                 {
1869                         if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess)
1870                                 ec.Report.Error (445, loc, "Cannot modify the result of an unboxing conversion");
1871                         return base.DoResolveLValue (ec, right_side);
1872                 }
1873
1874                 public override void Emit (EmitContext ec)
1875                 {
1876                         base.Emit (ec);
1877
1878                         ILGenerator ig = ec.ig;
1879                         ig.Emit (OpCodes.Unbox_Any, type);
1880                 }
1881
1882                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
1883                 {
1884                         type = storey.MutateType (type);
1885                         base.MutateHoistedGenericType (storey);                 
1886                 }
1887         }
1888         
1889         /// <summary>
1890         ///   This is used to perform explicit numeric conversions.
1891         ///
1892         ///   Explicit numeric conversions might trigger exceptions in a checked
1893         ///   context, so they should generate the conv.ovf opcodes instead of
1894         ///   conv opcodes.
1895         /// </summary>
1896         public class ConvCast : TypeCast {
1897                 public enum Mode : byte {
1898                         I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
1899                         U1_I1, U1_CH,
1900                         I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
1901                         U2_I1, U2_U1, U2_I2, U2_CH,
1902                         I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
1903                         U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
1904                         I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH, I8_I,
1905                         U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH, U8_I,
1906                         CH_I1, CH_U1, CH_I2,
1907                         R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
1908                         R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4,
1909                         I_I8,
1910                 }
1911
1912                 Mode mode;
1913                 
1914                 public ConvCast (Expression child, Type return_type, Mode m)
1915                         : base (child, return_type)
1916                 {
1917                         mode = m;
1918                 }
1919
1920                 public override Expression DoResolve (ResolveContext ec)
1921                 {
1922                         // This should never be invoked, we are born in fully
1923                         // initialized state.
1924
1925                         return this;
1926                 }
1927
1928                 public override string ToString ()
1929                 {
1930                         return String.Format ("ConvCast ({0}, {1})", mode, child);
1931                 }
1932                 
1933                 public override void Emit (EmitContext ec)
1934                 {
1935                         ILGenerator ig = ec.ig;
1936                         
1937                         base.Emit (ec);
1938
1939                         if (ec.HasSet (EmitContext.Options.CheckedScope)) {
1940                                 switch (mode){
1941                                 case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1942                                 case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1943                                 case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1944                                 case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1945                                 case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1946
1947                                 case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1948                                 case Mode.U1_CH: /* nothing */ break;
1949
1950                                 case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1951                                 case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1952                                 case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1953                                 case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1954                                 case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1955                                 case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1956
1957                                 case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1958                                 case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1959                                 case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1960                                 case Mode.U2_CH: /* nothing */ break;
1961
1962                                 case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1963                                 case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1964                                 case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1965                                 case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1966                                 case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1967                                 case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1968                                 case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1969
1970                                 case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1971                                 case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1972                                 case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1973                                 case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1974                                 case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1975                                 case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1976
1977                                 case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1978                                 case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1979                                 case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1980                                 case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1981                                 case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1982                                 case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1983                                 case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1984                                 case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1985                                 case Mode.I8_I: ig.Emit (OpCodes.Conv_Ovf_U); break;
1986
1987                                 case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1988                                 case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1989                                 case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1990                                 case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1991                                 case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1992                                 case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break;
1993                                 case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
1994                                 case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1995                                 case Mode.U8_I: ig.Emit (OpCodes.Conv_Ovf_U_Un); break;
1996
1997                                 case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1998                                 case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1999                                 case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
2000
2001                                 case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
2002                                 case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
2003                                 case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
2004                                 case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2005                                 case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
2006                                 case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
2007                                 case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
2008                                 case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
2009                                 case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2010
2011                                 case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
2012                                 case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
2013                                 case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
2014                                 case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2015                                 case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
2016                                 case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
2017                                 case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
2018                                 case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
2019                                 case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2020                                 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
2021
2022                                 case Mode.I_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
2023                                 }
2024                         } else {
2025                                 switch (mode){
2026                                 case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break;
2027                                 case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break;
2028                                 case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break;
2029                                 case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break;
2030                                 case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break;
2031
2032                                 case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break;
2033                                 case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break;
2034
2035                                 case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break;
2036                                 case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break;
2037                                 case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break;
2038                                 case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break;
2039                                 case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break;
2040                                 case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break;
2041
2042                                 case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break;
2043                                 case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break;
2044                                 case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break;
2045                                 case Mode.U2_CH: /* nothing */ break;
2046
2047                                 case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break;
2048                                 case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break;
2049                                 case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break;
2050                                 case Mode.I4_U4: /* nothing */ break;
2051                                 case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break;
2052                                 case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break;
2053                                 case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break;
2054
2055                                 case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break;
2056                                 case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break;
2057                                 case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break;
2058                                 case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break;
2059                                 case Mode.U4_I4: /* nothing */ break;
2060                                 case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break;
2061
2062                                 case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break;
2063                                 case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break;
2064                                 case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break;
2065                                 case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break;
2066                                 case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break;
2067                                 case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break;
2068                                 case Mode.I8_U8: /* nothing */ break;
2069                                 case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break;
2070                                 case Mode.I8_I: ig.Emit (OpCodes.Conv_U); break;
2071
2072                                 case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break;
2073                                 case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break;
2074                                 case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break;
2075                                 case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break;
2076                                 case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break;
2077                                 case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break;
2078                                 case Mode.U8_I8: /* nothing */ break;
2079                                 case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break;
2080                                 case Mode.U8_I: ig.Emit (OpCodes.Conv_U); break;
2081
2082                                 case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break;
2083                                 case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break;
2084                                 case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break;
2085
2086                                 case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break;
2087                                 case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break;
2088                                 case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break;
2089                                 case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break;
2090                                 case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break;
2091                                 case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break;
2092                                 case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break;
2093                                 case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break;
2094                                 case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break;
2095
2096                                 case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break;
2097                                 case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break;
2098                                 case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break;
2099                                 case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break;
2100                                 case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break;
2101                                 case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break;
2102                                 case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break;
2103                                 case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break;
2104                                 case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break;
2105                                 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
2106
2107                                 case Mode.I_I8: ig.Emit (OpCodes.Conv_U8); break;
2108                                 }
2109                         }
2110                 }
2111         }
2112         
2113         public class OpcodeCast : TypeCast {
2114                 readonly OpCode op;
2115                 
2116                 public OpcodeCast (Expression child, Type return_type, OpCode op)
2117                         : base (child, return_type)
2118                 {
2119                         this.op = op;
2120                 }
2121
2122                 public override Expression DoResolve (ResolveContext ec)
2123                 {
2124                         // This should never be invoked, we are born in fully
2125                         // initialized state.
2126
2127                         return this;
2128                 }
2129
2130                 public override void Emit (EmitContext ec)
2131                 {
2132                         base.Emit (ec);
2133                         ec.ig.Emit (op);
2134                 }
2135
2136                 public Type UnderlyingType {
2137                         get { return child.Type; }
2138                 }
2139         }
2140
2141         /// <summary>
2142         ///   This kind of cast is used to encapsulate a child and cast it
2143         ///   to the class requested
2144         /// </summary>
2145         public sealed class ClassCast : TypeCast {
2146                 readonly bool forced;
2147                 
2148                 public ClassCast (Expression child, Type return_type)
2149                         : base (child, return_type)
2150                 {
2151                 }
2152                 
2153                 public ClassCast (Expression child, Type return_type, bool forced)
2154                         : base (child, return_type)
2155                 {
2156                         this.forced = forced;
2157                 }
2158
2159                 public override void Emit (EmitContext ec)
2160                 {
2161                         base.Emit (ec);
2162
2163                         bool gen = TypeManager.IsGenericParameter (child.Type);
2164                         if (gen)
2165                                 ec.ig.Emit (OpCodes.Box, child.Type);
2166                         
2167                         if (type.IsGenericParameter) {
2168                                 ec.ig.Emit (OpCodes.Unbox_Any, type);
2169                                 return;
2170                         }
2171                         
2172                         if (gen && !forced)
2173                                 return;
2174                         
2175                         ec.ig.Emit (OpCodes.Castclass, type);
2176                 }
2177         }
2178
2179         //
2180         // Created during resolving pahse when an expression is wrapped or constantified
2181         // and original expression can be used later (e.g. for expression trees)
2182         //
2183         public class ReducedExpression : Expression
2184         {
2185                 sealed class ReducedConstantExpression : EmptyConstantCast
2186                 {
2187                         readonly Expression orig_expr;
2188
2189                         public ReducedConstantExpression (Constant expr, Expression orig_expr)
2190                                 : base (expr, expr.Type)
2191                         {
2192                                 this.orig_expr = orig_expr;
2193                         }
2194
2195                         public override Constant ConvertImplicitly (Type target_type)
2196                         {
2197                                 Constant c = base.ConvertImplicitly (target_type);
2198                                 if (c != null)
2199                                         c = new ReducedConstantExpression (c, orig_expr);
2200                                 return c;
2201                         }
2202
2203                         public override Expression CreateExpressionTree (ResolveContext ec)
2204                         {
2205                                 return orig_expr.CreateExpressionTree (ec);
2206                         }
2207
2208                         public override bool GetAttributableValue (ResolveContext ec, Type value_type, out object value)
2209                         {
2210                                 //
2211                                 // Even if resolved result is a constant original expression was not
2212                                 // and attribute accepts constants only
2213                                 //
2214                                 Attribute.Error_AttributeArgumentNotValid (ec, orig_expr.Location);
2215                                 value = null;
2216                                 return false;
2217                         }
2218
2219                         public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
2220                         {
2221                                 Constant c = base.ConvertExplicitly (in_checked_context, target_type);
2222                                 if (c != null)
2223                                         c = new ReducedConstantExpression (c, orig_expr);
2224                                 return c;
2225                         }
2226                 }
2227
2228                 sealed class ReducedExpressionStatement : ExpressionStatement
2229                 {
2230                         readonly Expression orig_expr;
2231                         readonly ExpressionStatement stm;
2232
2233                         public ReducedExpressionStatement (ExpressionStatement stm, Expression orig)
2234                         {
2235                                 this.orig_expr = orig;
2236                                 this.stm = stm;
2237                                 this.loc = orig.Location;
2238                         }
2239
2240                         public override Expression CreateExpressionTree (ResolveContext ec)
2241                         {
2242                                 return orig_expr.CreateExpressionTree (ec);
2243                         }
2244
2245                         public override Expression DoResolve (ResolveContext ec)
2246                         {
2247                                 eclass = stm.eclass;
2248                                 type = stm.Type;
2249                                 return this;
2250                         }
2251
2252                         public override void Emit (EmitContext ec)
2253                         {
2254                                 stm.Emit (ec);
2255                         }
2256
2257                         public override void EmitStatement (EmitContext ec)
2258                         {
2259                                 stm.EmitStatement (ec);
2260                         }
2261
2262                         public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
2263                         {
2264                                 stm.MutateHoistedGenericType (storey);
2265                         }
2266                 }
2267
2268                 readonly Expression expr, orig_expr;
2269
2270                 private ReducedExpression (Expression expr, Expression orig_expr)
2271                 {
2272                         this.expr = expr;
2273                         this.orig_expr = orig_expr;
2274                         this.loc = orig_expr.Location;
2275                 }
2276
2277                 public static Constant Create (Constant expr, Expression original_expr)
2278                 {
2279                         return new ReducedConstantExpression (expr, original_expr);
2280                 }
2281
2282                 public static ExpressionStatement Create (ExpressionStatement s, Expression orig)
2283                 {
2284                         return new ReducedExpressionStatement (s, orig);
2285                 }
2286
2287                 public static Expression Create (Expression expr, Expression original_expr)
2288                 {
2289                         Constant c = expr as Constant;
2290                         if (c != null)
2291                                 return Create (c, original_expr);
2292
2293                         ExpressionStatement s = expr as ExpressionStatement;
2294                         if (s != null)
2295                                 return Create (s, original_expr);
2296
2297                         return new ReducedExpression (expr, original_expr);
2298                 }
2299
2300                 public override Expression CreateExpressionTree (ResolveContext ec)
2301                 {
2302                         return orig_expr.CreateExpressionTree (ec);
2303                 }
2304
2305                 public override Expression DoResolve (ResolveContext ec)
2306                 {
2307                         eclass = expr.eclass;
2308                         type = expr.Type;
2309                         return this;
2310                 }
2311
2312                 public override void Emit (EmitContext ec)
2313                 {
2314                         expr.Emit (ec);
2315                 }
2316
2317                 public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
2318                 {
2319                         expr.EmitBranchable (ec, target, on_true);
2320                 }
2321
2322 #if NET_4_0
2323                 public override SLE.Expression MakeExpression (BuilderContext ctx)
2324                 {
2325                         return orig_expr.MakeExpression (ctx);
2326                 }
2327 #endif
2328
2329                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
2330                 {
2331                         expr.MutateHoistedGenericType (storey);
2332                 }
2333         }
2334
2335         //
2336         // Standard composite pattern
2337         //
2338         public abstract class CompositeExpression : Expression
2339         {
2340                 Expression expr;
2341
2342                 protected CompositeExpression (Expression expr)
2343                 {
2344                         this.expr = expr;
2345                         this.loc = expr.Location;
2346                 }
2347
2348                 public override Expression CreateExpressionTree (ResolveContext ec)
2349                 {
2350                         return expr.CreateExpressionTree (ec);
2351                 }
2352
2353                 public Expression Child {
2354                         get { return expr; }
2355                 }
2356
2357                 public override Expression DoResolve (ResolveContext ec)
2358                 {
2359                         expr = expr.Resolve (ec);
2360                         if (expr != null) {
2361                                 type = expr.Type;
2362                                 eclass = expr.eclass;
2363                         }
2364
2365                         return this;
2366                 }
2367
2368                 public override void Emit (EmitContext ec)
2369                 {
2370                         expr.Emit (ec);
2371                 }
2372
2373                 public override bool IsNull {
2374                         get { return expr.IsNull; }
2375                 }
2376         }
2377
2378         //
2379         // Base of expressions used only to narrow resolve flow
2380         //
2381         public abstract class ShimExpression : Expression
2382         {
2383                 protected Expression expr;
2384
2385                 protected ShimExpression (Expression expr)
2386                 {
2387                         this.expr = expr;
2388                 }
2389
2390                 protected override void CloneTo (CloneContext clonectx, Expression t)
2391                 {
2392                         if (expr == null)
2393                                 return;
2394
2395                         ShimExpression target = (ShimExpression) t;
2396                         target.expr = expr.Clone (clonectx);
2397                 }
2398
2399                 public override Expression CreateExpressionTree (ResolveContext ec)
2400                 {
2401                         throw new NotSupportedException ("ET");
2402                 }
2403
2404                 public override void Emit (EmitContext ec)
2405                 {
2406                         throw new InternalErrorException ("Missing Resolve call");
2407                 }
2408
2409                 public Expression Expr {
2410                         get { return expr; }
2411                 }
2412
2413                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
2414                 {
2415                         throw new InternalErrorException ("Missing Resolve call");
2416                 }
2417         }
2418
2419         //
2420         // Unresolved type name expressions
2421         //
2422         public abstract class ATypeNameExpression : FullNamedExpression
2423         {
2424                 string name;
2425                 protected TypeArguments targs;
2426
2427                 protected ATypeNameExpression (string name, Location l)
2428                 {
2429                         this.name = name;
2430                         loc = l;
2431                 }
2432
2433                 protected ATypeNameExpression (string name, TypeArguments targs, Location l)
2434                 {
2435                         this.name = name;
2436                         this.targs = targs;
2437                         loc = l;
2438                 }
2439
2440                 public bool HasTypeArguments {
2441                         get {
2442                                 return targs != null;
2443                         }
2444                 }
2445
2446                 public override bool Equals (object obj)
2447                 {
2448                         ATypeNameExpression atne = obj as ATypeNameExpression;
2449                         return atne != null && atne.Name == Name &&
2450                                 (targs == null || targs.Equals (atne.targs));
2451                 }
2452
2453                 public override int GetHashCode ()
2454                 {
2455                         return Name.GetHashCode ();
2456                 }
2457
2458                 public override string GetSignatureForError ()
2459                 {
2460                         if (targs != null) {
2461                                 return TypeManager.RemoveGenericArity (Name) + "<" +
2462                                         targs.GetSignatureForError () + ">";
2463                         }
2464
2465                         return Name;
2466                 }
2467
2468                 public string Name {
2469                         get {
2470                                 return name;
2471                         }
2472                         set {
2473                                 name = value;
2474                         }
2475                 }
2476
2477                 public TypeArguments TypeArguments {
2478                         get {
2479                                 return targs;
2480                         }
2481                 }
2482         }
2483         
2484         /// <summary>
2485         ///   SimpleName expressions are formed of a single word and only happen at the beginning 
2486         ///   of a dotted-name.
2487         /// </summary>
2488         public class SimpleName : ATypeNameExpression {
2489                 bool in_transit;
2490
2491                 public SimpleName (string name, Location l)
2492                         : base (name, l)
2493                 {
2494                 }
2495
2496                 public SimpleName (string name, TypeArguments args, Location l)
2497                         : base (name, args, l)
2498                 {
2499                 }
2500
2501                 public SimpleName (string name, TypeParameter[] type_params, Location l)
2502                         : base (name, l)
2503                 {
2504                         targs = new TypeArguments ();
2505                         foreach (TypeParameter type_param in type_params)
2506                                 targs.Add (new TypeParameterExpr (type_param, l));
2507                 }
2508
2509                 public static string RemoveGenericArity (string name)
2510                 {
2511                         int start = 0;
2512                         StringBuilder sb = null;
2513                         do {
2514                                 int pos = name.IndexOf ('`', start);
2515                                 if (pos < 0) {
2516                                         if (start == 0)
2517                                                 return name;
2518
2519                                         sb.Append (name.Substring (start));
2520                                         break;
2521                                 }
2522
2523                                 if (sb == null)
2524                                         sb = new StringBuilder ();
2525                                 sb.Append (name.Substring (start, pos-start));
2526
2527                                 pos++;
2528                                 while ((pos < name.Length) && Char.IsNumber (name [pos]))
2529                                         pos++;
2530
2531                                 start = pos;
2532                         } while (start < name.Length);
2533
2534                         return sb.ToString ();
2535                 }
2536
2537                 public SimpleName GetMethodGroup ()
2538                 {
2539                         return new SimpleName (RemoveGenericArity (Name), targs, loc);
2540                 }
2541
2542                 public static void Error_ObjectRefRequired (ResolveContext ec, Location l, string name)
2543                 {
2544                         if (ec.HasSet (ResolveContext.Options.FieldInitializerScope))
2545                                 ec.Report.Error (236, l,
2546                                         "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
2547                                         name);
2548                         else
2549                                 ec.Report.Error (120, l,
2550                                         "An object reference is required to access non-static member `{0}'",
2551                                         name);
2552                 }
2553
2554                 public bool IdenticalNameAndTypeName (IMemberContext mc, Expression resolved_to, Location loc)
2555                 {
2556                         return resolved_to != null && resolved_to.Type != null && 
2557                                 resolved_to.Type.Name == Name &&
2558                                 (mc.LookupNamespaceOrType (Name, loc, /* ignore_cs0104 = */ true) != null);
2559                 }
2560
2561                 public override Expression DoResolve (ResolveContext ec)
2562                 {
2563                         return SimpleNameResolve (ec, null, false);
2564                 }
2565
2566                 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
2567                 {
2568                         return SimpleNameResolve (ec, right_side, false);
2569                 }
2570                 
2571
2572                 public Expression DoResolve (ResolveContext ec, bool intermediate)
2573                 {
2574                         return SimpleNameResolve (ec, null, intermediate);
2575                 }
2576
2577                 static bool IsNestedChild (Type t, Type parent)
2578                 {
2579                         while (parent != null) {
2580                                 if (TypeManager.IsNestedChildOf (t, TypeManager.DropGenericTypeArguments (parent)))
2581                                         return true;
2582
2583                                 parent = parent.BaseType;
2584                         }
2585
2586                         return false;
2587                 }
2588
2589                 FullNamedExpression ResolveNested (Type t)
2590                 {
2591                         if (!TypeManager.IsGenericTypeDefinition (t) && !TypeManager.IsGenericType (t))
2592                                 return null;
2593
2594                         Type ds = t;
2595                         while (ds != null && !IsNestedChild (t, ds))
2596                                 ds = ds.DeclaringType;
2597
2598                         if (ds == null)
2599                                 return null;
2600
2601                         Type[] gen_params = TypeManager.GetTypeArguments (t);
2602
2603                         int arg_count = targs != null ? targs.Count : 0;
2604
2605                         for (; (ds != null) && TypeManager.IsGenericType (ds); ds = ds.DeclaringType) {
2606                                 Type[] gargs = TypeManager.GetTypeArguments (ds);
2607                                 if (arg_count + gargs.Length == gen_params.Length) {
2608                                         TypeArguments new_args = new TypeArguments ();
2609                                         foreach (Type param in gargs)
2610                                                 new_args.Add (new TypeExpression (param, loc));
2611
2612                                         if (targs != null)
2613                                                 new_args.Add (targs);
2614
2615                                         return new GenericTypeExpr (t, new_args, loc);
2616                                 }
2617                         }
2618
2619                         return null;
2620                 }
2621
2622                 public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
2623                 {
2624                         int errors = ec.Compiler.Report.Errors;
2625                         FullNamedExpression fne = ec.LookupNamespaceOrType (Name, loc, /*ignore_cs0104=*/ false);
2626
2627                         if (fne != null) {
2628                                 if (fne.Type == null)
2629                                         return fne;
2630
2631                                 FullNamedExpression nested = ResolveNested (fne.Type);
2632                                 if (nested != null)
2633                                         return nested.ResolveAsTypeStep (ec, false);
2634
2635                                 if (targs != null) {
2636                                         if (TypeManager.IsGenericType (fne.Type)) {
2637                                                 GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc);
2638                                                 return ct.ResolveAsTypeStep (ec, false);
2639                                         }
2640
2641                                         fne.Error_TypeArgumentsCannotBeUsed (ec.Compiler.Report, loc);
2642                                 }
2643
2644                                 return fne;
2645                         }
2646
2647                         if (!HasTypeArguments && Name == "dynamic" && RootContext.Version > LanguageVersion.V_3)
2648                                 return new DynamicTypeExpr (loc);
2649
2650                         if (silent || errors != ec.Compiler.Report.Errors)
2651                                 return null;
2652
2653                         Error_TypeOrNamespaceNotFound (ec);
2654                         return null;
2655                 }
2656
2657                 protected virtual void Error_TypeOrNamespaceNotFound (IMemberContext ec)
2658                 {
2659                         if (ec.CurrentType != null) {
2660                                 if (ec.CurrentTypeDefinition != null) {
2661                                         MemberCore mc = ec.CurrentTypeDefinition.GetDefinition (Name);
2662                                         if (mc != null) {
2663                                                 Error_UnexpectedKind (ec.Compiler.Report, mc, "type", GetMemberType (mc), loc);
2664                                                 return;
2665                                         }
2666                                 }
2667
2668                                 string ns = ec.CurrentType.Namespace;
2669                                 string fullname = (ns.Length > 0) ? ns + "." + Name : Name;
2670                                 foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
2671                                         Type type = a.GetType (fullname);
2672                                         if (type != null) {
2673                                                 ec.Compiler.Report.SymbolRelatedToPreviousError (type);
2674                                                 Expression.ErrorIsInaccesible (loc, TypeManager.CSharpName (type), ec.Compiler.Report);
2675                                                 return;
2676                                         }
2677                                 }
2678
2679                                 if (ec.CurrentTypeDefinition != null) {
2680                                         Type t = ec.CurrentTypeDefinition.LookupAnyGeneric (Name);
2681                                         if (t != null) {
2682                                                 Namespace.Error_InvalidNumberOfTypeArguments (t, loc);
2683                                                 return;
2684                                         }
2685                                 }
2686                         }
2687
2688                         if (targs != null) {
2689                                 FullNamedExpression retval = ec.LookupNamespaceOrType (SimpleName.RemoveGenericArity (Name), loc, true);
2690                                 if (retval != null) {
2691                                         retval.Error_TypeArgumentsCannotBeUsed (ec.Compiler.Report, loc);
2692                                         return;
2693                                 }
2694                         }
2695                                                 
2696                         NamespaceEntry.Error_NamespaceNotFound (loc, Name, ec.Compiler.Report);
2697                 }
2698
2699                 // TODO: I am still not convinced about this. If someone else will need it
2700                 // implement this as virtual property in MemberCore hierarchy
2701                 public static string GetMemberType (MemberCore mc)
2702                 {
2703                         if (mc is Property)
2704                                 return "property";
2705                         if (mc is Indexer)
2706                                 return "indexer";
2707                         if (mc is FieldBase)
2708                                 return "field";
2709                         if (mc is MethodCore)
2710                                 return "method";
2711                         if (mc is EnumMember)
2712                                 return "enum";
2713                         if (mc is Event)
2714                                 return "event";
2715
2716                         return "type";
2717                 }
2718
2719                 Expression SimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate)
2720                 {
2721                         if (in_transit)
2722                                 return null;
2723
2724                         in_transit = true;
2725                         Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
2726                         in_transit = false;
2727
2728                         if (e == null)
2729                                 return null;
2730
2731                         if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
2732                                 return e;
2733
2734                         return null;
2735                 }
2736
2737                 /// <remarks>
2738                 ///   7.5.2: Simple Names. 
2739                 ///
2740                 ///   Local Variables and Parameters are handled at
2741                 ///   parse time, so they never occur as SimpleNames.
2742                 ///
2743                 ///   The `intermediate' flag is used by MemberAccess only
2744                 ///   and it is used to inform us that it is ok for us to 
2745                 ///   avoid the static check, because MemberAccess might end
2746                 ///   up resolving the Name as a Type name and the access as
2747                 ///   a static type access.
2748                 ///
2749                 ///   ie: Type Type; .... { Type.GetType (""); }
2750                 ///
2751                 ///   Type is both an instance variable and a Type;  Type.GetType
2752                 ///   is the static method not an instance method of type.
2753                 /// </remarks>
2754                 Expression DoSimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate)
2755                 {
2756                         Expression e = null;
2757
2758                         //
2759                         // Stage 1: Performed by the parser (binding to locals or parameters).
2760                         //
2761                         Block current_block = ec.CurrentBlock;
2762                         if (current_block != null){
2763                                 LocalInfo vi = current_block.GetLocalInfo (Name);
2764                                 if (vi != null){
2765                                         e = new LocalVariableReference (ec.CurrentBlock, Name, loc);
2766
2767                                         if (right_side != null) {
2768                                                 e = e.ResolveLValue (ec, right_side);
2769                                         } else {
2770                                                 ResolveFlags rf = ResolveFlags.VariableOrValue;
2771                                                 if (intermediate)
2772                                                         rf |= ResolveFlags.DisableFlowAnalysis;
2773
2774                                                 e = e.Resolve (ec, rf);
2775                                         }
2776
2777                                         if (targs != null && e != null)
2778                                                 e.Error_TypeArgumentsCannotBeUsed (ec.Report, loc);
2779
2780                                         return e;
2781                                 }
2782
2783                                 e = current_block.Toplevel.GetParameterReference (Name, loc);
2784                                 if (e != null) {
2785                                         if (right_side != null)
2786                                                 e = e.ResolveLValue (ec, right_side);
2787                                         else
2788                                                 e = e.Resolve (ec);
2789
2790                                         if (targs != null && e != null)
2791                                                 e.Error_TypeArgumentsCannotBeUsed (ec.Report, loc);
2792
2793                                         return e;
2794                                 }
2795                         }
2796                         
2797                         //
2798                         // Stage 2: Lookup members 
2799                         //
2800
2801                         Type almost_matched_type = null;
2802                         ArrayList almost_matched = null;
2803                         for (Type lookup_ds = ec.CurrentType; lookup_ds != null; lookup_ds = lookup_ds.DeclaringType) {
2804                                 e = MemberLookup (ec.Compiler, ec.CurrentType, lookup_ds, Name, loc);
2805                                 if (e != null) {
2806                                         PropertyExpr pe = e as PropertyExpr;
2807                                         if (pe != null) {
2808                                                 AParametersCollection param = TypeManager.GetParameterData (pe.PropertyInfo);
2809
2810                                                 // since TypeManager.MemberLookup doesn't know if we're doing a lvalue access or not,
2811                                                 // it doesn't know which accessor to check permissions against
2812                                                 if (param.IsEmpty && pe.IsAccessibleFrom (ec.CurrentType, right_side != null))
2813                                                         break;
2814                                         } else if (e is EventExpr) {
2815                                                 if (((EventExpr) e).IsAccessibleFrom (ec.CurrentType))
2816                                                         break;
2817                                         } else if (targs != null && e is TypeExpression) {
2818                                                 e = new GenericTypeExpr (e.Type, targs, loc).ResolveAsTypeStep (ec, false);
2819                                                 break;
2820                                         } else {
2821                                                 break;
2822                                         }
2823                                         e = null;
2824                                 }
2825
2826                                 if (almost_matched == null && almost_matched_members.Count > 0) {
2827                                         almost_matched_type = lookup_ds;
2828                                         almost_matched = (ArrayList) almost_matched_members.Clone ();
2829                                 }
2830                         }
2831
2832                         if (e == null) {
2833                                 if (almost_matched == null && almost_matched_members.Count > 0) {
2834                                         almost_matched_type = ec.CurrentType;
2835                                         almost_matched = (ArrayList) almost_matched_members.Clone ();
2836                                 }
2837                                 e = ResolveAsTypeStep (ec, true);
2838                         }
2839
2840                         if (e == null) {
2841                                 if (current_block != null) {
2842                                         IKnownVariable ikv = current_block.Explicit.GetKnownVariable (Name);
2843                                         if (ikv != null) {
2844                                                 LocalInfo li = ikv as LocalInfo;
2845                                                 // Supress CS0219 warning
2846                                                 if (li != null)
2847                                                         li.Used = true;
2848
2849                                                 Error_VariableIsUsedBeforeItIsDeclared (ec.Report, Name);
2850                                                 return null;
2851                                         }
2852                                 }
2853
2854                                 if (RootContext.EvalMode){
2855                                         FieldInfo fi = Evaluator.LookupField (Name);
2856                                         if (fi != null)
2857                                                 return new FieldExpr (fi, loc).Resolve (ec);
2858                                 }
2859
2860                                 if (almost_matched != null)
2861                                         almost_matched_members = almost_matched;
2862                                 if (almost_matched_type == null)
2863                                         almost_matched_type = ec.CurrentType;
2864
2865                                 string type_name = ec.MemberContext.CurrentType == null ? null : ec.MemberContext.CurrentType.Name;
2866                                 return Error_MemberLookupFailed (ec, ec.CurrentType, null, almost_matched_type, Name,
2867                                         type_name, AllMemberTypes, AllBindingFlags);
2868                         }
2869
2870                         if (e is MemberExpr) {
2871                                 MemberExpr me = (MemberExpr) e;
2872
2873                                 Expression left;
2874                                 if (me.IsInstance) {
2875                                         if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer | ResolveContext.Options.ConstantScope)) {
2876                                                 //
2877                                                 // Note that an MemberExpr can be both IsInstance and IsStatic.
2878                                                 // An unresolved MethodGroupExpr can contain both kinds of methods
2879                                                 // and each predicate is true if the MethodGroupExpr contains
2880                                                 // at least one of that kind of method.
2881                                                 //
2882
2883                                                 if (!me.IsStatic &&
2884                                                     (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
2885                                                         Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
2886                                                         return null;
2887                                                 }
2888
2889                                                 //
2890                                                 // Pass the buck to MemberAccess and Invocation.
2891                                                 //
2892                                                 left = EmptyExpression.Null;
2893                                         } else {
2894                                                 left = ec.GetThis (loc);
2895                                         }
2896                                 } else {
2897                                         left = new TypeExpression (ec.CurrentType, loc);
2898                                 }
2899
2900                                 me = me.ResolveMemberAccess (ec, left, loc, null);
2901                                 if (me == null)
2902                                         return null;
2903
2904                                 if (targs != null) {
2905                                         if (!targs.Resolve (ec))
2906                                                 return null;
2907
2908                                         me.SetTypeArguments (ec, targs);
2909                                 }
2910
2911                                 if (!me.IsStatic && (me.InstanceExpression != null && me.InstanceExpression != EmptyExpression.Null) &&
2912                                     TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2913                                     me.InstanceExpression.Type != me.DeclaringType &&
2914                                     !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2915                                     (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
2916                                         ec.Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
2917                                                 TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type));
2918                                         return null;
2919                                 }
2920
2921                                 return (right_side != null)
2922                                         ? me.DoResolveLValue (ec, right_side)
2923                                         : me.DoResolve (ec);
2924                         }
2925
2926                         return e;
2927                 }
2928         }
2929
2930         /// <summary>
2931         ///   Represents a namespace or a type.  The name of the class was inspired by
2932         ///   section 10.8.1 (Fully Qualified Names).
2933         /// </summary>
2934         public abstract class FullNamedExpression : Expression
2935         {
2936                 protected override void CloneTo (CloneContext clonectx, Expression target)
2937                 {
2938                         // Do nothing, most unresolved type expressions cannot be
2939                         // resolved to different type
2940                 }
2941
2942                 public override Expression CreateExpressionTree (ResolveContext ec)
2943                 {
2944                         throw new NotSupportedException ("ET");
2945                 }
2946
2947                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
2948                 {
2949                         throw new NotSupportedException ();
2950                 }
2951
2952                 public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
2953                 {
2954                         return this;
2955                 }
2956
2957                 public override void Emit (EmitContext ec)
2958                 {
2959                         throw new InternalErrorException ("FullNamedExpression `{0}' found in resolved tree",
2960                                 GetSignatureForError ());
2961                 }
2962         }
2963         
2964         /// <summary>
2965         ///   Expression that evaluates to a type
2966         /// </summary>
2967         public abstract class TypeExpr : FullNamedExpression {
2968                 public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
2969                 {
2970                         TypeExpr t = DoResolveAsTypeStep (ec);
2971                         if (t == null)
2972                                 return null;
2973
2974                         eclass = ExprClass.Type;
2975                         return t;
2976                 }
2977
2978                 override public Expression DoResolve (ResolveContext ec)
2979                 {
2980                         return ResolveAsTypeTerminal (ec, false);
2981                 }
2982
2983                 public virtual bool CheckAccessLevel (IMemberContext mc)
2984                 {
2985                         return mc.CurrentTypeDefinition.CheckAccessLevel (Type);
2986                 }
2987
2988                 public virtual bool IsClass {
2989                         get { return Type.IsClass; }
2990                 }
2991
2992                 public virtual bool IsValueType {
2993                         get { return TypeManager.IsStruct (Type); }
2994                 }
2995
2996                 public virtual bool IsInterface {
2997                         get { return Type.IsInterface; }
2998                 }
2999
3000                 public virtual bool IsSealed {
3001                         get { return Type.IsSealed; }
3002                 }
3003
3004                 public virtual bool CanInheritFrom ()
3005                 {
3006                         if (Type == TypeManager.enum_type ||
3007                             (Type == TypeManager.value_type && RootContext.StdLib) ||
3008                             Type == TypeManager.multicast_delegate_type ||
3009                             Type == TypeManager.delegate_type ||
3010                             Type == TypeManager.array_type)
3011                                 return false;
3012
3013                         return true;
3014                 }
3015
3016                 protected abstract TypeExpr DoResolveAsTypeStep (IMemberContext ec);
3017
3018                 public override bool Equals (object obj)
3019                 {
3020                         TypeExpr tobj = obj as TypeExpr;
3021                         if (tobj == null)
3022                                 return false;
3023
3024                         return Type == tobj.Type;
3025                 }
3026
3027                 public override int GetHashCode ()
3028                 {
3029                         return Type.GetHashCode ();
3030                 }
3031
3032                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
3033                 {
3034                         type = storey.MutateType (type);
3035                 }
3036         }
3037
3038         /// <summary>
3039         ///   Fully resolved Expression that already evaluated to a type
3040         /// </summary>
3041         public class TypeExpression : TypeExpr {
3042                 public TypeExpression (Type t, Location l)
3043                 {
3044                         Type = t;
3045                         eclass = ExprClass.Type;
3046                         loc = l;
3047                 }
3048
3049                 protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec)
3050                 {
3051                         return this;
3052                 }
3053
3054                 public override TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent)
3055                 {
3056                         return this;
3057                 }
3058         }
3059
3060         //
3061         // Used to create types from a fully qualified name.  These are just used
3062         // by the parser to setup the core types.
3063         //
3064         public sealed class TypeLookupExpression : TypeExpr {
3065                 readonly string ns_name;
3066                 readonly string name;
3067                 
3068                 public TypeLookupExpression (string ns, string name)
3069                 {
3070                         this.name = name;
3071                         this.ns_name = ns;
3072                         eclass = ExprClass.Type;
3073                 }
3074
3075                 public override TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent)
3076                 {
3077                         //
3078                         // It's null only during mscorlib bootstrap when DefineType
3079                         // nees to resolve base type of same type
3080                         //
3081                         // For instance struct Char : IComparable<char>
3082                         //
3083                         // TODO: it could be removed when Resolve starts to use 
3084                         // DeclSpace instead of Type
3085                         //
3086                         if (type == null) {
3087                                 Namespace ns = GlobalRootNamespace.Instance.GetNamespace (ns_name, false);
3088                                 FullNamedExpression fne = ns.Lookup (ec.Compiler, name, loc);
3089                                 if (fne != null)
3090                                         type = fne.Type;
3091                         }
3092
3093                         return this;
3094                 }
3095
3096                 protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec)
3097                 {
3098                         return this;
3099                 }
3100
3101                 public override string GetSignatureForError ()
3102                 {
3103                         if (type == null)
3104                                 return TypeManager.CSharpName (ns_name + "." + name, null);
3105
3106                         return base.GetSignatureForError ();
3107                 }
3108         }
3109
3110         /// <summary>
3111         ///   This class denotes an expression which evaluates to a member
3112         ///   of a struct or a class.
3113         /// </summary>
3114         public abstract class MemberExpr : Expression
3115         {
3116                 protected bool is_base;
3117
3118                 /// <summary>
3119                 ///   The name of this member.
3120                 /// </summary>
3121                 public abstract string Name {
3122                         get;
3123                 }
3124
3125                 //
3126                 // When base.member is used
3127                 //
3128                 public bool IsBase {
3129                         get { return is_base; }
3130                         set { is_base = value; }
3131                 }
3132
3133                 /// <summary>
3134                 ///   Whether this is an instance member.
3135                 /// </summary>
3136                 public abstract bool IsInstance {
3137                         get;
3138                 }
3139
3140                 /// <summary>
3141                 ///   Whether this is a static member.
3142                 /// </summary>
3143                 public abstract bool IsStatic {
3144                         get;
3145                 }
3146
3147                 /// <summary>
3148                 ///   The type which declares this member.
3149                 /// </summary>
3150                 public abstract Type DeclaringType {
3151                         get;
3152                 }
3153
3154                 /// <summary>
3155                 ///   The instance expression associated with this member, if it's a
3156                 ///   non-static member.
3157                 /// </summary>
3158                 public Expression InstanceExpression;
3159
3160                 public static void error176 (ResolveContext ec, Location loc, string name)
3161                 {
3162                         ec.Report.Error (176, loc, "Static member `{0}' cannot be accessed " +
3163                                       "with an instance reference, qualify it with a type name instead", name);
3164                 }
3165
3166                 public static void Error_BaseAccessInExpressionTree (ResolveContext ec, Location loc)
3167                 {
3168                         ec.Report.Error (831, loc, "An expression tree may not contain a base access");
3169                 }
3170
3171                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
3172                 {
3173                         if (InstanceExpression != null)
3174                                 InstanceExpression.MutateHoistedGenericType (storey);
3175                 }
3176
3177                 // TODO: possible optimalization
3178                 // Cache resolved constant result in FieldBuilder <-> expression map
3179                 public virtual MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
3180                                                                SimpleName original)
3181                 {
3182                         //
3183                         // Precondition:
3184                         //   original == null || original.Resolve (...) ==> left
3185                         //
3186
3187                         if (left is TypeExpr) {
3188                                 left = left.ResolveAsBaseTerminal (ec, false);
3189                                 if (left == null)
3190                                         return null;
3191
3192                                 // TODO: Same problem as in class.cs, TypeTerminal does not
3193                                 // always do all necessary checks
3194                                 ObsoleteAttribute oa = AttributeTester.GetObsoleteAttribute (left.Type);
3195                                 if (oa != null && !ec.IsObsolete) {
3196                                         AttributeTester.Report_ObsoleteMessage (oa, left.GetSignatureForError (), loc, ec.Report);
3197                                 }
3198
3199                                 GenericTypeExpr ct = left as GenericTypeExpr;
3200                                 if (ct != null && !ct.CheckConstraints (ec))
3201                                         return null;
3202                                 //
3203
3204                                 if (!IsStatic) {
3205                                         SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
3206                                         return null;
3207                                 }
3208
3209                                 return this;
3210                         }
3211                                 
3212                         if (!IsInstance) {
3213                                 if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
3214                                         return this;
3215
3216                                 return ResolveExtensionMemberAccess (ec, left);
3217                         }
3218
3219                         InstanceExpression = left;
3220                         return this;
3221                 }
3222
3223                 protected virtual MemberExpr ResolveExtensionMemberAccess (ResolveContext ec, Expression left)
3224                 {
3225                         error176 (ec, loc, GetSignatureForError ());
3226                         return this;
3227                 }
3228
3229                 protected void EmitInstance (EmitContext ec, bool prepare_for_load)
3230                 {
3231                         if (IsStatic)
3232                                 return;
3233
3234                         if (InstanceExpression == EmptyExpression.Null) {
3235                                 // FIXME: This should not be here at all
3236                                 SimpleName.Error_ObjectRefRequired (new ResolveContext (ec.MemberContext), loc, GetSignatureForError ());
3237                                 return;
3238                         }
3239
3240                         if (TypeManager.IsValueType (InstanceExpression.Type)) {
3241                                 if (InstanceExpression is IMemoryLocation) {
3242                                         ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
3243                                 } else {
3244                                         LocalTemporary t = new LocalTemporary (InstanceExpression.Type);
3245                                         InstanceExpression.Emit (ec);
3246                                         t.Store (ec);
3247                                         t.AddressOf (ec, AddressOp.Store);
3248                                 }
3249                         } else
3250                                 InstanceExpression.Emit (ec);
3251
3252                         if (prepare_for_load)
3253                                 ec.ig.Emit (OpCodes.Dup);
3254                 }
3255
3256                 public virtual void SetTypeArguments (ResolveContext ec, TypeArguments ta)
3257                 {
3258                         // TODO: need to get correct member type
3259                         ec.Report.Error (307, loc, "The property `{0}' cannot be used with type arguments",
3260                                 GetSignatureForError ());
3261                 }
3262         }
3263
3264         /// 
3265         /// Represents group of extension methods
3266         /// 
3267         public class ExtensionMethodGroupExpr : MethodGroupExpr
3268         {
3269                 readonly NamespaceEntry namespace_entry;
3270                 public Expression ExtensionExpression;
3271                 Argument extension_argument;
3272
3273                 public ExtensionMethodGroupExpr (ArrayList list, NamespaceEntry n, Type extensionType, Location l)
3274                         : base (list, extensionType, l)
3275                 {
3276                         this.namespace_entry = n;
3277                 }
3278
3279                 public override bool IsStatic {
3280                         get { return true; }
3281                 }
3282
3283                 public bool IsTopLevel {
3284                         get { return namespace_entry == null; }
3285                 }
3286
3287                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
3288                 {
3289                         extension_argument.Expr.MutateHoistedGenericType (storey);
3290                         base.MutateHoistedGenericType (storey);
3291                 }
3292
3293                 public override MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments arguments, bool may_fail, Location loc)
3294                 {
3295                         if (arguments == null)
3296                                 arguments = new Arguments (1);
3297
3298                         arguments.Insert (0, new Argument (ExtensionExpression));
3299                         MethodGroupExpr mg = ResolveOverloadExtensions (ec, ref arguments, namespace_entry, loc);
3300
3301                         // Store resolved argument and restore original arguments
3302                         if (mg != null)
3303                                 ((ExtensionMethodGroupExpr)mg).extension_argument = arguments [0];
3304                         else
3305                                 arguments.RemoveAt (0); // Clean-up modified arguments for error reporting
3306
3307                         return mg;
3308                 }
3309
3310                 MethodGroupExpr ResolveOverloadExtensions (ResolveContext ec, ref Arguments arguments, NamespaceEntry ns, Location loc)
3311                 {
3312                         // Use normal resolve rules
3313                         MethodGroupExpr mg = base.OverloadResolve (ec, ref arguments, ns != null, loc);
3314                         if (mg != null)
3315                                 return mg;
3316
3317                         if (ns == null)
3318                                 return null;
3319
3320                         // Search continues
3321                         ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, Name, loc);
3322                         if (e == null)
3323                                 return base.OverloadResolve (ec, ref arguments, false, loc);
3324
3325                         e.ExtensionExpression = ExtensionExpression;
3326                         e.SetTypeArguments (ec, type_arguments);                        
3327                         return e.ResolveOverloadExtensions (ec, ref arguments, e.namespace_entry, loc);
3328                 }               
3329         }
3330
3331         /// <summary>
3332         ///   MethodGroupExpr represents a group of method candidates which
3333         ///   can be resolved to the best method overload
3334         /// </summary>
3335         public class MethodGroupExpr : MemberExpr
3336         {
3337                 public interface IErrorHandler
3338                 {
3339                         bool AmbiguousCall (ResolveContext ec, MethodBase ambiguous);
3340                         bool NoExactMatch (ResolveContext ec, MethodBase method);
3341                 }
3342
3343                 public IErrorHandler CustomErrorHandler;                
3344                 public MethodBase [] Methods;
3345                 MethodBase best_candidate;
3346                 // TODO: make private
3347                 public TypeArguments type_arguments;
3348                 bool identical_type_name;
3349                 bool has_inaccessible_candidates_only;
3350                 Type delegate_type;
3351                 Type queried_type;
3352                 
3353                 public MethodGroupExpr (MemberInfo [] mi, Type type, Location l)
3354                         : this (type, l)
3355                 {
3356                         Methods = new MethodBase [mi.Length];
3357                         mi.CopyTo (Methods, 0);
3358                 }
3359
3360                 public MethodGroupExpr (MemberInfo[] mi, Type type, Location l, bool inacessibleCandidatesOnly)
3361                         : this (mi, type, l)
3362                 {
3363                         has_inaccessible_candidates_only = inacessibleCandidatesOnly;
3364                 }
3365
3366                 public MethodGroupExpr (ArrayList list, Type type, Location l)
3367                         : this (type, l)
3368                 {
3369                         try {
3370                                 Methods = (MethodBase[])list.ToArray (typeof (MethodBase));
3371                         } catch {
3372                                 foreach (MemberInfo m in list){
3373                                         if (!(m is MethodBase)){
3374                                                 Console.WriteLine ("Name " + m.Name);
3375                                                 Console.WriteLine ("Found a: " + m.GetType ().FullName);
3376                                         }
3377                                 }
3378                                 throw;
3379                         }
3380
3381
3382                 }
3383
3384                 protected MethodGroupExpr (Type type, Location loc)
3385                 {
3386                         this.loc = loc;
3387                         eclass = ExprClass.MethodGroup;
3388                         this.type = InternalType.MethodGroup;
3389                         queried_type = type;
3390                 }
3391
3392                 public override Type DeclaringType {
3393                         get {
3394                                 return queried_type;
3395                         }
3396                 }
3397
3398                 public Type DelegateType {
3399                         set {
3400                                 delegate_type = value;
3401                         }
3402                 }
3403
3404                 public bool IdenticalTypeName {
3405                         get {
3406                                 return identical_type_name;
3407                         }
3408                 }
3409
3410                 public override string GetSignatureForError ()
3411                 {
3412                         if (best_candidate != null)
3413                                 return TypeManager.CSharpSignature (best_candidate);
3414                         
3415                         return TypeManager.CSharpSignature (Methods [0]);
3416                 }
3417
3418                 public override string Name {
3419                         get {
3420                                 return Methods [0].Name;
3421                         }
3422                 }
3423
3424                 public override bool IsInstance {
3425                         get {
3426                                 if (best_candidate != null)
3427                                         return !best_candidate.IsStatic;
3428
3429                                 foreach (MethodBase mb in Methods)
3430                                         if (!mb.IsStatic)
3431                                                 return true;
3432
3433                                 return false;
3434                         }
3435                 }
3436
3437                 public override bool IsStatic {
3438                         get {
3439                                 if (best_candidate != null)
3440                                         return best_candidate.IsStatic;
3441
3442                                 foreach (MethodBase mb in Methods)
3443                                         if (mb.IsStatic)
3444                                                 return true;
3445
3446                                 return false;
3447                         }
3448                 }
3449                 
3450                 public static explicit operator ConstructorInfo (MethodGroupExpr mg)
3451                 {
3452                         return (ConstructorInfo)mg.best_candidate;
3453                 }
3454
3455                 public static explicit operator MethodInfo (MethodGroupExpr mg)
3456                 {
3457                         return (MethodInfo)mg.best_candidate;
3458                 }
3459
3460                 //
3461                 //  7.4.3.3  Better conversion from expression
3462                 //  Returns :   1    if a->p is better,
3463                 //              2    if a->q is better,
3464                 //              0 if neither is better
3465                 //
3466                 static int BetterExpressionConversion (ResolveContext ec, Argument a, Type p, Type q)
3467                 {
3468                         Type argument_type = TypeManager.TypeToCoreType (a.Type);
3469                         if (argument_type == InternalType.AnonymousMethod && RootContext.Version > LanguageVersion.ISO_2) {
3470                                 //
3471                                 // Uwrap delegate from Expression<T>
3472                                 //
3473                                 if (TypeManager.DropGenericTypeArguments (p) == TypeManager.expression_type) {
3474                                         p = TypeManager.GetTypeArguments (p) [0];
3475                                 }
3476                                 if (TypeManager.DropGenericTypeArguments (q) == TypeManager.expression_type) {
3477                                         q = TypeManager.GetTypeArguments (q) [0];
3478                                 }
3479                                 
3480                                 p = Delegate.GetInvokeMethod (ec.Compiler, null, p).ReturnType;
3481                                 q = Delegate.GetInvokeMethod (ec.Compiler, null, q).ReturnType;
3482                                 if (p == TypeManager.void_type && q != TypeManager.void_type)
3483                                         return 2;
3484                                 if (q == TypeManager.void_type && p != TypeManager.void_type)
3485                                         return 1;
3486                         } else {
3487                                 if (argument_type == p)
3488                                         return 1;
3489
3490                                 if (argument_type == q)
3491                                         return 2;
3492                         }
3493
3494                         return BetterTypeConversion (ec, p, q);
3495                 }
3496
3497                 //
3498                 // 7.4.3.4  Better conversion from type
3499                 //
3500                 public static int BetterTypeConversion (ResolveContext ec, Type p, Type q)
3501                 {
3502                         if (p == null || q == null)
3503                                 throw new InternalErrorException ("BetterTypeConversion got a null conversion");
3504
3505                         if (p == TypeManager.int32_type) {
3506                                 if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
3507                                         return 1;
3508                         } else if (p == TypeManager.int64_type) {
3509                                 if (q == TypeManager.uint64_type)
3510                                         return 1;
3511                         } else if (p == TypeManager.sbyte_type) {
3512                                 if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
3513                                         q == TypeManager.uint32_type || q == TypeManager.uint64_type)
3514                                         return 1;
3515                         } else if (p == TypeManager.short_type) {
3516                                 if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
3517                                         q == TypeManager.uint64_type)
3518                                         return 1;
3519                         }
3520
3521                         if (q == TypeManager.int32_type) {
3522                                 if (p == TypeManager.uint32_type || p == TypeManager.uint64_type)
3523                                         return 2;
3524                         } if (q == TypeManager.int64_type) {
3525                                 if (p == TypeManager.uint64_type)
3526                                         return 2;
3527                         } else if (q == TypeManager.sbyte_type) {
3528                                 if (p == TypeManager.byte_type || p == TypeManager.ushort_type ||
3529                                         p == TypeManager.uint32_type || p == TypeManager.uint64_type)
3530                                         return 2;
3531                         } if (q == TypeManager.short_type) {
3532                                 if (p == TypeManager.ushort_type || p == TypeManager.uint32_type ||
3533                                         p == TypeManager.uint64_type)
3534                                         return 2;
3535                         }
3536
3537                         // TODO: this is expensive
3538                         Expression p_tmp = new EmptyExpression (p);
3539                         Expression q_tmp = new EmptyExpression (q);
3540
3541                         bool p_to_q = Convert.ImplicitConversionExists (ec, p_tmp, q);
3542                         bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p);
3543
3544                         if (p_to_q && !q_to_p)
3545                                 return 1;
3546
3547                         if (q_to_p && !p_to_q)
3548                                 return 2;
3549
3550                         return 0;
3551                 }
3552
3553                 /// <summary>
3554                 ///   Determines "Better function" between candidate
3555                 ///   and the current best match
3556                 /// </summary>
3557                 /// <remarks>
3558                 ///    Returns a boolean indicating :
3559                 ///     false if candidate ain't better
3560                 ///     true  if candidate is better than the current best match
3561                 /// </remarks>
3562                 static bool BetterFunction (ResolveContext ec, Arguments args, int argument_count,
3563                         MethodBase candidate, bool candidate_params,
3564                         MethodBase best, bool best_params)
3565                 {
3566                         AParametersCollection candidate_pd = TypeManager.GetParameterData (candidate);
3567                         AParametersCollection best_pd = TypeManager.GetParameterData (best);
3568                 
3569                         bool better_at_least_one = false;
3570                         bool same = true;
3571                         for (int j = 0, c_idx = 0, b_idx = 0; j < argument_count; ++j, ++c_idx, ++b_idx) 
3572                         {
3573                                 Argument a = args [j];
3574
3575                                 // Provided default argument value is never better
3576                                 if (a.IsDefaultArgument && candidate_params == best_params)
3577                                         return false;
3578
3579                                 Type ct = candidate_pd.Types [c_idx];
3580                                 Type bt = best_pd.Types [b_idx];
3581
3582                                 if (candidate_params && candidate_pd.FixedParameters [c_idx].ModFlags == Parameter.Modifier.PARAMS) 
3583                                 {
3584                                         ct = TypeManager.GetElementType (ct);
3585                                         --c_idx;
3586                                 }
3587
3588                                 if (best_params && best_pd.FixedParameters [b_idx].ModFlags == Parameter.Modifier.PARAMS) 
3589                                 {
3590                                         bt = TypeManager.GetElementType (bt);
3591                                         --b_idx;
3592                                 }
3593
3594                                 if (ct.Equals (bt))
3595                                         continue;
3596
3597                                 same = false;
3598                                 int result = BetterExpressionConversion (ec, a, ct, bt);
3599
3600                                 // for each argument, the conversion to 'ct' should be no worse than 
3601                                 // the conversion to 'bt'.
3602                                 if (result == 2)
3603                                         return false;
3604
3605                                 // for at least one argument, the conversion to 'ct' should be better than 
3606                                 // the conversion to 'bt'.
3607                                 if (result != 0)
3608                                         better_at_least_one = true;
3609                         }
3610
3611                         if (better_at_least_one)
3612                                 return true;
3613
3614                         //
3615                         // This handles the case
3616                         //
3617                         //   Add (float f1, float f2, float f3);
3618                         //   Add (params decimal [] foo);
3619                         //
3620                         // The call Add (3, 4, 5) should be ambiguous.  Without this check, the
3621                         // first candidate would've chosen as better.
3622                         //
3623                         if (!same)
3624                                 return false;
3625
3626                         //
3627                         // The two methods have equal parameter types.  Now apply tie-breaking rules
3628                         //
3629                         if (TypeManager.IsGenericMethod (best)) {
3630                                 if (!TypeManager.IsGenericMethod (candidate))
3631                                         return true;
3632                         } else if (TypeManager.IsGenericMethod (candidate)) {
3633                                 return false;
3634                         }
3635
3636                         //
3637                         // This handles the following cases:
3638                         //
3639                         //   Trim () is better than Trim (params char[] chars)
3640                         //   Concat (string s1, string s2, string s3) is better than
3641                         //     Concat (string s1, params string [] srest)
3642                         //   Foo (int, params int [] rest) is better than Foo (params int [] rest)
3643                         //
3644                         if (!candidate_params && best_params)
3645                                 return true;
3646                         if (candidate_params && !best_params)
3647                                 return false;
3648
3649                         int candidate_param_count = candidate_pd.Count;
3650                         int best_param_count = best_pd.Count;
3651
3652                         if (candidate_param_count != best_param_count)
3653                                 // can only happen if (candidate_params && best_params)
3654                                 return candidate_param_count > best_param_count && best_pd.HasParams;
3655
3656                         //
3657                         // now, both methods have the same number of parameters, and the parameters have the same types
3658                         // Pick the "more specific" signature
3659                         //
3660
3661                         MethodBase orig_candidate = TypeManager.DropGenericMethodArguments (candidate);
3662                         MethodBase orig_best = TypeManager.DropGenericMethodArguments (best);
3663
3664                         AParametersCollection orig_candidate_pd = TypeManager.GetParameterData (orig_candidate);
3665                         AParametersCollection orig_best_pd = TypeManager.GetParameterData (orig_best);
3666
3667                         bool specific_at_least_once = false;
3668                         for (int j = 0; j < candidate_param_count; ++j) 
3669                         {
3670                                 Type ct = orig_candidate_pd.Types [j];
3671                                 Type bt = orig_best_pd.Types [j];
3672                                 if (ct.Equals (bt))
3673                                         continue;
3674                                 Type specific = MoreSpecific (ct, bt);
3675                                 if (specific == bt)
3676                                         return false;
3677                                 if (specific == ct)
3678                                         specific_at_least_once = true;
3679                         }
3680
3681                         if (specific_at_least_once)
3682                                 return true;
3683
3684                         // FIXME: handle lifted operators
3685                         // ...
3686
3687                         return false;
3688                 }
3689
3690                 protected override MemberExpr ResolveExtensionMemberAccess (ResolveContext ec, Expression left)
3691                 {
3692                         if (!IsStatic)
3693                                 return base.ResolveExtensionMemberAccess (ec, left);
3694
3695                         //
3696                         // When left side is an expression and at least one candidate method is 
3697                         // static, it can be extension method
3698                         //
3699                         InstanceExpression = left;
3700                         return this;
3701                 }
3702
3703                 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
3704                                                                 SimpleName original)
3705                 {
3706                         if (!(left is TypeExpr) &&
3707                             original != null && original.IdenticalNameAndTypeName (ec, left, loc))
3708                                 identical_type_name = true;
3709
3710                         return base.ResolveMemberAccess (ec, left, loc, original);
3711                 }
3712
3713                 public override Expression CreateExpressionTree (ResolveContext ec)
3714                 {
3715                         if (best_candidate == null) {
3716                                 ec.Report.Error (1953, loc, "An expression tree cannot contain an expression with method group");
3717                                 return null;
3718                         }
3719
3720                         IMethodData md = TypeManager.GetMethod (best_candidate);
3721                         if (md != null && md.IsExcluded ())
3722                                 ec.Report.Error (765, loc,
3723                                         "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
3724                         
3725                         return new TypeOfMethod (best_candidate, loc);
3726                 }
3727                 
3728                 override public Expression DoResolve (ResolveContext ec)
3729                 {
3730                         if (InstanceExpression != null) {
3731                                 InstanceExpression = InstanceExpression.DoResolve (ec);
3732                                 if (InstanceExpression == null)
3733                                         return null;
3734                         }
3735
3736                         return this;
3737                 }
3738
3739                 public void ReportUsageError (ResolveContext ec)
3740                 {
3741                         ec.Report.Error (654, loc, "Method `" + DeclaringType + "." +
3742                                       Name + "()' is referenced without parentheses");
3743                 }
3744
3745                 override public void Emit (EmitContext ec)
3746                 {
3747                         throw new NotSupportedException ();
3748                         // ReportUsageError ();
3749                 }
3750                 
3751                 public void EmitCall (EmitContext ec, Arguments arguments)
3752                 {
3753                         Invocation.EmitCall (ec, IsBase, InstanceExpression, best_candidate, arguments, loc);                   
3754                 }
3755
3756                 void Error_AmbiguousCall (ResolveContext ec, MethodBase ambiguous)
3757                 {
3758                         if (CustomErrorHandler != null && CustomErrorHandler.AmbiguousCall (ec, ambiguous))
3759                                 return;
3760
3761                         ec.Report.SymbolRelatedToPreviousError (best_candidate);
3762                         ec.Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'",
3763                                 TypeManager.CSharpSignature (ambiguous), TypeManager.CSharpSignature (best_candidate));
3764                 }
3765
3766                 protected virtual void Error_InvalidArguments (ResolveContext ec, Location loc, int idx, MethodBase method,
3767                                                                                                         Argument a, AParametersCollection expected_par, Type paramType)
3768                 {
3769                         ExtensionMethodGroupExpr emg = this as ExtensionMethodGroupExpr;
3770
3771                         if (a is CollectionElementInitializer.ElementInitializerArgument) {
3772                                 ec.Report.SymbolRelatedToPreviousError (method);
3773                                 if ((expected_par.FixedParameters [idx].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
3774                                         ec.Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier",
3775                                                 TypeManager.CSharpSignature (method));
3776                                         return;
3777                                 }
3778                                 ec.Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments",
3779                                           TypeManager.CSharpSignature (method));
3780                         } else if (TypeManager.IsDelegateType (method.DeclaringType)) {
3781                                 ec.Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments",
3782                                         TypeManager.CSharpName (method.DeclaringType));
3783                         } else {
3784                                 ec.Report.SymbolRelatedToPreviousError (method);
3785                                 if (emg != null) {
3786                                         ec.Report.Error (1928, loc,
3787                                                 "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' has some invalid arguments",
3788                                                 emg.ExtensionExpression.GetSignatureForError (),
3789                                                 emg.Name, TypeManager.CSharpSignature (method));
3790                                 } else {
3791                                         ec.Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments",
3792                                                 TypeManager.CSharpSignature (method));
3793                                 }
3794                         }
3795
3796                         Parameter.Modifier mod = idx >= expected_par.Count ? 0 : expected_par.FixedParameters [idx].ModFlags;
3797
3798                         string index = (idx + 1).ToString ();
3799                         if (((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) ^
3800                                 (a.Modifier & (Parameter.Modifier.REF | Parameter.Modifier.OUT))) != 0) {
3801                                 if ((mod & Parameter.Modifier.ISBYREF) == 0)
3802                                         ec.Report.Error (1615, loc, "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' modifier",
3803                                                 index, Parameter.GetModifierSignature (a.Modifier));
3804                                 else
3805                                         ec.Report.Error (1620, loc, "Argument `#{0}' is missing `{1}' modifier",
3806                                                 index, Parameter.GetModifierSignature (mod));
3807                         } else {
3808                                 string p1 = a.GetSignatureForError ();
3809                                 string p2 = TypeManager.CSharpName (paramType);
3810
3811                                 if (p1 == p2) {
3812                                         ec.Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous ");
3813                                         ec.Report.SymbolRelatedToPreviousError (a.Expr.Type);
3814                                         ec.Report.SymbolRelatedToPreviousError (paramType);
3815                                 }
3816
3817                                 if (idx == 0 && emg != null) {
3818                                         ec.Report.Error (1929, loc,
3819                                                 "Extension method instance type `{0}' cannot be converted to `{1}'", p1, p2);
3820                                 } else {
3821                                         ec.Report.Error (1503, loc,
3822                                                 "Argument `#{0}' cannot convert `{1}' expression to type `{2}'", index, p1, p2);
3823                                 }
3824                         }
3825                 }
3826
3827                 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, Type target, bool expl)
3828                 {
3829                         ec.Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method",
3830                                 Name, TypeManager.CSharpName (target));
3831                 }
3832
3833                 void Error_ArgumentCountWrong (ResolveContext ec, int arg_count)
3834                 {
3835                         ec.Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments",
3836                                       Name, arg_count.ToString ());
3837                 }
3838                 
3839                 protected virtual int GetApplicableParametersCount (MethodBase method, AParametersCollection parameters)
3840                 {
3841                         return parameters.Count;
3842                 }               
3843
3844                 public static bool IsAncestralType (Type first_type, Type second_type)
3845                 {
3846                         return first_type != second_type &&
3847                                 (TypeManager.IsSubclassOf (second_type, first_type) ||
3848                                 TypeManager.ImplementsInterface (second_type, first_type));
3849                 }
3850
3851                 ///
3852                 /// Determines if the candidate method is applicable (section 14.4.2.1)
3853                 /// to the given set of arguments
3854                 /// A return value rates candidate method compatibility,
3855                 /// 0 = the best, int.MaxValue = the worst
3856                 ///
3857                 public int IsApplicable (ResolveContext ec,
3858                                                 ref Arguments arguments, int arg_count, ref MethodBase method, ref bool params_expanded_form)
3859                 {
3860                         MethodBase candidate = method;
3861
3862                         AParametersCollection pd = TypeManager.GetParameterData (candidate);
3863                         int param_count = GetApplicableParametersCount (candidate, pd);
3864                         int optional_count = 0;
3865
3866                         if (arg_count != param_count) {
3867                                 for (int i = 0; i < pd.Count; ++i) {
3868                                         if (pd.FixedParameters [i].HasDefaultValue) {
3869                                                 optional_count = pd.Count - i;
3870                                                 break;
3871                                         }
3872                                 }
3873
3874                                 int args_gap = Math.Abs (arg_count - param_count);
3875                                 if (optional_count != 0) {
3876                                         if (args_gap > optional_count)
3877                                                 return int.MaxValue - 10000 + args_gap - optional_count;
3878
3879                                         // Readjust expected number when params used
3880                                         if (pd.HasParams) {
3881                                                 optional_count--;
3882                                                 if (arg_count < param_count)
3883                                                         param_count--;
3884                                         } else if (arg_count > param_count) {
3885                                                 return int.MaxValue - 10000 + args_gap;
3886                                         }
3887                                 } else if (arg_count != param_count) {
3888                                         if (!pd.HasParams)
3889                                                 return int.MaxValue - 10000 + args_gap;
3890                                         if (arg_count < param_count - 1)
3891                                                 return int.MaxValue - 10000 + args_gap;
3892                                 }
3893
3894                                 // Initialize expanded form of a method with 1 params parameter
3895                                 params_expanded_form = param_count == 1 && pd.HasParams;
3896
3897                                 // Resize to fit optional arguments
3898                                 if (optional_count != 0) {
3899                                         Arguments resized;
3900                                         if (arguments == null) {
3901                                                 resized = new Arguments (optional_count);
3902                                         } else {
3903                                                 resized = new Arguments (param_count);
3904                                                 resized.AddRange (arguments);
3905                                         }
3906
3907                                         for (int i = arg_count; i < param_count; ++i)
3908                                                 resized.Add (null);
3909                                         arguments = resized;
3910                                 }
3911                         }
3912
3913                         if (arg_count > 0) {
3914                                 //
3915                                 // Shuffle named arguments to the right positions if there are any
3916                                 //
3917                                 if (arguments [arg_count - 1] is NamedArgument) {
3918                                         arg_count = arguments.Count;
3919
3920                                         for (int i = 0; i < arg_count; ++i) {
3921                                                 bool arg_moved = false;
3922                                                 while (true) {
3923                                                         NamedArgument na = arguments[i] as NamedArgument;
3924                                                         if (na == null)
3925                                                                 break;
3926
3927                                                         int index = pd.GetParameterIndexByName (na.Name.Value);
3928
3929                                                         // Named parameter not found or already reordered
3930                                                         if (index <= i)
3931                                                                 break;
3932
3933                                                         // When using parameters which should not be available to the user
3934                                                         if (index >= param_count)
3935                                                                 break;
3936
3937                                                         if (!arg_moved) {
3938                                                                 arguments.MarkReorderedArgument (na);
3939                                                                 arg_moved = true;
3940                                                         }
3941
3942                                                         Argument temp = arguments[index];
3943                                                         arguments[index] = arguments[i];
3944                                                         arguments[i] = temp;
3945
3946                                                         if (temp == null)
3947                                                                 break;
3948                                                 }
3949                                         }
3950                                 } else {
3951                                         arg_count = arguments.Count;
3952                                 }
3953                         } else if (arguments != null) {
3954                                 arg_count = arguments.Count;
3955                         }
3956
3957                         //
3958                         // 1. Handle generic method using type arguments when specified or type inference
3959                         //
3960                         if (TypeManager.IsGenericMethod (candidate)) {
3961                                 if (type_arguments != null) {
3962                                         Type [] g_args = candidate.GetGenericArguments ();
3963                                         if (g_args.Length != type_arguments.Count)
3964                                                 return int.MaxValue - 20000 + Math.Abs (type_arguments.Count - g_args.Length);
3965
3966                                         // TODO: Don't create new method, create Parameters only
3967                                         method = ((MethodInfo) candidate).MakeGenericMethod (type_arguments.Arguments);
3968                                         candidate = method;
3969                                         pd = TypeManager.GetParameterData (candidate);
3970                                 } else {
3971                                         int score = TypeManager.InferTypeArguments (ec, arguments, ref candidate);
3972                                         if (score != 0)
3973                                                 return score - 20000;
3974
3975                                         if (TypeManager.IsGenericMethodDefinition (candidate))
3976                                                 throw new InternalErrorException ("A generic method `{0}' definition took part in overload resolution",
3977                                                         TypeManager.CSharpSignature (candidate));
3978
3979                                         pd = TypeManager.GetParameterData (candidate);
3980                                 }
3981                         } else {
3982                                 if (type_arguments != null)
3983                                         return int.MaxValue - 15000;
3984                         }
3985
3986                         //
3987                         // 2. Each argument has to be implicitly convertible to method parameter
3988                         //
3989                         method = candidate;
3990                         Parameter.Modifier p_mod = 0;
3991                         Type pt = null;
3992                         for (int i = 0; i < arg_count; i++) {
3993                                 Argument a = arguments [i];
3994                                 if (a == null) {
3995                                         if (!pd.FixedParameters [i].HasDefaultValue)
3996                                                 throw new InternalErrorException ();
3997
3998                                         Expression e = pd.FixedParameters [i].DefaultValue as Constant;
3999                                         if (e == null)
4000                                                 e = new DefaultValueExpression (new TypeExpression (pd.Types [i], loc), loc).Resolve (ec);
4001
4002                                         arguments [i] = new Argument (e, Argument.AType.Default);
4003                                         continue;
4004                                 }
4005
4006                                 if (p_mod != Parameter.Modifier.PARAMS) {
4007                                         p_mod = pd.FixedParameters [i].ModFlags & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
4008                                         pt = pd.Types [i];
4009                                 } else {
4010                                         params_expanded_form = true;
4011                                 }
4012
4013                                 Parameter.Modifier a_mod = a.Modifier & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
4014                                 int score = 1;
4015                                 if (!params_expanded_form)
4016                                         score = IsArgumentCompatible (ec, a_mod, a, p_mod & ~Parameter.Modifier.PARAMS, pt);
4017
4018                                 if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && delegate_type == null) {
4019                                         // It can be applicable in expanded form
4020                                         score = IsArgumentCompatible (ec, a_mod, a, 0, TypeManager.GetElementType (pt));
4021                                         if (score == 0)
4022                                                 params_expanded_form = true;
4023                                 }
4024
4025                                 if (score != 0) {
4026                                         if (params_expanded_form)
4027                                                 ++score;
4028                                         return (arg_count - i) * 2 + score;
4029                                 }
4030                         }
4031                         
4032                         if (arg_count != param_count)
4033                                 params_expanded_form = true;    
4034                         
4035                         return 0;
4036                 }
4037
4038                 int IsArgumentCompatible (ResolveContext ec, Parameter.Modifier arg_mod, Argument argument, Parameter.Modifier param_mod, Type parameter)
4039                 {
4040                         //
4041                         // Types have to be identical when ref or out modifer is used 
4042                         //
4043                         if (arg_mod != 0 || param_mod != 0) {
4044                                 if (TypeManager.HasElementType (parameter))
4045                                         parameter = TypeManager.GetElementType (parameter);
4046
4047                                 Type a_type = argument.Type;
4048                                 if (TypeManager.HasElementType (a_type))
4049                                         a_type = TypeManager.GetElementType (a_type);
4050
4051                                 if (a_type != parameter)
4052                                         return 2;
4053                         } else {
4054                                 if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter))
4055                                         return 2;
4056                         }
4057
4058                         if (arg_mod != param_mod)
4059                                 return 1;
4060
4061                         return 0;
4062                 }
4063
4064                 public static bool IsOverride (MethodBase cand_method, MethodBase base_method)
4065                 {
4066                         if (!IsAncestralType (base_method.DeclaringType, cand_method.DeclaringType))
4067                                 return false;
4068
4069                         AParametersCollection cand_pd = TypeManager.GetParameterData (cand_method);
4070                         AParametersCollection base_pd = TypeManager.GetParameterData (base_method);
4071                 
4072                         if (cand_pd.Count != base_pd.Count)
4073                                 return false;
4074
4075                         for (int j = 0; j < cand_pd.Count; ++j) 
4076                         {
4077                                 Parameter.Modifier cm = cand_pd.FixedParameters [j].ModFlags;
4078                                 Parameter.Modifier bm = base_pd.FixedParameters [j].ModFlags;
4079                                 Type ct = cand_pd.Types [j];
4080                                 Type bt = base_pd.Types [j];
4081
4082                                 if (cm != bm || ct != bt)
4083                                         return false;
4084                         }
4085
4086                         return true;
4087                 }
4088
4089                 public static MethodGroupExpr MakeUnionSet (MethodGroupExpr mg1, MethodGroupExpr mg2, Location loc)
4090                 {
4091                         if (mg1 == null) {
4092                                 if (mg2 == null)
4093                                         return null;
4094                                 return mg2;
4095                         }
4096
4097                         if (mg2 == null)
4098                                 return mg1;
4099                         
4100                         ArrayList all = new ArrayList (mg1.Methods);
4101                         foreach (MethodBase m in mg2.Methods){
4102                                 if (!TypeManager.ArrayContainsMethod (mg1.Methods, m, false))
4103                                         all.Add (m);
4104                         }
4105
4106                         return new MethodGroupExpr (all, null, loc);
4107                 }               
4108
4109                 static Type MoreSpecific (Type p, Type q)
4110                 {
4111                         if (TypeManager.IsGenericParameter (p) && !TypeManager.IsGenericParameter (q))
4112                                 return q;
4113                         if (!TypeManager.IsGenericParameter (p) && TypeManager.IsGenericParameter (q))
4114                                 return p;
4115
4116                         if (TypeManager.HasElementType (p)) 
4117                         {
4118                                 Type pe = TypeManager.GetElementType (p);
4119                                 Type qe = TypeManager.GetElementType (q);
4120                                 Type specific = MoreSpecific (pe, qe);
4121                                 if (specific == pe)
4122                                         return p;
4123                                 if (specific == qe)
4124                                         return q;
4125                         } 
4126                         else if (TypeManager.IsGenericType (p)) 
4127                         {
4128                                 Type[] pargs = TypeManager.GetTypeArguments (p);
4129                                 Type[] qargs = TypeManager.GetTypeArguments (q);
4130
4131                                 bool p_specific_at_least_once = false;
4132                                 bool q_specific_at_least_once = false;
4133
4134                                 for (int i = 0; i < pargs.Length; i++) 
4135                                 {
4136                                         Type specific = MoreSpecific (TypeManager.TypeToCoreType (pargs [i]), TypeManager.TypeToCoreType (qargs [i]));
4137                                         if (specific == pargs [i])
4138                                                 p_specific_at_least_once = true;
4139                                         if (specific == qargs [i])
4140                                                 q_specific_at_least_once = true;
4141                                 }
4142
4143                                 if (p_specific_at_least_once && !q_specific_at_least_once)
4144                                         return p;
4145                                 if (!p_specific_at_least_once && q_specific_at_least_once)
4146                                         return q;
4147                         }
4148
4149                         return null;
4150                 }
4151
4152                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
4153                 {
4154                         base.MutateHoistedGenericType (storey);
4155
4156                         MethodInfo mi = best_candidate as MethodInfo;
4157                         if (mi != null) {
4158                                 best_candidate = storey.MutateGenericMethod (mi);
4159                                 return;
4160                         }
4161
4162                         best_candidate = storey.MutateConstructor ((ConstructorInfo) this);
4163                 }
4164
4165                 /// <summary>
4166                 ///   Find the Applicable Function Members (7.4.2.1)
4167                 ///
4168                 ///   me: Method Group expression with the members to select.
4169                 ///       it might contain constructors or methods (or anything
4170                 ///       that maps to a method).
4171                 ///
4172                 ///   Arguments: ArrayList containing resolved Argument objects.
4173                 ///
4174                 ///   loc: The location if we want an error to be reported, or a Null
4175                 ///        location for "probing" purposes.
4176                 ///
4177                 ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
4178                 ///            that is the best match of me on Arguments.
4179                 ///
4180                 /// </summary>
4181                 public virtual MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments Arguments,
4182                         bool may_fail, Location loc)
4183                 {
4184                         bool method_params = false;
4185                         Type applicable_type = null;
4186                         ArrayList candidates = new ArrayList (2);
4187                         ArrayList candidate_overrides = null;
4188
4189                         //
4190                         // Used to keep a map between the candidate
4191                         // and whether it is being considered in its
4192                         // normal or expanded form
4193                         //
4194                         // false is normal form, true is expanded form
4195                         //
4196                         Hashtable candidate_to_form = null;
4197                         Hashtable candidates_expanded = null;
4198                         Arguments candidate_args = Arguments;
4199
4200                         int arg_count = Arguments != null ? Arguments.Count : 0;
4201
4202                         if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
4203                                 if (!may_fail)
4204                                         ec.Report.Error (1533, loc, "Invoke cannot be called directly on a delegate");
4205                                 return null;
4206                         }
4207
4208                         int nmethods = Methods.Length;
4209
4210                         if (!IsBase) {
4211                                 //
4212                                 // Methods marked 'override' don't take part in 'applicable_type'
4213                                 // computation, nor in the actual overload resolution.
4214                                 // However, they still need to be emitted instead of a base virtual method.
4215                                 // So, we salt them away into the 'candidate_overrides' array.
4216                                 //
4217                                 // In case of reflected methods, we replace each overriding method with
4218                                 // its corresponding base virtual method.  This is to improve compatibility
4219                                 // with non-C# libraries which change the visibility of overrides (#75636)
4220                                 //
4221                                 int j = 0;
4222                                 for (int i = 0; i < Methods.Length; ++i) {
4223                                         MethodBase m = Methods [i];
4224                                         if (TypeManager.IsOverride (m)) {
4225                                                 if (candidate_overrides == null)
4226                                                         candidate_overrides = new ArrayList ();
4227                                                 candidate_overrides.Add (m);
4228                                                 m = TypeManager.TryGetBaseDefinition (m);
4229                                         }
4230                                         if (m != null)
4231                                                 Methods [j++] = m;
4232                                 }
4233                                 nmethods = j;
4234                         }
4235
4236                         //
4237                         // Enable message recording, it's used mainly by lambda expressions
4238                         //
4239                         SessionReportPrinter msg_recorder = new SessionReportPrinter ();
4240                         ReportPrinter prev_recorder = ec.Report.SetPrinter (msg_recorder);
4241
4242                         //
4243                         // First we construct the set of applicable methods
4244                         //
4245                         bool is_sorted = true;
4246                         int best_candidate_rate = int.MaxValue;
4247                         for (int i = 0; i < nmethods; i++) {
4248                                 Type decl_type = Methods [i].DeclaringType;
4249
4250                                 //
4251                                 // If we have already found an applicable method
4252                                 // we eliminate all base types (Section 14.5.5.1)
4253                                 //
4254                                 if (applicable_type != null && IsAncestralType (decl_type, applicable_type))
4255                                         continue;
4256
4257                                 //
4258                                 // Check if candidate is applicable (section 14.4.2.1)
4259                                 //
4260                                 bool params_expanded_form = false;
4261                                 int candidate_rate = IsApplicable (ec, ref candidate_args, arg_count, ref Methods [i], ref params_expanded_form);
4262
4263                                 if (candidate_rate < best_candidate_rate) {
4264                                         best_candidate_rate = candidate_rate;
4265                                         best_candidate = Methods [i];
4266                                 }
4267                                 
4268                                 if (params_expanded_form) {
4269                                         if (candidate_to_form == null)
4270                                                 candidate_to_form = new PtrHashtable ();
4271                                         MethodBase candidate = Methods [i];
4272                                         candidate_to_form [candidate] = candidate;
4273                                 }
4274                                 
4275                                 if (candidate_args != Arguments) {
4276                                         if (candidates_expanded == null)
4277                                                 candidates_expanded = new Hashtable (2);
4278
4279                                         candidates_expanded.Add (Methods [i], candidate_args);
4280                                         candidate_args = Arguments;
4281                                 }
4282
4283                                 if (candidate_rate != 0 || has_inaccessible_candidates_only) {
4284                                         if (msg_recorder != null)
4285                                                 msg_recorder.EndSession ();
4286                                         continue;
4287                                 }
4288
4289                                 msg_recorder = null;
4290                                 candidates.Add (Methods [i]);
4291
4292                                 if (applicable_type == null)
4293                                         applicable_type = decl_type;
4294                                 else if (applicable_type != decl_type) {
4295                                         is_sorted = false;
4296                                         if (IsAncestralType (applicable_type, decl_type))
4297                                                 applicable_type = decl_type;
4298                                 }
4299                         }
4300
4301                         ec.Report.SetPrinter (prev_recorder);
4302                         if (msg_recorder != null && !msg_recorder.IsEmpty) {
4303                                 if (!may_fail)
4304                                         msg_recorder.Merge (prev_recorder);
4305
4306                                 return null;
4307                         }
4308                         
4309                         int candidate_top = candidates.Count;
4310
4311                         if (applicable_type == null) {
4312                                 //
4313                                 // When we found a top level method which does not match and it's 
4314                                 // not an extension method. We start extension methods lookup from here
4315                                 //
4316                                 if (InstanceExpression != null) {
4317                                         ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (type, Name, loc);
4318                                         if (ex_method_lookup != null) {
4319                                                 ex_method_lookup.ExtensionExpression = InstanceExpression;
4320                                                 ex_method_lookup.SetTypeArguments (ec, type_arguments);
4321                                                 return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc);
4322                                         }
4323                                 }
4324                                 
4325                                 if (may_fail)
4326                                         return null;
4327
4328                                 //
4329                                 // Okay so we have failed to find exact match so we
4330                                 // return error info about the closest match
4331                                 //
4332                                 if (best_candidate != null) {
4333                                         if (CustomErrorHandler != null && !has_inaccessible_candidates_only && CustomErrorHandler.NoExactMatch (ec, best_candidate))
4334                                                 return null;
4335
4336                                         AParametersCollection pd = TypeManager.GetParameterData (best_candidate);
4337                                         bool cand_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
4338                                         if (arg_count == pd.Count || pd.HasParams) {
4339                                                 if (TypeManager.IsGenericMethodDefinition (best_candidate)) {
4340                                                         if (type_arguments == null) {
4341                                                                 ec.Report.Error (411, loc,
4342                                                                         "The type arguments for method `{0}' cannot be inferred from " +
4343                                                                         "the usage. Try specifying the type arguments explicitly",
4344                                                                         TypeManager.CSharpSignature (best_candidate));
4345                                                                 return null;
4346                                                         }
4347
4348                                                         Type[] g_args = TypeManager.GetGenericArguments (best_candidate);
4349                                                         if (type_arguments.Count != g_args.Length) {
4350                                                                 ec.Report.SymbolRelatedToPreviousError (best_candidate);
4351                                                                 ec.Report.Error (305, loc, "Using the generic method `{0}' requires `{1}' type argument(s)",
4352                                                                         TypeManager.CSharpSignature (best_candidate),
4353                                                                         g_args.Length.ToString ());
4354                                                                 return null;
4355                                                         }
4356                                                 } else {
4357                                                         if (type_arguments != null && !TypeManager.IsGenericMethod (best_candidate)) {
4358                                                                 Error_TypeArgumentsCannotBeUsed (ec.Report, loc);
4359                                                                 return null;
4360                                                         }
4361                                                 }
4362
4363                                                 if (has_inaccessible_candidates_only) {
4364                                                         if (InstanceExpression != null && type != ec.CurrentType && TypeManager.IsNestedFamilyAccessible (ec.CurrentType, best_candidate.DeclaringType)) {
4365                                                                 // Although a derived class can access protected members of
4366                                                                 // its base class it cannot do so through an instance of the
4367                                                                 // base class (CS1540).  If the qualifier_type is a base of the
4368                                                                 // ec.CurrentType and the lookup succeeds with the latter one,
4369                                                                 // then we are in this situation.
4370                                                                 Error_CannotAccessProtected (ec, loc, best_candidate, queried_type, ec.CurrentType);
4371                                                         } else {
4372                                                                 ec.Report.SymbolRelatedToPreviousError (best_candidate);
4373                                                                 ErrorIsInaccesible (loc, GetSignatureForError (), ec.Report);
4374                                                         }
4375                                                 }
4376
4377                                                 if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, cand_params, may_fail, loc))
4378                                                         return null;
4379
4380                                                 if (has_inaccessible_candidates_only)
4381                                                         return null;
4382
4383                                                 throw new InternalErrorException ("VerifyArgumentsCompat didn't find any problem with rejected candidate " + best_candidate);
4384                                         }
4385                                 }
4386
4387                                 //
4388                                 // We failed to find any method with correct argument count
4389                                 //
4390                                 if (Name == ConstructorInfo.ConstructorName) {
4391                                         ec.Report.SymbolRelatedToPreviousError (queried_type);
4392                                         ec.Report.Error (1729, loc,
4393                                                 "The type `{0}' does not contain a constructor that takes `{1}' arguments",
4394                                                 TypeManager.CSharpName (queried_type), arg_count);
4395                                 } else {
4396                                         Error_ArgumentCountWrong (ec, arg_count);
4397                                 }
4398                                 
4399                                 return null;
4400                         }
4401
4402                         if (!is_sorted) {
4403                                 //
4404                                 // At this point, applicable_type is _one_ of the most derived types
4405                                 // in the set of types containing the methods in this MethodGroup.
4406                                 // Filter the candidates so that they only contain methods from the
4407                                 // most derived types.
4408                                 //
4409
4410                                 int finalized = 0; // Number of finalized candidates
4411
4412                                 do {
4413                                         // Invariant: applicable_type is a most derived type
4414                                         
4415                                         // We'll try to complete Section 14.5.5.1 for 'applicable_type' by 
4416                                         // eliminating all it's base types.  At the same time, we'll also move
4417                                         // every unrelated type to the end of the array, and pick the next
4418                                         // 'applicable_type'.
4419
4420                                         Type next_applicable_type = null;
4421                                         int j = finalized; // where to put the next finalized candidate
4422                                         int k = finalized; // where to put the next undiscarded candidate
4423                                         for (int i = finalized; i < candidate_top; ++i) {
4424                                                 MethodBase candidate = (MethodBase) candidates [i];
4425                                                 Type decl_type = candidate.DeclaringType;
4426
4427                                                 if (decl_type == applicable_type) {
4428                                                         candidates [k++] = candidates [j];
4429                                                         candidates [j++] = candidates [i];
4430                                                         continue;
4431                                                 }
4432
4433                                                 if (IsAncestralType (decl_type, applicable_type))
4434                                                         continue;
4435
4436                                                 if (next_applicable_type != null &&
4437                                                         IsAncestralType (decl_type, next_applicable_type))
4438                                                         continue;
4439
4440                                                 candidates [k++] = candidates [i];
4441
4442                                                 if (next_applicable_type == null ||
4443                                                         IsAncestralType (next_applicable_type, decl_type))
4444                                                         next_applicable_type = decl_type;
4445                                         }
4446
4447                                         applicable_type = next_applicable_type;
4448                                         finalized = j;
4449                                         candidate_top = k;
4450                                 } while (applicable_type != null);
4451                         }
4452
4453                         //
4454                         // Now we actually find the best method
4455                         //
4456
4457                         best_candidate = (MethodBase) candidates [0];
4458                         method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
4459
4460                         //
4461                         // TODO: Broken inverse order of candidates logic does not work with optional
4462                         // parameters used for method overrides and I am not going to fix it for SRE
4463                         //
4464                         if (candidates_expanded != null && candidates_expanded.Contains (best_candidate)) {
4465                                 candidate_args = (Arguments) candidates_expanded [best_candidate];
4466                                 arg_count = candidate_args.Count;
4467                         }
4468
4469                         for (int ix = 1; ix < candidate_top; ix++) {
4470                                 MethodBase candidate = (MethodBase) candidates [ix];
4471
4472                                 if (candidate == best_candidate)
4473                                         continue;
4474
4475                                 bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
4476
4477                                 if (BetterFunction (ec, candidate_args, arg_count, 
4478                                         candidate, cand_params,
4479                                         best_candidate, method_params)) {
4480                                         best_candidate = candidate;
4481                                         method_params = cand_params;
4482                                 }
4483                         }
4484                         //
4485                         // Now check that there are no ambiguities i.e the selected method
4486                         // should be better than all the others
4487                         //
4488                         MethodBase ambiguous = null;
4489                         for (int ix = 1; ix < candidate_top; ix++) {
4490                                 MethodBase candidate = (MethodBase) candidates [ix];
4491
4492                                 if (candidate == best_candidate)
4493                                         continue;
4494
4495                                 bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
4496                                 if (!BetterFunction (ec, candidate_args, arg_count,
4497                                         best_candidate, method_params,
4498                                         candidate, cand_params)) 
4499                                 {
4500                                         if (!may_fail)
4501                                                 ec.Report.SymbolRelatedToPreviousError (candidate);
4502                                         ambiguous = candidate;
4503                                 }
4504                         }
4505
4506                         if (ambiguous != null) {
4507                                 Error_AmbiguousCall (ec, ambiguous);
4508                                 return this;
4509                         }
4510
4511                         //
4512                         // If the method is a virtual function, pick an override closer to the LHS type.
4513                         //
4514                         if (!IsBase && best_candidate.IsVirtual) {
4515                                 if (TypeManager.IsOverride (best_candidate))
4516                                         throw new InternalErrorException (
4517                                                 "Should not happen.  An 'override' method took part in overload resolution: " + best_candidate);
4518
4519                                 if (candidate_overrides != null) {
4520                                         Type[] gen_args = null;
4521                                         bool gen_override = false;
4522                                         if (TypeManager.IsGenericMethod (best_candidate))
4523                                                 gen_args = TypeManager.GetGenericArguments (best_candidate);
4524
4525                                         foreach (MethodBase candidate in candidate_overrides) {
4526                                                 if (TypeManager.IsGenericMethod (candidate)) {
4527                                                         if (gen_args == null)
4528                                                                 continue;
4529
4530                                                         if (gen_args.Length != TypeManager.GetGenericArguments (candidate).Length)
4531                                                                 continue;
4532                                                 } else {
4533                                                         if (gen_args != null)
4534                                                                 continue;
4535                                                 }
4536                                                 
4537                                                 if (IsOverride (candidate, best_candidate)) {
4538                                                         gen_override = true;
4539                                                         best_candidate = candidate;
4540                                                 }
4541                                         }
4542
4543                                         if (gen_override && gen_args != null) {
4544                                                 best_candidate = ((MethodInfo) best_candidate).MakeGenericMethod (gen_args);
4545                                         }
4546                                 }
4547                         }
4548
4549                         //
4550                         // And now check if the arguments are all
4551                         // compatible, perform conversions if
4552                         // necessary etc. and return if everything is
4553                         // all right
4554                         //
4555                         if (!VerifyArgumentsCompat (ec, ref candidate_args, arg_count, best_candidate,
4556                                 method_params, may_fail, loc))
4557                                 return null;
4558
4559                         if (best_candidate == null)
4560                                 return null;
4561
4562                         MethodBase the_method = TypeManager.DropGenericMethodArguments (best_candidate);
4563                         if (TypeManager.IsGenericMethodDefinition (the_method) &&
4564                             !ConstraintChecker.CheckConstraints (ec, the_method, best_candidate, loc))
4565                                 return null;
4566
4567                         //
4568                         // Check ObsoleteAttribute on the best method
4569                         //
4570                         ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (the_method);
4571                         if (oa != null && !ec.IsObsolete)
4572                                 AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
4573
4574                         IMethodData data = TypeManager.GetMethod (the_method);
4575                         if (data != null)
4576                                 data.SetMemberIsUsed ();
4577
4578                         Arguments = candidate_args;
4579                         return this;
4580                 }
4581                 
4582                 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
4583                 {
4584                         type_arguments = ta;
4585                 }
4586
4587                 public bool VerifyArgumentsCompat (ResolveContext ec, ref Arguments arguments,
4588                                                           int arg_count, MethodBase method,
4589                                                           bool chose_params_expanded,
4590                                                           bool may_fail, Location loc)
4591                 {
4592                         AParametersCollection pd = TypeManager.GetParameterData (method);
4593                         int param_count = GetApplicableParametersCount (method, pd);
4594
4595                         int errors = ec.Report.Errors;
4596                         Parameter.Modifier p_mod = 0;
4597                         Type pt = null;
4598                         int a_idx = 0, a_pos = 0;
4599                         Argument a = null;
4600                         ArrayList params_initializers = null;
4601                         bool has_unsafe_arg = method is MethodInfo ? ((MethodInfo) method).ReturnType.IsPointer : false;
4602
4603                         for (; a_idx < arg_count; a_idx++, ++a_pos) {
4604                                 a = arguments [a_idx];
4605                                 if (p_mod != Parameter.Modifier.PARAMS) {
4606                                         p_mod = pd.FixedParameters [a_idx].ModFlags;
4607                                         pt = pd.Types [a_idx];
4608                                         has_unsafe_arg |= pt.IsPointer;
4609
4610                                         if (p_mod == Parameter.Modifier.PARAMS) {
4611                                                 if (chose_params_expanded) {
4612                                                         params_initializers = new ArrayList (arg_count - a_idx);
4613                                                         pt = TypeManager.GetElementType (pt);
4614                                                 }
4615                                         }
4616                                 }
4617
4618                                 //
4619                                 // Types have to be identical when ref or out modifer is used 
4620                                 //
4621                                 if (a.Modifier != 0 || (p_mod & ~Parameter.Modifier.PARAMS) != 0) {
4622                                         if ((p_mod & ~Parameter.Modifier.PARAMS) != a.Modifier)
4623                                                 break;
4624
4625                                         if (!TypeManager.IsEqual (a.Expr.Type, pt))
4626                                                 break;
4627
4628                                         continue;
4629                                 } else {
4630                                         NamedArgument na = a as NamedArgument;
4631                                         if (na != null) {
4632                                                 int name_index = pd.GetParameterIndexByName (na.Name.Value);
4633                                                 if (name_index < 0 || name_index >= param_count) {
4634                                                         if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType)) {
4635                                                                 ec.Report.SymbolRelatedToPreviousError (DeclaringType);
4636                                                                 ec.Report.Error (1746, na.Name.Location,
4637                                                                         "The delegate `{0}' does not contain a parameter named `{1}'",
4638                                                                         TypeManager.CSharpName (DeclaringType), na.Name.Value);
4639                                                         } else {
4640                                                                 ec.Report.SymbolRelatedToPreviousError (best_candidate);
4641                                                                 ec.Report.Error (1739, na.Name.Location,
4642                                                                         "The best overloaded method match for `{0}' does not contain a parameter named `{1}'",
4643                                                                         TypeManager.CSharpSignature (method), na.Name.Value);
4644                                                         }
4645                                                 } else if (arguments[name_index] != a) {
4646                                                         if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType))
4647                                                                 ec.Report.SymbolRelatedToPreviousError (DeclaringType);
4648                                                         else
4649                                                                 ec.Report.SymbolRelatedToPreviousError (best_candidate);
4650
4651                                                         ec.Report.Error (1744, na.Name.Location,
4652                                                                 "Named argument `{0}' cannot be used for a parameter which has positional argument specified",
4653                                                                 na.Name.Value);
4654                                                 }
4655                                         }
4656                                 }
4657
4658                                 if (delegate_type != null && !Delegate.IsTypeCovariant (a.Expr, pt))
4659                                         break;
4660
4661                                 Expression conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc);
4662                                 if (conv == null)
4663                                         break;
4664
4665                                 //
4666                                 // Convert params arguments to an array initializer
4667                                 //
4668                                 if (params_initializers != null) {
4669                                         // we choose to use 'a.Expr' rather than 'conv' so that
4670                                         // we don't hide the kind of expression we have (esp. CompoundAssign.Helper)
4671                                         params_initializers.Add (a.Expr);
4672                                         arguments.RemoveAt (a_idx--);
4673                                         --arg_count;
4674                                         continue;
4675                                 }
4676
4677                                 // Update the argument with the implicit conversion
4678                                 a.Expr = conv;
4679                         }
4680
4681                         if (a_idx != arg_count) {
4682                                 if (!may_fail && ec.Report.Errors == errors) {
4683                                         if (CustomErrorHandler != null)
4684                                                 CustomErrorHandler.NoExactMatch (ec, best_candidate);
4685                                         else
4686                                                 Error_InvalidArguments (ec, loc, a_pos, method, a, pd, pt);
4687                                 }
4688                                 return false;
4689                         }
4690
4691                         //
4692                         // Fill not provided arguments required by params modifier
4693                         //
4694                         if (params_initializers == null && pd.HasParams && arg_count + 1 == param_count) {
4695                                 if (arguments == null)
4696                                         arguments = new Arguments (1);
4697
4698                                 pt = pd.Types [param_count - 1];
4699                                 pt = TypeManager.GetElementType (pt);
4700                                 has_unsafe_arg |= pt.IsPointer;
4701                                 params_initializers = new ArrayList (0);
4702                         }
4703
4704                         //
4705                         // Append an array argument with all params arguments
4706                         //
4707                         if (params_initializers != null) {
4708                                 arguments.Add (new Argument (
4709                                                        new ArrayCreation (new TypeExpression (pt, loc), "[]",
4710                                                                           params_initializers, loc).Resolve (ec)));
4711                                 arg_count++;
4712                         }
4713
4714                         if (arg_count < param_count) {
4715                                 if (!may_fail)
4716                                         Error_ArgumentCountWrong (ec, arg_count);
4717                                 return false;
4718                         }
4719
4720                         if (has_unsafe_arg && !ec.IsUnsafe) {
4721                                 if (!may_fail)
4722                                         UnsafeError (ec, loc);
4723                                 return false;
4724                         }
4725
4726                         return true;
4727                 }
4728         }
4729
4730         public class ConstantExpr : MemberExpr
4731         {
4732                 FieldInfo constant;
4733
4734                 public ConstantExpr (FieldInfo constant, Location loc)
4735                 {
4736                         this.constant = constant;
4737                         this.loc = loc;
4738                 }
4739
4740                 public override string Name {
4741                         get { throw new NotImplementedException (); }
4742                 }
4743
4744                 public override bool IsInstance {
4745                         get { return !IsStatic; }
4746                 }
4747
4748                 public override bool IsStatic {
4749                         get { return constant.IsStatic; }
4750                 }
4751
4752                 public override Type DeclaringType {
4753                         get { return constant.DeclaringType; }
4754                 }
4755
4756                 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc, SimpleName original)
4757                 {
4758                         constant = TypeManager.GetGenericFieldDefinition (constant);
4759
4760                         IConstant ic = TypeManager.GetConstant (constant);
4761                         if (ic == null) {
4762                                 if (constant.IsLiteral) {
4763                                         ic = new ExternalConstant (constant);
4764                                 } else {
4765                                         ic = ExternalConstant.CreateDecimal (constant);
4766                                         // HACK: decimal field was not resolved as constant
4767                                         if (ic == null)
4768                                                 return new FieldExpr (constant, loc).ResolveMemberAccess (ec, left, loc, original);
4769                                 }
4770                                 TypeManager.RegisterConstant (constant, ic);
4771                         }
4772
4773                         return base.ResolveMemberAccess (ec, left, loc, original);
4774                 }
4775
4776                 public override Expression CreateExpressionTree (ResolveContext ec)
4777                 {
4778                         throw new NotSupportedException ("ET");
4779                 }
4780
4781                 public override Expression DoResolve (ResolveContext ec)
4782                 {
4783                         IConstant ic = TypeManager.GetConstant (constant);
4784                         if (ic.ResolveValue ()) {
4785                                 if (!ec.IsObsolete)
4786                                         ic.CheckObsoleteness (loc);
4787                         }
4788
4789                         return ic.CreateConstantReference (loc);
4790                 }
4791
4792                 public override void Emit (EmitContext ec)
4793                 {
4794                         throw new NotSupportedException ();
4795                 }
4796
4797                 public override string GetSignatureForError ()
4798                 {
4799                         return TypeManager.GetFullNameSignature (constant);
4800                 }
4801         }
4802
4803         /// <summary>
4804         ///   Fully resolved expression that evaluates to a Field
4805         /// </summary>
4806         public class FieldExpr : MemberExpr, IDynamicAssign, IMemoryLocation, IVariableReference {
4807                 public FieldInfo FieldInfo;
4808                 readonly Type constructed_generic_type;
4809                 VariableInfo variable_info;
4810                 
4811                 LocalTemporary temp;
4812                 bool prepared;
4813                 
4814                 protected FieldExpr (Location l)
4815                 {
4816                         loc = l;
4817                 }
4818                 
4819                 public FieldExpr (FieldInfo fi, Location l)
4820                 {
4821                         FieldInfo = fi;
4822                         type = TypeManager.TypeToCoreType (fi.FieldType);
4823                         loc = l;
4824                 }
4825
4826                 public FieldExpr (FieldInfo fi, Type genericType, Location l)
4827                         : this (fi, l)
4828                 {
4829                         if (TypeManager.IsGenericTypeDefinition (genericType))
4830                                 return;
4831                         this.constructed_generic_type = genericType;
4832                 }
4833
4834                 public override string Name {
4835                         get {
4836                                 return FieldInfo.Name;
4837                         }
4838                 }
4839
4840                 public override bool IsInstance {
4841                         get {
4842                                 return !FieldInfo.IsStatic;
4843                         }
4844                 }
4845
4846                 public override bool IsStatic {
4847                         get {
4848                                 return FieldInfo.IsStatic;
4849                         }
4850                 }
4851
4852                 public override Type DeclaringType {
4853                         get {
4854                                 return FieldInfo.DeclaringType;
4855                         }
4856                 }
4857
4858                 public override string GetSignatureForError ()
4859                 {
4860                         return TypeManager.GetFullNameSignature (FieldInfo);
4861                 }
4862
4863                 public VariableInfo VariableInfo {
4864                         get {
4865                                 return variable_info;
4866                         }
4867                 }
4868
4869                 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
4870                                                                 SimpleName original)
4871                 {
4872                         FieldInfo fi = TypeManager.GetGenericFieldDefinition (FieldInfo);
4873                         Type t = fi.FieldType;
4874
4875                         if (t.IsPointer && !ec.IsUnsafe) {
4876                                 UnsafeError (ec, loc);
4877                         }
4878
4879                         return base.ResolveMemberAccess (ec, left, loc, original);
4880                 }
4881
4882                 public void SetHasAddressTaken ()
4883                 {
4884                         IVariableReference vr = InstanceExpression as IVariableReference;
4885                         if (vr != null)
4886                                 vr.SetHasAddressTaken ();
4887                 }
4888
4889                 public override Expression CreateExpressionTree (ResolveContext ec)
4890                 {
4891                         Expression instance;
4892                         if (InstanceExpression == null) {
4893                                 instance = new NullLiteral (loc);
4894                         } else {
4895                                 instance = InstanceExpression.CreateExpressionTree (ec);
4896                         }
4897
4898                         Arguments args = Arguments.CreateForExpressionTree (ec, null,
4899                                 instance,
4900                                 CreateTypeOfExpression ());
4901
4902                         return CreateExpressionFactoryCall (ec, "Field", args);
4903                 }
4904
4905                 public Expression CreateTypeOfExpression ()
4906                 {
4907                         return new TypeOfField (GetConstructedFieldInfo (), loc);
4908                 }
4909
4910                 override public Expression DoResolve (ResolveContext ec)
4911                 {
4912                         return DoResolve (ec, false, false);
4913                 }
4914
4915                 Expression DoResolve (ResolveContext ec, bool lvalue_instance, bool out_access)
4916                 {
4917                         if (!FieldInfo.IsStatic){
4918                                 if (InstanceExpression == null){
4919                                         //
4920                                         // This can happen when referencing an instance field using
4921                                         // a fully qualified type expression: TypeName.InstanceField = xxx
4922                                         // 
4923                                         SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
4924                                         return null;
4925                                 }
4926
4927                                 // Resolve the field's instance expression while flow analysis is turned
4928                                 // off: when accessing a field "a.b", we must check whether the field
4929                                 // "a.b" is initialized, not whether the whole struct "a" is initialized.
4930
4931                                 if (lvalue_instance) {
4932                                         using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
4933                                                 Expression right_side =
4934                                                         out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
4935
4936                                                 if (InstanceExpression != EmptyExpression.Null)
4937                                                         InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
4938                                         }
4939                                 } else {
4940                                         ResolveFlags rf = ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis;
4941
4942                                         if (InstanceExpression != EmptyExpression.Null)
4943                                                 InstanceExpression = InstanceExpression.Resolve (ec, rf);
4944                                 }
4945
4946                                 if (InstanceExpression == null)
4947                                         return null;
4948
4949                                 using (ec.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
4950                                         InstanceExpression.CheckMarshalByRefAccess (ec);
4951                                 }
4952                         }
4953
4954                         // TODO: the code above uses some non-standard multi-resolve rules
4955                         if (eclass != ExprClass.Invalid)
4956                                 return this;
4957
4958                         if (!ec.IsObsolete) {
4959                                 FieldBase f = TypeManager.GetField (FieldInfo);
4960                                 if (f != null) {
4961                                         f.CheckObsoleteness (loc);
4962                                 } else {
4963                                         ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
4964                                         if (oa != null)
4965                                                 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc, ec.Report);
4966                                 }
4967                         }
4968
4969                         IFixedBuffer fb = AttributeTester.GetFixedBuffer (FieldInfo);
4970                         IVariableReference var = InstanceExpression as IVariableReference;
4971                         
4972                         if (fb != null) {
4973                                 IFixedExpression fe = InstanceExpression as IFixedExpression;
4974                                 if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) {
4975                                         ec.Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement");
4976                                 }
4977
4978                                 if (InstanceExpression.eclass != ExprClass.Variable) {
4979                                         ec.Report.SymbolRelatedToPreviousError (FieldInfo);
4980                                         ec.Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields",
4981                                                 TypeManager.GetFullNameSignature (FieldInfo));
4982                                 } else if (var != null && var.IsHoisted) {
4983                                         AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, var, loc);
4984                                 }
4985                                 
4986                                 return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec);
4987                         }
4988
4989                         eclass = ExprClass.Variable;
4990
4991                         // If the instance expression is a local variable or parameter.
4992                         if (var == null || var.VariableInfo == null)
4993                                 return this;
4994
4995                         VariableInfo vi = var.VariableInfo;
4996                         if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc))
4997                                 return null;
4998
4999                         variable_info = vi.GetSubStruct (FieldInfo.Name);
5000                         eclass = ExprClass.Variable;
5001                         return this;
5002                 }
5003
5004                 static readonly int [] codes = {
5005                         191,    // instance, write access
5006                         192,    // instance, out access
5007                         198,    // static, write access
5008                         199,    // static, out access
5009                         1648,   // member of value instance, write access
5010                         1649,   // member of value instance, out access
5011                         1650,   // member of value static, write access
5012                         1651    // member of value static, out access
5013                 };
5014
5015                 static readonly string [] msgs = {
5016                         /*0191*/ "A readonly field `{0}' cannot be assigned to (except in a constructor or a variable initializer)",
5017                         /*0192*/ "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
5018                         /*0198*/ "A static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
5019                         /*0199*/ "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
5020                         /*1648*/ "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)",
5021                         /*1649*/ "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)",
5022                         /*1650*/ "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
5023                         /*1651*/ "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)"
5024                 };
5025
5026                 // The return value is always null.  Returning a value simplifies calling code.
5027                 Expression Report_AssignToReadonly (ResolveContext ec, Expression right_side)
5028                 {
5029                         int i = 0;
5030                         if (right_side == EmptyExpression.OutAccess.Instance || right_side == EmptyExpression.LValueMemberOutAccess)
5031                                 i += 1;
5032                         if (IsStatic)
5033                                 i += 2;
5034                         if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess)
5035                                 i += 4;
5036                         ec.Report.Error (codes [i], loc, msgs [i], GetSignatureForError ());
5037
5038                         return null;
5039                 }
5040                 
5041                 override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
5042                 {
5043                         IVariableReference var = InstanceExpression as IVariableReference;
5044                         if (var != null && var.VariableInfo != null)
5045                                 var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
5046
5047                         bool lvalue_instance = !FieldInfo.IsStatic && TypeManager.IsValueType (FieldInfo.DeclaringType);
5048                         bool out_access = right_side == EmptyExpression.OutAccess.Instance || right_side == EmptyExpression.LValueMemberOutAccess;
5049
5050                         Expression e = DoResolve (ec, lvalue_instance, out_access);
5051
5052                         if (e == null)
5053                                 return null;
5054
5055                         FieldBase fb = TypeManager.GetField (FieldInfo);
5056                         if (fb != null) {
5057                                 fb.SetAssigned ();
5058
5059                                 if ((right_side == EmptyExpression.UnaryAddress || right_side == EmptyExpression.OutAccess.Instance) &&
5060                                         (fb.ModFlags & Modifiers.VOLATILE) != 0) {
5061                                         ec.Report.Warning (420, 1, loc,
5062                                                 "`{0}': A volatile field references will not be treated as volatile",
5063                                                 fb.GetSignatureForError ());
5064                                 }
5065                         }
5066
5067                         if (FieldInfo.IsInitOnly) {
5068                                 // InitOnly fields can only be assigned in constructors or initializers
5069                                 if (!ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.ConstructorScope))
5070                                         return Report_AssignToReadonly (ec, right_side);
5071
5072                                 if (ec.HasSet (ResolveContext.Options.ConstructorScope)) {
5073                                         Type ctype = ec.CurrentType;
5074
5075                                         // InitOnly fields cannot be assigned-to in a different constructor from their declaring type
5076                                         if (!TypeManager.IsEqual (ctype, FieldInfo.DeclaringType))
5077                                                 return Report_AssignToReadonly (ec, right_side);
5078                                         // static InitOnly fields cannot be assigned-to in an instance constructor
5079                                         if (IsStatic && !ec.IsStatic)
5080                                                 return Report_AssignToReadonly (ec, right_side);
5081                                         // instance constructors can't modify InitOnly fields of other instances of the same type
5082                                         if (!IsStatic && !(InstanceExpression is This))
5083                                                 return Report_AssignToReadonly (ec, right_side);
5084                                 }
5085                         }
5086
5087                         if (right_side == EmptyExpression.OutAccess.Instance &&
5088                             !IsStatic && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type)) {
5089                                 ec.Report.SymbolRelatedToPreviousError (DeclaringType);
5090                                 ec.Report.Warning (197, 1, loc,
5091                                                 "Passing `{0}' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class",
5092                                                 GetSignatureForError ());
5093                         }
5094
5095                         eclass = ExprClass.Variable;
5096                         return this;
5097                 }
5098
5099                 bool is_marshal_by_ref ()
5100                 {
5101                         return !IsStatic && TypeManager.IsStruct (Type) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type);
5102                 }
5103
5104                 public override void CheckMarshalByRefAccess (ResolveContext ec)
5105                 {
5106                         if (is_marshal_by_ref () && !(InstanceExpression is This)) {
5107                                 ec.Report.SymbolRelatedToPreviousError (DeclaringType);
5108                                 ec.Report.Warning (1690, 1, loc, "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
5109                                                 GetSignatureForError ());
5110                         }
5111                 }
5112
5113                 public override int GetHashCode ()
5114                 {
5115                         return FieldInfo.GetHashCode ();
5116                 }
5117                 
5118                 public bool IsFixed {
5119                         get {
5120                                 //
5121                                 // A variable of the form V.I is fixed when V is a fixed variable of a struct type
5122                                 //
5123                                 IVariableReference variable = InstanceExpression as IVariableReference;
5124                                 if (variable != null)
5125                                         return TypeManager.IsStruct (InstanceExpression.Type) && variable.IsFixed;
5126
5127                                 IFixedExpression fe = InstanceExpression as IFixedExpression;
5128                                 return fe != null && fe.IsFixed;
5129                         }
5130                 }
5131
5132                 public bool IsHoisted {
5133                         get {
5134                                 IVariableReference hv = InstanceExpression as IVariableReference;
5135                                 return hv != null && hv.IsHoisted;
5136                         }
5137                 }
5138
5139                 public override bool Equals (object obj)
5140                 {
5141                         FieldExpr fe = obj as FieldExpr;
5142                         if (fe == null)
5143                                 return false;
5144
5145                         if (FieldInfo != fe.FieldInfo)
5146                                 return false;
5147
5148                         if (InstanceExpression == null || fe.InstanceExpression == null)
5149                                 return true;
5150
5151                         return InstanceExpression.Equals (fe.InstanceExpression);
5152                 }
5153                 
5154                 public void Emit (EmitContext ec, bool leave_copy)
5155                 {
5156                         ILGenerator ig = ec.ig;
5157                         bool is_volatile = false;
5158
5159                         FieldBase f = TypeManager.GetField (FieldInfo);
5160                         if (f != null){
5161                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5162                                         is_volatile = true;
5163
5164                                 f.SetMemberIsUsed ();
5165                         }
5166                         
5167                         if (FieldInfo.IsStatic){
5168                                 if (is_volatile)
5169                                         ig.Emit (OpCodes.Volatile);
5170
5171                                 ig.Emit (OpCodes.Ldsfld, GetConstructedFieldInfo ());
5172                         } else {
5173                                 if (!prepared)
5174                                         EmitInstance (ec, false);
5175
5176                                 // Optimization for build-in types
5177                                 if (TypeManager.IsStruct (type) && TypeManager.IsEqual (type, ec.MemberContext.CurrentType)) {
5178                                         LoadFromPtr (ig, type);
5179                                 } else {
5180                                         IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
5181                                         if (ff != null) {
5182                                                 ig.Emit (OpCodes.Ldflda, GetConstructedFieldInfo ());
5183                                                 ig.Emit (OpCodes.Ldflda, ff.Element);
5184                                         } else {
5185                                                 if (is_volatile)
5186                                                         ig.Emit (OpCodes.Volatile);
5187
5188                                                 ig.Emit (OpCodes.Ldfld, GetConstructedFieldInfo ());
5189                                         }
5190                                 }
5191                         }
5192
5193                         if (leave_copy) {
5194                                 ec.ig.Emit (OpCodes.Dup);
5195                                 if (!FieldInfo.IsStatic) {
5196                                         temp = new LocalTemporary (this.Type);
5197                                         temp.Store (ec);
5198                                 }
5199                         }
5200                 }
5201
5202                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
5203                 {
5204                         FieldAttributes fa = FieldInfo.Attributes;
5205                         bool is_static = (fa & FieldAttributes.Static) != 0;
5206                         ILGenerator ig = ec.ig;
5207
5208                         prepared = prepare_for_load;
5209                         EmitInstance (ec, prepared);
5210
5211                         source.Emit (ec);
5212                         if (leave_copy) {
5213                                 ec.ig.Emit (OpCodes.Dup);
5214                                 if (!FieldInfo.IsStatic) {
5215                                         temp = new LocalTemporary (this.Type);
5216                                         temp.Store (ec);
5217                                 }
5218                         }
5219
5220                         FieldBase f = TypeManager.GetField (FieldInfo);
5221                         if (f != null){
5222                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5223                                         ig.Emit (OpCodes.Volatile);
5224                                         
5225                                 f.SetAssigned ();
5226                         }
5227
5228                         if (is_static)
5229                                 ig.Emit (OpCodes.Stsfld, GetConstructedFieldInfo ());
5230                         else
5231                                 ig.Emit (OpCodes.Stfld, GetConstructedFieldInfo ());
5232                         
5233                         if (temp != null) {
5234                                 temp.Emit (ec);
5235                                 temp.Release (ec);
5236                                 temp = null;
5237                         }
5238                 }
5239
5240                 public override void Emit (EmitContext ec)
5241                 {
5242                         Emit (ec, false);
5243                 }
5244
5245                 public override void EmitSideEffect (EmitContext ec)
5246                 {
5247                         FieldBase f = TypeManager.GetField (FieldInfo);
5248                         bool is_volatile = f != null && (f.ModFlags & Modifiers.VOLATILE) != 0;
5249
5250                         if (is_volatile || is_marshal_by_ref ())
5251                                 base.EmitSideEffect (ec);
5252                 }
5253
5254                 public override void Error_VariableIsUsedBeforeItIsDeclared (Report r, string name)
5255                 {
5256                         r.Error (844, loc,
5257                                 "A local variable `{0}' cannot be used before it is declared. Consider renaming the local variable when it hides the field `{1}'",
5258                                 name, GetSignatureForError ());
5259                 }
5260
5261                 public void AddressOf (EmitContext ec, AddressOp mode)
5262                 {
5263                         ILGenerator ig = ec.ig;
5264
5265                         FieldBase f = TypeManager.GetField (FieldInfo);
5266                         if (f != null){                         
5267                                 if ((mode & AddressOp.Store) != 0)
5268                                         f.SetAssigned ();
5269                                 if ((mode & AddressOp.Load) != 0)
5270                                         f.SetMemberIsUsed ();
5271                         }
5272
5273                         //
5274                         // Handle initonly fields specially: make a copy and then
5275                         // get the address of the copy.
5276                         //
5277                         bool need_copy;
5278                         if (FieldInfo.IsInitOnly){
5279                                 need_copy = true;
5280                                 if (ec.HasSet (EmitContext.Options.ConstructorScope)){
5281                                         if (FieldInfo.IsStatic){
5282                                                 if (ec.IsStatic)
5283                                                         need_copy = false;
5284                                         } else
5285                                                 need_copy = false;
5286                                 }
5287                         } else
5288                                 need_copy = false;
5289                         
5290                         if (need_copy){
5291                                 LocalBuilder local;
5292                                 Emit (ec);
5293                                 local = ig.DeclareLocal (type);
5294                                 ig.Emit (OpCodes.Stloc, local);
5295                                 ig.Emit (OpCodes.Ldloca, local);
5296                                 return;
5297                         }
5298
5299
5300                         if (FieldInfo.IsStatic){
5301                                 ig.Emit (OpCodes.Ldsflda, GetConstructedFieldInfo ());
5302                         } else {
5303                                 if (!prepared)
5304                                         EmitInstance (ec, false);
5305                                 ig.Emit (OpCodes.Ldflda, GetConstructedFieldInfo ());
5306                         }
5307                 }
5308
5309                 FieldInfo GetConstructedFieldInfo ()
5310                 {
5311                         if (constructed_generic_type == null)
5312                                 return FieldInfo;
5313
5314                         return TypeBuilder.GetField (constructed_generic_type, FieldInfo);
5315                 }
5316
5317 #if NET_4_0
5318                 public SLE.Expression MakeAssignExpression (BuilderContext ctx)
5319                 {
5320                         return MakeExpression (ctx);
5321                 }
5322
5323                 public override SLE.Expression MakeExpression (BuilderContext ctx)
5324                 {
5325                         return SLE.Expression.Field (InstanceExpression.MakeExpression (ctx), FieldInfo);
5326                 }
5327 #endif
5328                 
5329                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
5330                 {
5331                         FieldInfo = storey.MutateField (FieldInfo);
5332                         base.MutateHoistedGenericType (storey);
5333                 }               
5334         }
5335
5336         
5337         /// <summary>
5338         ///   Expression that evaluates to a Property.  The Assign class
5339         ///   might set the `Value' expression if we are in an assignment.
5340         ///
5341         ///   This is not an LValue because we need to re-write the expression, we
5342         ///   can not take data from the stack and store it.  
5343         /// </summary>
5344         public class PropertyExpr : MemberExpr, IDynamicAssign
5345         {
5346                 public readonly PropertyInfo PropertyInfo;
5347                 MethodInfo getter, setter;
5348                 bool is_static;
5349
5350                 bool resolved;
5351                 TypeArguments targs;
5352                 
5353                 LocalTemporary temp;
5354                 bool prepared;
5355
5356                 public PropertyExpr (Type container_type, PropertyInfo pi, Location l)
5357                 {
5358                         PropertyInfo = pi;
5359                         eclass = ExprClass.PropertyAccess;
5360                         is_static = false;
5361                         loc = l;
5362
5363                         type = TypeManager.TypeToCoreType (pi.PropertyType);
5364
5365                         ResolveAccessors (container_type);
5366                 }
5367
5368                 public override string Name {
5369                         get {
5370                                 return PropertyInfo.Name;
5371                         }
5372                 }
5373
5374                 public override bool IsInstance {
5375                         get {
5376                                 return !is_static;
5377                         }
5378                 }
5379
5380                 public override bool IsStatic {
5381                         get {
5382                                 return is_static;
5383                         }
5384                 }
5385
5386                 public override Expression CreateExpressionTree (ResolveContext ec)
5387                 {
5388                         Arguments args;
5389                         if (IsSingleDimensionalArrayLength ()) {
5390                                 args = new Arguments (1);
5391                                 args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
5392                                 return CreateExpressionFactoryCall (ec, "ArrayLength", args);
5393                         }
5394
5395                         if (is_base) {
5396                                 Error_BaseAccessInExpressionTree (ec, loc);
5397                                 return null;
5398                         }
5399
5400                         args = new Arguments (2);
5401                         if (InstanceExpression == null)
5402                                 args.Add (new Argument (new NullLiteral (loc)));
5403                         else
5404                                 args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
5405                         args.Add (new Argument (new TypeOfMethod (getter, loc)));
5406                         return CreateExpressionFactoryCall (ec, "Property", args);
5407                 }
5408
5409                 public Expression CreateSetterTypeOfExpression ()
5410                 {
5411                         return new TypeOfMethod (setter, loc);
5412                 }
5413
5414                 public override Type DeclaringType {
5415                         get {
5416                                 return PropertyInfo.DeclaringType;
5417                         }
5418                 }
5419
5420                 public override string GetSignatureForError ()
5421                 {
5422                         return TypeManager.GetFullNameSignature (PropertyInfo);
5423                 }
5424
5425                 void FindAccessors (Type invocation_type)
5426                 {
5427                         const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
5428                                 BindingFlags.Static | BindingFlags.Instance |
5429                                 BindingFlags.DeclaredOnly;
5430
5431                         Type current = PropertyInfo.DeclaringType;
5432                         for (; current != null; current = current.BaseType) {
5433                                 MemberInfo[] group = TypeManager.MemberLookup (
5434                                         invocation_type, invocation_type, current,
5435                                         MemberTypes.Property, flags, PropertyInfo.Name, null);
5436
5437                                 if (group == null)
5438                                         continue;
5439
5440                                 if (group.Length != 1)
5441                                         // Oooops, can this ever happen ?
5442                                         return;
5443
5444                                 PropertyInfo pi = (PropertyInfo) group [0];
5445
5446                                 if (getter == null)
5447                                         getter = pi.GetGetMethod (true);
5448
5449                                 if (setter == null)
5450                                         setter = pi.GetSetMethod (true);
5451
5452                                 MethodInfo accessor = getter != null ? getter : setter;
5453
5454                                 if (!accessor.IsVirtual)
5455                                         return;
5456                         }
5457                 }
5458
5459                 //
5460                 // We also perform the permission checking here, as the PropertyInfo does not
5461                 // hold the information for the accessibility of its setter/getter
5462                 //
5463                 // TODO: Refactor to use some kind of cache together with GetPropertyFromAccessor
5464                 void ResolveAccessors (Type container_type)
5465                 {
5466                         FindAccessors (container_type);
5467
5468                         if (getter != null) {
5469                                 MethodBase the_getter = TypeManager.DropGenericMethodArguments (getter);
5470                                 IMethodData md = TypeManager.GetMethod (the_getter);
5471                                 if (md != null)
5472                                         md.SetMemberIsUsed ();
5473
5474                                 is_static = getter.IsStatic;
5475                         }
5476
5477                         if (setter != null) {
5478                                 MethodBase the_setter = TypeManager.DropGenericMethodArguments (setter);
5479                                 IMethodData md = TypeManager.GetMethod (the_setter);
5480                                 if (md != null)
5481                                         md.SetMemberIsUsed ();
5482
5483                                 is_static = setter.IsStatic;
5484                         }
5485                 }
5486
5487 #if NET_4_0
5488                 public SLE.Expression MakeAssignExpression (BuilderContext ctx)
5489                 {
5490                         return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), setter);
5491                 }
5492
5493                 public override SLE.Expression MakeExpression (BuilderContext ctx)
5494                 {
5495                         return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), getter);
5496                 }
5497 #endif
5498
5499                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
5500                 {
5501                         if (InstanceExpression != null)
5502                                 InstanceExpression.MutateHoistedGenericType (storey);
5503
5504                         type = storey.MutateType (type);
5505                         if (getter != null)
5506                                 getter = storey.MutateGenericMethod (getter);
5507                         if (setter != null)
5508                                 setter = storey.MutateGenericMethod (setter);
5509                 }
5510
5511                 bool InstanceResolve (ResolveContext ec, bool lvalue_instance, bool must_do_cs1540_check)
5512                 {
5513                         if (is_static) {
5514                                 InstanceExpression = null;
5515                                 return true;
5516                         }
5517
5518                         if (InstanceExpression == null) {
5519                                 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
5520                                 return false;
5521                         }
5522
5523                         InstanceExpression = InstanceExpression.DoResolve (ec);
5524                         if (lvalue_instance && InstanceExpression != null)
5525                                 InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess);
5526
5527                         if (InstanceExpression == null)
5528                                 return false;
5529
5530                         InstanceExpression.CheckMarshalByRefAccess (ec);
5531
5532                         if (must_do_cs1540_check && (InstanceExpression != EmptyExpression.Null) &&
5533                             !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.CurrentType) &&
5534                             !TypeManager.IsNestedChildOf (ec.CurrentType, InstanceExpression.Type) &&
5535                             !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.CurrentType)) {
5536                                 ec.Report.SymbolRelatedToPreviousError (PropertyInfo);
5537                                 Error_CannotAccessProtected (ec, loc, PropertyInfo, InstanceExpression.Type, ec.CurrentType);
5538                                 return false;
5539                         }
5540
5541                         return true;
5542                 }
5543
5544                 void Error_PropertyNotFound (ResolveContext ec, MethodInfo mi, bool getter)
5545                 {
5546                         // TODO: correctly we should compare arguments but it will lead to bigger changes
5547                         if (mi is MethodBuilder) {
5548                                 Error_TypeDoesNotContainDefinition (ec, loc, PropertyInfo.DeclaringType, Name);
5549                                 return;
5550                         }
5551                         
5552                         StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
5553                         sig.Append ('.');
5554                         AParametersCollection iparams = TypeManager.GetParameterData (mi);
5555                         sig.Append (getter ? "get_" : "set_");
5556                         sig.Append (Name);
5557                         sig.Append (iparams.GetSignatureForError ());
5558
5559                         ec.Report.SymbolRelatedToPreviousError (mi);
5560                         ec.Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
5561                                 Name, sig.ToString ());
5562                 }
5563
5564                 public bool IsAccessibleFrom (Type invocation_type, bool lvalue)
5565                 {
5566                         bool dummy;
5567                         MethodInfo accessor = lvalue ? setter : getter;
5568                         if (accessor == null && lvalue)
5569                                 accessor = getter;
5570                         return accessor != null && IsAccessorAccessible (invocation_type, accessor, out dummy);
5571                 }
5572
5573                 bool IsSingleDimensionalArrayLength ()
5574                 {
5575                         if (DeclaringType != TypeManager.array_type || getter == null || Name != "Length")
5576                                 return false;
5577
5578                         string t_name = InstanceExpression.Type.Name;
5579                         int t_name_len = t_name.Length;
5580                         return t_name_len > 2 && t_name [t_name_len - 2] == '[';
5581                 }
5582
5583                 public override Expression DoResolve (ResolveContext ec)
5584                 {
5585                         if (resolved)
5586                                 return this;
5587
5588                         bool must_do_cs1540_check = false;
5589                         ec.Report.DisableReporting ();
5590                         bool res = ResolveGetter (ec, ref must_do_cs1540_check);
5591                         ec.Report.EnableReporting ();
5592
5593                         if (!res) {
5594                                 if (InstanceExpression != null) {
5595                                         Type expr_type = InstanceExpression.Type;
5596                                         ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (expr_type, Name, loc);
5597                                         if (ex_method_lookup != null) {
5598                                                 ex_method_lookup.ExtensionExpression = InstanceExpression;
5599                                                 ex_method_lookup.SetTypeArguments (ec, targs);
5600                                                 return ex_method_lookup.DoResolve (ec);
5601                                         }
5602                                 }
5603
5604                                 ResolveGetter (ec, ref must_do_cs1540_check);
5605                                 return null;
5606                         }
5607
5608                         if (!InstanceResolve (ec, false, must_do_cs1540_check))
5609                                 return null;
5610
5611                         //
5612                         // Only base will allow this invocation to happen.
5613                         //
5614                         if (IsBase && getter.IsAbstract) {
5615                                 Error_CannotCallAbstractBase (ec, TypeManager.GetFullNameSignature (PropertyInfo));
5616                         }
5617
5618                         if (PropertyInfo.PropertyType.IsPointer && !ec.IsUnsafe){
5619                                 UnsafeError (ec, loc);
5620                         }
5621
5622                         if (!ec.IsObsolete) {
5623                                 PropertyBase pb = TypeManager.GetProperty (PropertyInfo);
5624                                 if (pb != null) {
5625                                         pb.CheckObsoleteness (loc);
5626                                 } else {
5627                                         ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (PropertyInfo);
5628                                         if (oa != null)
5629                                                 AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
5630                                 }
5631                         }
5632
5633                         resolved = true;
5634
5635                         return this;
5636                 }
5637
5638                 override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
5639                 {
5640                         if (right_side == EmptyExpression.OutAccess.Instance) {
5641                                 if (ec.CurrentBlock.Toplevel.GetParameterReference (PropertyInfo.Name, loc) is MemberAccess) {
5642                                         ec.Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter",
5643                                             PropertyInfo.Name);
5644                                 } else {
5645                                         right_side.DoResolveLValue (ec, this);
5646                                 }
5647                                 return null;
5648                         }
5649
5650                         if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) {
5651                                 Error_CannotModifyIntermediateExpressionValue (ec);
5652                         }
5653
5654                         if (setter == null){
5655                                 //
5656                                 // The following condition happens if the PropertyExpr was
5657                                 // created, but is invalid (ie, the property is inaccessible),
5658                                 // and we did not want to embed the knowledge about this in
5659                                 // the caller routine.  This only avoids double error reporting.
5660                                 //
5661                                 if (getter == null)
5662                                         return null;
5663
5664                                 if (ec.CurrentBlock.Toplevel.GetParameterReference (PropertyInfo.Name, loc) is MemberAccess) {
5665                                         ec.Report.Error (1947, loc, "A range variable `{0}' cannot be assigned to. Consider using `let' clause to store the value",
5666                                                 PropertyInfo.Name);
5667                                 } else {
5668                                         ec.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read only)",
5669                                                 GetSignatureForError ());
5670                                 }
5671                                 return null;
5672                         }
5673
5674                         if (targs != null) {
5675                                 base.SetTypeArguments (ec, targs);
5676                                 return null;
5677                         }
5678
5679                         if (TypeManager.GetParameterData (setter).Count != 1){
5680                                 Error_PropertyNotFound (ec, setter, false);
5681                                 return null;
5682                         }
5683
5684                         bool must_do_cs1540_check;
5685                         if (!IsAccessorAccessible (ec.CurrentType, setter, out must_do_cs1540_check)) {
5686                                 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
5687                                 if (pm != null && pm.HasCustomAccessModifier) {
5688                                         ec.Report.SymbolRelatedToPreviousError (pm);
5689                                         ec.Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
5690                                                 TypeManager.CSharpSignature (setter));
5691                                 }
5692                                 else {
5693                                         ec.Report.SymbolRelatedToPreviousError (setter);
5694                                         ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter), ec.Report);
5695                                 }
5696                                 return null;
5697                         }
5698                         
5699                         if (!InstanceResolve (ec, TypeManager.IsStruct (PropertyInfo.DeclaringType), must_do_cs1540_check))
5700                                 return null;
5701                         
5702                         //
5703                         // Only base will allow this invocation to happen.
5704                         //
5705                         if (IsBase && setter.IsAbstract){
5706                                 Error_CannotCallAbstractBase (ec, TypeManager.GetFullNameSignature (PropertyInfo));
5707                         }
5708
5709                         if (PropertyInfo.PropertyType.IsPointer && !ec.IsUnsafe) {
5710                                 UnsafeError (ec, loc);
5711                         }
5712
5713                         if (!ec.IsObsolete) {
5714                                 PropertyBase pb = TypeManager.GetProperty (PropertyInfo);
5715                                 if (pb != null) {
5716                                         pb.CheckObsoleteness (loc);
5717                                 } else {
5718                                         ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (PropertyInfo);
5719                                         if (oa != null)
5720                                                 AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
5721                                 }
5722                         }
5723
5724                         return this;
5725                 }
5726                 
5727                 public override void Emit (EmitContext ec)
5728                 {
5729                         Emit (ec, false);
5730                 }
5731                 
5732                 public void Emit (EmitContext ec, bool leave_copy)
5733                 {
5734                         //
5735                         // Special case: length of single dimension array property is turned into ldlen
5736                         //
5737                         if (IsSingleDimensionalArrayLength ()) {
5738                                 if (!prepared)
5739                                         EmitInstance (ec, false);
5740                                 ec.ig.Emit (OpCodes.Ldlen);
5741                                 ec.ig.Emit (OpCodes.Conv_I4);
5742                                 return;
5743                         }
5744
5745                         Invocation.EmitCall (ec, IsBase, InstanceExpression, getter, null, loc, prepared, false);
5746                         
5747                         if (leave_copy) {
5748                                 ec.ig.Emit (OpCodes.Dup);
5749                                 if (!is_static) {
5750                                         temp = new LocalTemporary (this.Type);
5751                                         temp.Store (ec);
5752                                 }
5753                         }
5754                 }
5755
5756                 //
5757                 // Implements the IAssignMethod interface for assignments
5758                 //
5759                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
5760                 {
5761                         Expression my_source = source;
5762
5763                         if (prepare_for_load) {
5764                                 prepared = true;
5765                                 source.Emit (ec);
5766                                 
5767                                 if (leave_copy) {
5768                                         ec.ig.Emit (OpCodes.Dup);
5769                                         if (!is_static) {
5770                                                 temp = new LocalTemporary (this.Type);
5771                                                 temp.Store (ec);
5772                                         }
5773                                 }
5774                         } else if (leave_copy) {
5775                                 source.Emit (ec);
5776                                 temp = new LocalTemporary (this.Type);
5777                                 temp.Store (ec);
5778                                 my_source = temp;
5779                         }
5780
5781                         Arguments args = new Arguments (1);
5782                         args.Add (new Argument (my_source));
5783                         
5784                         Invocation.EmitCall (ec, IsBase, InstanceExpression, setter, args, loc, false, prepared);
5785                         
5786                         if (temp != null) {
5787                                 temp.Emit (ec);
5788                                 temp.Release (ec);
5789                         }
5790                 }
5791
5792                 bool ResolveGetter (ResolveContext ec, ref bool must_do_cs1540_check)
5793                 {
5794                         if (targs != null) {
5795                                 base.SetTypeArguments (ec, targs);
5796                                 return false;
5797                         }
5798
5799                         if (getter != null) {
5800                                 if (TypeManager.GetParameterData (getter).Count != 0) {
5801                                         Error_PropertyNotFound (ec, getter, true);
5802                                         return false;
5803                                 }
5804                         }
5805
5806                         if (getter == null) {
5807                                 //
5808                                 // The following condition happens if the PropertyExpr was
5809                                 // created, but is invalid (ie, the property is inaccessible),
5810                                 // and we did not want to embed the knowledge about this in
5811                                 // the caller routine.  This only avoids double error reporting.
5812                                 //
5813                                 if (setter == null)
5814                                         return false;
5815
5816                                 if (InstanceExpression != EmptyExpression.Null) {
5817                                         ec.Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
5818                                                 TypeManager.GetFullNameSignature (PropertyInfo));
5819                                         return false;
5820                                 }
5821                         }
5822
5823                         if (getter != null &&
5824                                 !IsAccessorAccessible (ec.CurrentType, getter, out must_do_cs1540_check)) {
5825                                 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
5826                                 if (pm != null && pm.HasCustomAccessModifier) {
5827                                         ec.Report.SymbolRelatedToPreviousError (pm);
5828                                         ec.Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
5829                                                 TypeManager.CSharpSignature (getter));
5830                                 } else {
5831                                         ec.Report.SymbolRelatedToPreviousError (getter);
5832                                         ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter), ec.Report);
5833                                 }
5834
5835                                 return false;
5836                         }
5837
5838                         return true;
5839                 }
5840
5841                 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
5842                 {
5843                         targs = ta;
5844                 }
5845         }
5846
5847         /// <summary>
5848         ///   Fully resolved expression that evaluates to an Event
5849         /// </summary>
5850         public class EventExpr : MemberExpr {
5851                 public readonly EventInfo EventInfo;
5852
5853                 bool is_static;
5854                 MethodInfo add_accessor, remove_accessor;
5855
5856                 public EventExpr (EventInfo ei, Location loc)
5857                 {
5858                         EventInfo = ei;
5859                         this.loc = loc;
5860                         eclass = ExprClass.EventAccess;
5861
5862                         add_accessor = TypeManager.GetAddMethod (ei);
5863                         remove_accessor = TypeManager.GetRemoveMethod (ei);
5864                         if (add_accessor.IsStatic || remove_accessor.IsStatic)
5865                                 is_static = true;
5866
5867                         if (EventInfo is MyEventBuilder){
5868                                 MyEventBuilder eb = (MyEventBuilder) EventInfo;
5869                                 type = eb.EventType;
5870                                 eb.SetUsed ();
5871                         } else
5872                                 type = EventInfo.EventHandlerType;
5873                 }
5874
5875                 public override string Name {
5876                         get {
5877                                 return EventInfo.Name;
5878                         }
5879                 }
5880
5881                 public override bool IsInstance {
5882                         get {
5883                                 return !is_static;
5884                         }
5885                 }
5886
5887                 public override bool IsStatic {
5888                         get {
5889                                 return is_static;
5890                         }
5891                 }
5892
5893                 public override Type DeclaringType {
5894                         get {
5895                                 return EventInfo.DeclaringType;
5896                         }
5897                 }
5898                 
5899                 public void Error_AssignmentEventOnly (ResolveContext ec)
5900                 {
5901                         ec.Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator",
5902                                 GetSignatureForError ());
5903                 }
5904
5905                 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
5906                                                                 SimpleName original)
5907                 {
5908                         //
5909                         // If the event is local to this class, we transform ourselves into a FieldExpr
5910                         //
5911
5912                         if (EventInfo.DeclaringType == ec.CurrentType ||
5913                             TypeManager.IsNestedChildOf(ec.CurrentType, EventInfo.DeclaringType)) {
5914                                         
5915                                 // TODO: Breaks dynamic binder as currect context fields are imported and not compiled
5916                                 EventField mi = TypeManager.GetEventField (EventInfo);
5917
5918                                 if (mi != null) {
5919                                         if (!ec.IsObsolete)
5920                                                 mi.CheckObsoleteness (loc);
5921
5922                                         if ((mi.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0 && !ec.HasSet (ResolveContext.Options.CompoundAssignmentScope))
5923                                                 Error_AssignmentEventOnly (ec);
5924                                         
5925                                         FieldExpr ml = new FieldExpr (mi.BackingField.FieldBuilder, loc);
5926
5927                                         InstanceExpression = null;
5928                                 
5929                                         return ml.ResolveMemberAccess (ec, left, loc, original);
5930                                 }
5931                         }
5932
5933                         if (left is This && !ec.HasSet (ResolveContext.Options.CompoundAssignmentScope))                        
5934                                 Error_AssignmentEventOnly (ec);
5935
5936                         return base.ResolveMemberAccess (ec, left, loc, original);
5937                 }
5938
5939                 bool InstanceResolve (ResolveContext ec, bool must_do_cs1540_check)
5940                 {
5941                         if (is_static) {
5942                                 InstanceExpression = null;
5943                                 return true;
5944                         }
5945
5946                         if (InstanceExpression == null) {
5947                                 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
5948                                 return false;
5949                         }
5950
5951                         InstanceExpression = InstanceExpression.DoResolve (ec);
5952                         if (InstanceExpression == null)
5953                                 return false;
5954
5955                         if (IsBase && add_accessor.IsAbstract) {
5956                                 Error_CannotCallAbstractBase (ec, TypeManager.CSharpSignature(add_accessor));
5957                                 return false;
5958                         }
5959
5960                         //
5961                         // This is using the same mechanism as the CS1540 check in PropertyExpr.
5962                         // However, in the Event case, we reported a CS0122 instead.
5963                         //
5964                         // TODO: Exact copy from PropertyExpr
5965                         //
5966                         if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
5967                             !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.CurrentType) &&
5968                             !TypeManager.IsNestedChildOf (ec.CurrentType, InstanceExpression.Type) &&
5969                             !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.CurrentType)) {
5970                                 ec.Report.SymbolRelatedToPreviousError (EventInfo);
5971                                 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo), ec.Report);
5972                                 return false;
5973                         }
5974
5975                         return true;
5976                 }
5977
5978                 public bool IsAccessibleFrom (Type invocation_type)
5979                 {
5980                         bool dummy;
5981                         return IsAccessorAccessible (invocation_type, add_accessor, out dummy) &&
5982                                 IsAccessorAccessible (invocation_type, remove_accessor, out dummy);
5983                 }
5984
5985                 public override Expression CreateExpressionTree (ResolveContext ec)
5986                 {
5987                         throw new NotSupportedException ("ET");
5988                 }
5989
5990                 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
5991                 {
5992                         // contexts where an LValue is valid have already devolved to FieldExprs
5993                         Error_CannotAssign (ec);
5994                         return null;
5995                 }
5996
5997                 public override Expression DoResolve (ResolveContext ec)
5998                 {
5999                         bool must_do_cs1540_check;
6000                         if (!(IsAccessorAccessible (ec.CurrentType, add_accessor, out must_do_cs1540_check) &&
6001                               IsAccessorAccessible (ec.CurrentType, remove_accessor, out must_do_cs1540_check))) {
6002                                 ec.Report.SymbolRelatedToPreviousError (EventInfo);
6003                                 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo), ec.Report);
6004                                 return null;
6005                         }
6006
6007                         if (!InstanceResolve (ec, must_do_cs1540_check))
6008                                 return null;
6009
6010                         if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) {
6011                                 Error_CannotAssign (ec);
6012                                 return null;
6013                         }
6014
6015                         if (!ec.IsObsolete) {
6016                                 EventField ev = TypeManager.GetEventField (EventInfo);
6017                                 if (ev != null) {
6018                                         ev.CheckObsoleteness (loc);
6019                                 } else {
6020                                         ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (EventInfo);
6021                                         if (oa != null)
6022                                                 AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
6023                                 }
6024                         }
6025                         
6026                         return this;
6027                 }               
6028
6029                 public override void Emit (EmitContext ec)
6030                 {
6031                         throw new NotSupportedException ();
6032                         //Error_CannotAssign ();
6033                 }
6034
6035                 public void Error_CannotAssign (ResolveContext ec)
6036                 {
6037                         ec.Report.Error (70, loc,
6038                                 "The event `{0}' can only appear on the left hand side of += or -= when used outside of the type `{1}'",
6039                                 GetSignatureForError (), TypeManager.CSharpName (EventInfo.DeclaringType));
6040                 }
6041
6042                 public override string GetSignatureForError ()
6043                 {
6044                         return TypeManager.CSharpSignature (EventInfo);
6045                 }
6046
6047                 public void EmitAddOrRemove (EmitContext ec, bool is_add, Expression source)
6048                 {
6049                         Arguments args = new Arguments (1);
6050                         args.Add (new Argument (source));
6051                         Invocation.EmitCall (ec, IsBase, InstanceExpression, is_add ? add_accessor : remove_accessor, args, loc);
6052                 }
6053         }
6054
6055         public class TemporaryVariable : VariableReference
6056         {
6057                 LocalInfo li;
6058
6059                 public TemporaryVariable (Type type, Location loc)
6060                 {
6061                         this.type = type;
6062                         this.loc = loc;
6063                         eclass = ExprClass.Variable;
6064                 }
6065
6066                 public override Expression CreateExpressionTree (ResolveContext ec)
6067                 {
6068                         throw new NotSupportedException ("ET");
6069                 }
6070
6071                 public override Expression DoResolve (ResolveContext ec)
6072                 {
6073                         if (li != null)
6074                                 return this;
6075
6076                         TypeExpr te = new TypeExpression (type, loc);
6077                         li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
6078                         if (!li.Resolve (ec))
6079                                 return null;
6080
6081                         //
6082                         // Don't capture temporary variables except when using
6083                         // iterator redirection
6084                         //
6085                         if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.IsIterator && ec.IsVariableCapturingRequired) {
6086                                 AnonymousMethodStorey storey = li.Block.Explicit.CreateAnonymousMethodStorey (ec);
6087                                 storey.CaptureLocalVariable (ec, li);
6088                         }
6089
6090                         return this;
6091                 }
6092
6093                 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
6094                 {
6095                         return DoResolve (ec);
6096                 }
6097                 
6098                 public override void Emit (EmitContext ec)
6099                 {
6100                         Emit (ec, false);
6101                 }
6102
6103                 public void EmitAssign (EmitContext ec, Expression source)
6104                 {
6105                         EmitAssign (ec, source, false, false);
6106                 }
6107
6108                 public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
6109                 {
6110                         return li.HoistedVariant;
6111                 }
6112
6113                 public override bool IsFixed {
6114                         get { return true; }
6115                 }
6116
6117                 public override bool IsRef {
6118                         get { return false; }
6119                 }
6120
6121                 public override string Name {
6122                         get { throw new NotImplementedException (); }
6123                 }
6124
6125                 public override void SetHasAddressTaken ()
6126                 {
6127                         throw new NotImplementedException ();
6128                 }
6129
6130                 protected override ILocalVariable Variable {
6131                         get { return li; }
6132                 }
6133
6134                 public override VariableInfo VariableInfo {
6135                         get { throw new NotImplementedException (); }
6136                 }
6137         }
6138
6139         /// 
6140         /// Handles `var' contextual keyword; var becomes a keyword only
6141         /// if no type called var exists in a variable scope
6142         /// 
6143         class VarExpr : SimpleName
6144         {
6145                 // Used for error reporting only
6146                 ArrayList initializer;
6147
6148                 public VarExpr (Location loc)
6149                         : base ("var", loc)
6150                 {
6151                 }
6152
6153                 public ArrayList VariableInitializer {
6154                         set {
6155                                 this.initializer = value;
6156                         }
6157                 }
6158
6159                 public bool InferType (ResolveContext ec, Expression right_side)
6160                 {
6161                         if (type != null)
6162                                 throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
6163                         
6164                         type = right_side.Type;
6165                         if (type == TypeManager.null_type || type == TypeManager.void_type || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) {
6166                                 ec.Report.Error (815, loc, "An implicitly typed local variable declaration cannot be initialized with `{0}'",
6167                                               right_side.GetSignatureForError ());
6168                                 return false;
6169                         }
6170
6171                         eclass = ExprClass.Variable;
6172                         return true;
6173                 }
6174
6175                 protected override void Error_TypeOrNamespaceNotFound (IMemberContext ec)
6176                 {
6177                         if (RootContext.Version < LanguageVersion.V_3)
6178                                 base.Error_TypeOrNamespaceNotFound (ec);
6179                         else
6180                                 ec.Compiler.Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration");
6181                 }
6182
6183                 public override TypeExpr ResolveAsContextualType (IMemberContext rc, bool silent)
6184                 {
6185                         TypeExpr te = base.ResolveAsContextualType (rc, true);
6186                         if (te != null)
6187                                 return te;
6188
6189                         if (RootContext.Version < LanguageVersion.V_3)
6190                                 rc.Compiler.Report.FeatureIsNotAvailable (loc, "implicitly typed local variable");
6191
6192                         if (initializer == null)
6193                                 return null;
6194
6195                         if (initializer.Count > 1) {
6196                                 Location loc_init = ((CSharpParser.VariableDeclaration) initializer[1]).Location;
6197                                 rc.Compiler.Report.Error (819, loc_init, "An implicitly typed local variable declaration cannot include multiple declarators");
6198                                 initializer = null;
6199                                 return null;
6200                         }
6201
6202                         Expression variable_initializer = ((CSharpParser.VariableDeclaration) initializer[0]).expression_or_array_initializer;
6203                         if (variable_initializer == null) {
6204                                 rc.Compiler.Report.Error (818, loc, "An implicitly typed local variable declarator must include an initializer");
6205                                 return null;
6206                         }
6207
6208                         return null;
6209                 }
6210         }
6211 }