2009-10-23 Marek Safar <marek.safar@gmail.com>
[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;
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         // Base of expressions used only to narrow resolve flow
2337         //
2338         public abstract class ShimExpression : Expression
2339         {
2340                 protected Expression expr;
2341
2342                 protected ShimExpression (Expression expr)
2343                 {
2344                         this.expr = expr;
2345                 }
2346
2347                 protected override void CloneTo (CloneContext clonectx, Expression t)
2348                 {
2349                         if (expr == null)
2350                                 return;
2351
2352                         ShimExpression target = (ShimExpression) t;
2353                         target.expr = expr.Clone (clonectx);
2354                 }
2355
2356                 public override Expression CreateExpressionTree (ResolveContext ec)
2357                 {
2358                         throw new NotSupportedException ("ET");
2359                 }
2360
2361                 public override void Emit (EmitContext ec)
2362                 {
2363                         throw new InternalErrorException ("Missing Resolve call");
2364                 }
2365
2366                 public Expression Expr {
2367                         get { return expr; }
2368                 }
2369
2370                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
2371                 {
2372                         throw new InternalErrorException ("Missing Resolve call");
2373                 }
2374         }
2375
2376         //
2377         // Unresolved type name expressions
2378         //
2379         public abstract class ATypeNameExpression : FullNamedExpression
2380         {
2381                 string name;
2382                 protected TypeArguments targs;
2383
2384                 protected ATypeNameExpression (string name, Location l)
2385                 {
2386                         this.name = name;
2387                         loc = l;
2388                 }
2389
2390                 protected ATypeNameExpression (string name, TypeArguments targs, Location l)
2391                 {
2392                         this.name = name;
2393                         this.targs = targs;
2394                         loc = l;
2395                 }
2396
2397                 public bool HasTypeArguments {
2398                         get {
2399                                 return targs != null;
2400                         }
2401                 }
2402
2403                 public override bool Equals (object obj)
2404                 {
2405                         ATypeNameExpression atne = obj as ATypeNameExpression;
2406                         return atne != null && atne.Name == Name &&
2407                                 (targs == null || targs.Equals (atne.targs));
2408                 }
2409
2410                 public override int GetHashCode ()
2411                 {
2412                         return Name.GetHashCode ();
2413                 }
2414
2415                 public override string GetSignatureForError ()
2416                 {
2417                         if (targs != null) {
2418                                 return TypeManager.RemoveGenericArity (Name) + "<" +
2419                                         targs.GetSignatureForError () + ">";
2420                         }
2421
2422                         return Name;
2423                 }
2424
2425                 public string Name {
2426                         get {
2427                                 return name;
2428                         }
2429                         set {
2430                                 name = value;
2431                         }
2432                 }
2433
2434                 public TypeArguments TypeArguments {
2435                         get {
2436                                 return targs;
2437                         }
2438                 }
2439         }
2440         
2441         /// <summary>
2442         ///   SimpleName expressions are formed of a single word and only happen at the beginning 
2443         ///   of a dotted-name.
2444         /// </summary>
2445         public class SimpleName : ATypeNameExpression {
2446                 bool in_transit;
2447
2448                 public SimpleName (string name, Location l)
2449                         : base (name, l)
2450                 {
2451                 }
2452
2453                 public SimpleName (string name, TypeArguments args, Location l)
2454                         : base (name, args, l)
2455                 {
2456                 }
2457
2458                 public SimpleName (string name, TypeParameter[] type_params, Location l)
2459                         : base (name, l)
2460                 {
2461                         targs = new TypeArguments ();
2462                         foreach (TypeParameter type_param in type_params)
2463                                 targs.Add (new TypeParameterExpr (type_param, l));
2464                 }
2465
2466                 public static string RemoveGenericArity (string name)
2467                 {
2468                         int start = 0;
2469                         StringBuilder sb = null;
2470                         do {
2471                                 int pos = name.IndexOf ('`', start);
2472                                 if (pos < 0) {
2473                                         if (start == 0)
2474                                                 return name;
2475
2476                                         sb.Append (name.Substring (start));
2477                                         break;
2478                                 }
2479
2480                                 if (sb == null)
2481                                         sb = new StringBuilder ();
2482                                 sb.Append (name.Substring (start, pos-start));
2483
2484                                 pos++;
2485                                 while ((pos < name.Length) && Char.IsNumber (name [pos]))
2486                                         pos++;
2487
2488                                 start = pos;
2489                         } while (start < name.Length);
2490
2491                         return sb.ToString ();
2492                 }
2493
2494                 public SimpleName GetMethodGroup ()
2495                 {
2496                         return new SimpleName (RemoveGenericArity (Name), targs, loc);
2497                 }
2498
2499                 public static void Error_ObjectRefRequired (ResolveContext ec, Location l, string name)
2500                 {
2501                         if (ec.HasSet (ResolveContext.Options.FieldInitializerScope))
2502                                 ec.Report.Error (236, l,
2503                                         "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
2504                                         name);
2505                         else
2506                                 ec.Report.Error (120, l,
2507                                         "An object reference is required to access non-static member `{0}'",
2508                                         name);
2509                 }
2510
2511                 public bool IdenticalNameAndTypeName (IMemberContext mc, Expression resolved_to, Location loc)
2512                 {
2513                         return resolved_to != null && resolved_to.Type != null && 
2514                                 resolved_to.Type.Name == Name &&
2515                                 (mc.LookupNamespaceOrType (Name, loc, /* ignore_cs0104 = */ true) != null);
2516                 }
2517
2518                 public override Expression DoResolve (ResolveContext ec)
2519                 {
2520                         return SimpleNameResolve (ec, null, false);
2521                 }
2522
2523                 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
2524                 {
2525                         return SimpleNameResolve (ec, right_side, false);
2526                 }
2527                 
2528
2529                 public Expression DoResolve (ResolveContext ec, bool intermediate)
2530                 {
2531                         return SimpleNameResolve (ec, null, intermediate);
2532                 }
2533
2534                 static bool IsNestedChild (Type t, Type parent)
2535                 {
2536                         while (parent != null) {
2537                                 if (TypeManager.IsNestedChildOf (t, TypeManager.DropGenericTypeArguments (parent)))
2538                                         return true;
2539
2540                                 parent = parent.BaseType;
2541                         }
2542
2543                         return false;
2544                 }
2545
2546                 FullNamedExpression ResolveNested (Type t)
2547                 {
2548                         if (!TypeManager.IsGenericTypeDefinition (t) && !TypeManager.IsGenericType (t))
2549                                 return null;
2550
2551                         Type ds = t;
2552                         while (ds != null && !IsNestedChild (t, ds))
2553                                 ds = ds.DeclaringType;
2554
2555                         if (ds == null)
2556                                 return null;
2557
2558                         Type[] gen_params = TypeManager.GetTypeArguments (t);
2559
2560                         int arg_count = targs != null ? targs.Count : 0;
2561
2562                         for (; (ds != null) && TypeManager.IsGenericType (ds); ds = ds.DeclaringType) {
2563                                 Type[] gargs = TypeManager.GetTypeArguments (ds);
2564                                 if (arg_count + gargs.Length == gen_params.Length) {
2565                                         TypeArguments new_args = new TypeArguments ();
2566                                         foreach (Type param in gargs)
2567                                                 new_args.Add (new TypeExpression (param, loc));
2568
2569                                         if (targs != null)
2570                                                 new_args.Add (targs);
2571
2572                                         return new GenericTypeExpr (t, new_args, loc);
2573                                 }
2574                         }
2575
2576                         return null;
2577                 }
2578
2579                 public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
2580                 {
2581                         int errors = ec.Compiler.Report.Errors;
2582                         FullNamedExpression fne = ec.LookupNamespaceOrType (Name, loc, /*ignore_cs0104=*/ false);
2583
2584                         if (fne != null) {
2585                                 if (fne.Type == null)
2586                                         return fne;
2587
2588                                 FullNamedExpression nested = ResolveNested (fne.Type);
2589                                 if (nested != null)
2590                                         return nested.ResolveAsTypeStep (ec, false);
2591
2592                                 if (targs != null) {
2593                                         if (TypeManager.IsGenericType (fne.Type)) {
2594                                                 GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc);
2595                                                 return ct.ResolveAsTypeStep (ec, false);
2596                                         }
2597
2598                                         fne.Error_TypeArgumentsCannotBeUsed (ec.Compiler.Report, loc);
2599                                 }
2600
2601                                 return fne;
2602                         }
2603
2604                         if (!HasTypeArguments && Name == "dynamic" && RootContext.Version > LanguageVersion.V_3)
2605                                 return new DynamicTypeExpr (loc);
2606
2607                         if (silent || errors != ec.Compiler.Report.Errors)
2608                                 return null;
2609
2610                         Error_TypeOrNamespaceNotFound (ec);
2611                         return null;
2612                 }
2613
2614                 protected virtual void Error_TypeOrNamespaceNotFound (IMemberContext ec)
2615                 {
2616                         if (ec.CurrentType != null) {
2617                                 if (ec.CurrentTypeDefinition != null) {
2618                                         MemberCore mc = ec.CurrentTypeDefinition.GetDefinition (Name);
2619                                         if (mc != null) {
2620                                                 Error_UnexpectedKind (ec.Compiler.Report, mc, "type", GetMemberType (mc), loc);
2621                                                 return;
2622                                         }
2623                                 }
2624
2625                                 string ns = ec.CurrentType.Namespace;
2626                                 string fullname = (ns.Length > 0) ? ns + "." + Name : Name;
2627                                 foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
2628                                         Type type = a.GetType (fullname);
2629                                         if (type != null) {
2630                                                 ec.Compiler.Report.SymbolRelatedToPreviousError (type);
2631                                                 Expression.ErrorIsInaccesible (loc, TypeManager.CSharpName (type), ec.Compiler.Report);
2632                                                 return;
2633                                         }
2634                                 }
2635
2636                                 if (ec.CurrentTypeDefinition != null) {
2637                                         Type t = ec.CurrentTypeDefinition.LookupAnyGeneric (Name);
2638                                         if (t != null) {
2639                                                 Namespace.Error_InvalidNumberOfTypeArguments (t, loc);
2640                                                 return;
2641                                         }
2642                                 }
2643                         }
2644
2645                         if (targs != null) {
2646                                 FullNamedExpression retval = ec.LookupNamespaceOrType (SimpleName.RemoveGenericArity (Name), loc, true);
2647                                 if (retval != null) {
2648                                         retval.Error_TypeArgumentsCannotBeUsed (ec.Compiler.Report, loc);
2649                                         return;
2650                                 }
2651                         }
2652                                                 
2653                         NamespaceEntry.Error_NamespaceNotFound (loc, Name, ec.Compiler.Report);
2654                 }
2655
2656                 // TODO: I am still not convinced about this. If someone else will need it
2657                 // implement this as virtual property in MemberCore hierarchy
2658                 public static string GetMemberType (MemberCore mc)
2659                 {
2660                         if (mc is Property)
2661                                 return "property";
2662                         if (mc is Indexer)
2663                                 return "indexer";
2664                         if (mc is FieldBase)
2665                                 return "field";
2666                         if (mc is MethodCore)
2667                                 return "method";
2668                         if (mc is EnumMember)
2669                                 return "enum";
2670                         if (mc is Event)
2671                                 return "event";
2672
2673                         return "type";
2674                 }
2675
2676                 Expression SimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate)
2677                 {
2678                         if (in_transit)
2679                                 return null;
2680
2681                         in_transit = true;
2682                         Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
2683                         in_transit = false;
2684
2685                         if (e == null)
2686                                 return null;
2687
2688                         if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
2689                                 return e;
2690
2691                         return null;
2692                 }
2693
2694                 /// <remarks>
2695                 ///   7.5.2: Simple Names. 
2696                 ///
2697                 ///   Local Variables and Parameters are handled at
2698                 ///   parse time, so they never occur as SimpleNames.
2699                 ///
2700                 ///   The `intermediate' flag is used by MemberAccess only
2701                 ///   and it is used to inform us that it is ok for us to 
2702                 ///   avoid the static check, because MemberAccess might end
2703                 ///   up resolving the Name as a Type name and the access as
2704                 ///   a static type access.
2705                 ///
2706                 ///   ie: Type Type; .... { Type.GetType (""); }
2707                 ///
2708                 ///   Type is both an instance variable and a Type;  Type.GetType
2709                 ///   is the static method not an instance method of type.
2710                 /// </remarks>
2711                 Expression DoSimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate)
2712                 {
2713                         Expression e = null;
2714
2715                         //
2716                         // Stage 1: Performed by the parser (binding to locals or parameters).
2717                         //
2718                         Block current_block = ec.CurrentBlock;
2719                         if (current_block != null){
2720                                 LocalInfo vi = current_block.GetLocalInfo (Name);
2721                                 if (vi != null){
2722                                         e = new LocalVariableReference (ec.CurrentBlock, Name, loc);
2723
2724                                         if (right_side != null) {
2725                                                 e = e.ResolveLValue (ec, right_side);
2726                                         } else {
2727                                                 ResolveFlags rf = ResolveFlags.VariableOrValue;
2728                                                 if (intermediate)
2729                                                         rf |= ResolveFlags.DisableFlowAnalysis;
2730
2731                                                 e = e.Resolve (ec, rf);
2732                                         }
2733
2734                                         if (targs != null && e != null)
2735                                                 e.Error_TypeArgumentsCannotBeUsed (ec.Report, loc);
2736
2737                                         return e;
2738                                 }
2739
2740                                 e = current_block.Toplevel.GetParameterReference (Name, loc);
2741                                 if (e != null) {
2742                                         if (right_side != null)
2743                                                 e = e.ResolveLValue (ec, right_side);
2744                                         else
2745                                                 e = e.Resolve (ec);
2746
2747                                         if (targs != null && e != null)
2748                                                 e.Error_TypeArgumentsCannotBeUsed (ec.Report, loc);
2749
2750                                         return e;
2751                                 }
2752                         }
2753                         
2754                         //
2755                         // Stage 2: Lookup members 
2756                         //
2757
2758                         Type almost_matched_type = null;
2759                         ArrayList almost_matched = null;
2760                         for (Type lookup_ds = ec.CurrentType; lookup_ds != null; lookup_ds = lookup_ds.DeclaringType) {
2761                                 e = MemberLookup (ec.Compiler, ec.CurrentType, lookup_ds, Name, loc);
2762                                 if (e != null) {
2763                                         PropertyExpr pe = e as PropertyExpr;
2764                                         if (pe != null) {
2765                                                 AParametersCollection param = TypeManager.GetParameterData (pe.PropertyInfo);
2766
2767                                                 // since TypeManager.MemberLookup doesn't know if we're doing a lvalue access or not,
2768                                                 // it doesn't know which accessor to check permissions against
2769                                                 if (param.IsEmpty && pe.IsAccessibleFrom (ec.CurrentType, right_side != null))
2770                                                         break;
2771                                         } else if (e is EventExpr) {
2772                                                 if (((EventExpr) e).IsAccessibleFrom (ec.CurrentType))
2773                                                         break;
2774                                         } else if (targs != null && e is TypeExpression) {
2775                                                 e = new GenericTypeExpr (e.Type, targs, loc).ResolveAsTypeStep (ec, false);
2776                                                 break;
2777                                         } else {
2778                                                 break;
2779                                         }
2780                                         e = null;
2781                                 }
2782
2783                                 if (almost_matched == null && almost_matched_members.Count > 0) {
2784                                         almost_matched_type = lookup_ds;
2785                                         almost_matched = (ArrayList) almost_matched_members.Clone ();
2786                                 }
2787                         }
2788
2789                         if (e == null) {
2790                                 if (almost_matched == null && almost_matched_members.Count > 0) {
2791                                         almost_matched_type = ec.CurrentType;
2792                                         almost_matched = (ArrayList) almost_matched_members.Clone ();
2793                                 }
2794                                 e = ResolveAsTypeStep (ec, true);
2795                         }
2796
2797                         if (e == null) {
2798                                 if (current_block != null) {
2799                                         IKnownVariable ikv = current_block.Explicit.GetKnownVariable (Name);
2800                                         if (ikv != null) {
2801                                                 LocalInfo li = ikv as LocalInfo;
2802                                                 // Supress CS0219 warning
2803                                                 if (li != null)
2804                                                         li.Used = true;
2805
2806                                                 Error_VariableIsUsedBeforeItIsDeclared (ec.Report, Name);
2807                                                 return null;
2808                                         }
2809                                 }
2810
2811                                 if (RootContext.EvalMode){
2812                                         FieldInfo fi = Evaluator.LookupField (Name);
2813                                         if (fi != null)
2814                                                 return new FieldExpr (fi, loc).Resolve (ec);
2815                                 }
2816
2817                                 if (almost_matched != null)
2818                                         almost_matched_members = almost_matched;
2819                                 if (almost_matched_type == null)
2820                                         almost_matched_type = ec.CurrentType;
2821
2822                                 string type_name = ec.MemberContext.CurrentType == null ? null : ec.MemberContext.CurrentType.Name;
2823                                 return Error_MemberLookupFailed (ec, ec.CurrentType, null, almost_matched_type, Name,
2824                                         type_name, AllMemberTypes, AllBindingFlags);
2825                         }
2826
2827                         if (e is MemberExpr) {
2828                                 MemberExpr me = (MemberExpr) e;
2829
2830                                 Expression left;
2831                                 if (me.IsInstance) {
2832                                         if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer | ResolveContext.Options.ConstantScope)) {
2833                                                 //
2834                                                 // Note that an MemberExpr can be both IsInstance and IsStatic.
2835                                                 // An unresolved MethodGroupExpr can contain both kinds of methods
2836                                                 // and each predicate is true if the MethodGroupExpr contains
2837                                                 // at least one of that kind of method.
2838                                                 //
2839
2840                                                 if (!me.IsStatic &&
2841                                                     (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
2842                                                         Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
2843                                                         return null;
2844                                                 }
2845
2846                                                 //
2847                                                 // Pass the buck to MemberAccess and Invocation.
2848                                                 //
2849                                                 left = EmptyExpression.Null;
2850                                         } else {
2851                                                 left = ec.GetThis (loc);
2852                                         }
2853                                 } else {
2854                                         left = new TypeExpression (ec.CurrentType, loc);
2855                                 }
2856
2857                                 me = me.ResolveMemberAccess (ec, left, loc, null);
2858                                 if (me == null)
2859                                         return null;
2860
2861                                 if (targs != null) {
2862                                         if (!targs.Resolve (ec))
2863                                                 return null;
2864
2865                                         me.SetTypeArguments (ec, targs);
2866                                 }
2867
2868                                 if (!me.IsStatic && (me.InstanceExpression != null && me.InstanceExpression != EmptyExpression.Null) &&
2869                                     TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2870                                     me.InstanceExpression.Type != me.DeclaringType &&
2871                                     !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2872                                     (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
2873                                         ec.Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
2874                                                 TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type));
2875                                         return null;
2876                                 }
2877
2878                                 return (right_side != null)
2879                                         ? me.DoResolveLValue (ec, right_side)
2880                                         : me.DoResolve (ec);
2881                         }
2882
2883                         return e;
2884                 }
2885         }
2886
2887         /// <summary>
2888         ///   Represents a namespace or a type.  The name of the class was inspired by
2889         ///   section 10.8.1 (Fully Qualified Names).
2890         /// </summary>
2891         public abstract class FullNamedExpression : Expression
2892         {
2893                 protected override void CloneTo (CloneContext clonectx, Expression target)
2894                 {
2895                         // Do nothing, most unresolved type expressions cannot be
2896                         // resolved to different type
2897                 }
2898
2899                 public override Expression CreateExpressionTree (ResolveContext ec)
2900                 {
2901                         throw new NotSupportedException ("ET");
2902                 }
2903
2904                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
2905                 {
2906                         throw new NotSupportedException ();
2907                 }
2908
2909                 public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
2910                 {
2911                         return this;
2912                 }
2913
2914                 public override void Emit (EmitContext ec)
2915                 {
2916                         throw new InternalErrorException ("FullNamedExpression `{0}' found in resolved tree",
2917                                 GetSignatureForError ());
2918                 }
2919         }
2920         
2921         /// <summary>
2922         ///   Expression that evaluates to a type
2923         /// </summary>
2924         public abstract class TypeExpr : FullNamedExpression {
2925                 public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
2926                 {
2927                         TypeExpr t = DoResolveAsTypeStep (ec);
2928                         if (t == null)
2929                                 return null;
2930
2931                         eclass = ExprClass.Type;
2932                         return t;
2933                 }
2934
2935                 override public Expression DoResolve (ResolveContext ec)
2936                 {
2937                         return ResolveAsTypeTerminal (ec, false);
2938                 }
2939
2940                 public virtual bool CheckAccessLevel (IMemberContext mc)
2941                 {
2942                         return mc.CurrentTypeDefinition.CheckAccessLevel (Type);
2943                 }
2944
2945                 public virtual bool IsClass {
2946                         get { return Type.IsClass; }
2947                 }
2948
2949                 public virtual bool IsValueType {
2950                         get { return TypeManager.IsStruct (Type); }
2951                 }
2952
2953                 public virtual bool IsInterface {
2954                         get { return Type.IsInterface; }
2955                 }
2956
2957                 public virtual bool IsSealed {
2958                         get { return Type.IsSealed; }
2959                 }
2960
2961                 public virtual bool CanInheritFrom ()
2962                 {
2963                         if (Type == TypeManager.enum_type ||
2964                             (Type == TypeManager.value_type && RootContext.StdLib) ||
2965                             Type == TypeManager.multicast_delegate_type ||
2966                             Type == TypeManager.delegate_type ||
2967                             Type == TypeManager.array_type)
2968                                 return false;
2969
2970                         return true;
2971                 }
2972
2973                 protected abstract TypeExpr DoResolveAsTypeStep (IMemberContext ec);
2974
2975                 public override bool Equals (object obj)
2976                 {
2977                         TypeExpr tobj = obj as TypeExpr;
2978                         if (tobj == null)
2979                                 return false;
2980
2981                         return Type == tobj.Type;
2982                 }
2983
2984                 public override int GetHashCode ()
2985                 {
2986                         return Type.GetHashCode ();
2987                 }
2988
2989                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
2990                 {
2991                         type = storey.MutateType (type);
2992                 }
2993         }
2994
2995         /// <summary>
2996         ///   Fully resolved Expression that already evaluated to a type
2997         /// </summary>
2998         public class TypeExpression : TypeExpr {
2999                 public TypeExpression (Type t, Location l)
3000                 {
3001                         Type = t;
3002                         eclass = ExprClass.Type;
3003                         loc = l;
3004                 }
3005
3006                 protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec)
3007                 {
3008                         return this;
3009                 }
3010
3011                 public override TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent)
3012                 {
3013                         return this;
3014                 }
3015         }
3016
3017         //
3018         // Used to create types from a fully qualified name.  These are just used
3019         // by the parser to setup the core types.
3020         //
3021         public sealed class TypeLookupExpression : TypeExpr {
3022                 readonly string ns_name;
3023                 readonly string name;
3024                 
3025                 public TypeLookupExpression (string ns, string name)
3026                 {
3027                         this.name = name;
3028                         this.ns_name = ns;
3029                         eclass = ExprClass.Type;
3030                 }
3031
3032                 public override TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent)
3033                 {
3034                         //
3035                         // It's null only during mscorlib bootstrap when DefineType
3036                         // nees to resolve base type of same type
3037                         //
3038                         // For instance struct Char : IComparable<char>
3039                         //
3040                         // TODO: it could be removed when Resolve starts to use 
3041                         // DeclSpace instead of Type
3042                         //
3043                         if (type == null) {
3044                                 Namespace ns = GlobalRootNamespace.Instance.GetNamespace (ns_name, false);
3045                                 FullNamedExpression fne = ns.Lookup (ec.Compiler, name, loc);
3046                                 if (fne != null)
3047                                         type = fne.Type;
3048                         }
3049
3050                         return this;
3051                 }
3052
3053                 protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec)
3054                 {
3055                         return this;
3056                 }
3057
3058                 public override string GetSignatureForError ()
3059                 {
3060                         if (type == null)
3061                                 return TypeManager.CSharpName (ns_name + "." + name, null);
3062
3063                         return base.GetSignatureForError ();
3064                 }
3065         }
3066
3067         /// <summary>
3068         ///   This class denotes an expression which evaluates to a member
3069         ///   of a struct or a class.
3070         /// </summary>
3071         public abstract class MemberExpr : Expression
3072         {
3073                 protected bool is_base;
3074
3075                 /// <summary>
3076                 ///   The name of this member.
3077                 /// </summary>
3078                 public abstract string Name {
3079                         get;
3080                 }
3081
3082                 //
3083                 // When base.member is used
3084                 //
3085                 public bool IsBase {
3086                         get { return is_base; }
3087                         set { is_base = value; }
3088                 }
3089
3090                 /// <summary>
3091                 ///   Whether this is an instance member.
3092                 /// </summary>
3093                 public abstract bool IsInstance {
3094                         get;
3095                 }
3096
3097                 /// <summary>
3098                 ///   Whether this is a static member.
3099                 /// </summary>
3100                 public abstract bool IsStatic {
3101                         get;
3102                 }
3103
3104                 /// <summary>
3105                 ///   The type which declares this member.
3106                 /// </summary>
3107                 public abstract Type DeclaringType {
3108                         get;
3109                 }
3110
3111                 /// <summary>
3112                 ///   The instance expression associated with this member, if it's a
3113                 ///   non-static member.
3114                 /// </summary>
3115                 public Expression InstanceExpression;
3116
3117                 public static void error176 (ResolveContext ec, Location loc, string name)
3118                 {
3119                         ec.Report.Error (176, loc, "Static member `{0}' cannot be accessed " +
3120                                       "with an instance reference, qualify it with a type name instead", name);
3121                 }
3122
3123                 public static void Error_BaseAccessInExpressionTree (ResolveContext ec, Location loc)
3124                 {
3125                         ec.Report.Error (831, loc, "An expression tree may not contain a base access");
3126                 }
3127
3128                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
3129                 {
3130                         if (InstanceExpression != null)
3131                                 InstanceExpression.MutateHoistedGenericType (storey);
3132                 }
3133
3134                 // TODO: possible optimalization
3135                 // Cache resolved constant result in FieldBuilder <-> expression map
3136                 public virtual MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
3137                                                                SimpleName original)
3138                 {
3139                         //
3140                         // Precondition:
3141                         //   original == null || original.Resolve (...) ==> left
3142                         //
3143
3144                         if (left is TypeExpr) {
3145                                 left = left.ResolveAsBaseTerminal (ec, false);
3146                                 if (left == null)
3147                                         return null;
3148
3149                                 // TODO: Same problem as in class.cs, TypeTerminal does not
3150                                 // always do all necessary checks
3151                                 ObsoleteAttribute oa = AttributeTester.GetObsoleteAttribute (left.Type);
3152                                 if (oa != null && !ec.IsObsolete) {
3153                                         AttributeTester.Report_ObsoleteMessage (oa, left.GetSignatureForError (), loc, ec.Report);
3154                                 }
3155
3156                                 GenericTypeExpr ct = left as GenericTypeExpr;
3157                                 if (ct != null && !ct.CheckConstraints (ec))
3158                                         return null;
3159                                 //
3160
3161                                 if (!IsStatic) {
3162                                         SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
3163                                         return null;
3164                                 }
3165
3166                                 return this;
3167                         }
3168                                 
3169                         if (!IsInstance) {
3170                                 if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
3171                                         return this;
3172
3173                                 return ResolveExtensionMemberAccess (ec, left);
3174                         }
3175
3176                         InstanceExpression = left;
3177                         return this;
3178                 }
3179
3180                 protected virtual MemberExpr ResolveExtensionMemberAccess (ResolveContext ec, Expression left)
3181                 {
3182                         error176 (ec, loc, GetSignatureForError ());
3183                         return this;
3184                 }
3185
3186                 protected void EmitInstance (EmitContext ec, bool prepare_for_load)
3187                 {
3188                         if (IsStatic)
3189                                 return;
3190
3191                         if (InstanceExpression == EmptyExpression.Null) {
3192                                 // FIXME: This should not be here at all
3193                                 SimpleName.Error_ObjectRefRequired (new ResolveContext (ec.MemberContext), loc, GetSignatureForError ());
3194                                 return;
3195                         }
3196
3197                         if (TypeManager.IsValueType (InstanceExpression.Type)) {
3198                                 if (InstanceExpression is IMemoryLocation) {
3199                                         ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
3200                                 } else {
3201                                         LocalTemporary t = new LocalTemporary (InstanceExpression.Type);
3202                                         InstanceExpression.Emit (ec);
3203                                         t.Store (ec);
3204                                         t.AddressOf (ec, AddressOp.Store);
3205                                 }
3206                         } else
3207                                 InstanceExpression.Emit (ec);
3208
3209                         if (prepare_for_load)
3210                                 ec.ig.Emit (OpCodes.Dup);
3211                 }
3212
3213                 public virtual void SetTypeArguments (ResolveContext ec, TypeArguments ta)
3214                 {
3215                         // TODO: need to get correct member type
3216                         ec.Report.Error (307, loc, "The property `{0}' cannot be used with type arguments",
3217                                 GetSignatureForError ());
3218                 }
3219         }
3220
3221         /// 
3222         /// Represents group of extension methods
3223         /// 
3224         public class ExtensionMethodGroupExpr : MethodGroupExpr
3225         {
3226                 readonly NamespaceEntry namespace_entry;
3227                 public Expression ExtensionExpression;
3228                 Argument extension_argument;
3229
3230                 public ExtensionMethodGroupExpr (ArrayList list, NamespaceEntry n, Type extensionType, Location l)
3231                         : base (list, extensionType, l)
3232                 {
3233                         this.namespace_entry = n;
3234                 }
3235
3236                 public override bool IsStatic {
3237                         get { return true; }
3238                 }
3239
3240                 public bool IsTopLevel {
3241                         get { return namespace_entry == null; }
3242                 }
3243
3244                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
3245                 {
3246                         extension_argument.Expr.MutateHoistedGenericType (storey);
3247                         base.MutateHoistedGenericType (storey);
3248                 }
3249
3250                 public override MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments arguments, bool may_fail, Location loc)
3251                 {
3252                         if (arguments == null)
3253                                 arguments = new Arguments (1);
3254
3255                         arguments.Insert (0, new Argument (ExtensionExpression));
3256                         MethodGroupExpr mg = ResolveOverloadExtensions (ec, ref arguments, namespace_entry, loc);
3257
3258                         // Store resolved argument and restore original arguments
3259                         if (mg != null)
3260                                 ((ExtensionMethodGroupExpr)mg).extension_argument = arguments [0];
3261                         else
3262                                 arguments.RemoveAt (0); // Clean-up modified arguments for error reporting
3263
3264                         return mg;
3265                 }
3266
3267                 MethodGroupExpr ResolveOverloadExtensions (ResolveContext ec, ref Arguments arguments, NamespaceEntry ns, Location loc)
3268                 {
3269                         // Use normal resolve rules
3270                         MethodGroupExpr mg = base.OverloadResolve (ec, ref arguments, ns != null, loc);
3271                         if (mg != null)
3272                                 return mg;
3273
3274                         if (ns == null)
3275                                 return null;
3276
3277                         // Search continues
3278                         ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, Name, loc);
3279                         if (e == null)
3280                                 return base.OverloadResolve (ec, ref arguments, false, loc);
3281
3282                         e.ExtensionExpression = ExtensionExpression;
3283                         e.SetTypeArguments (ec, type_arguments);                        
3284                         return e.ResolveOverloadExtensions (ec, ref arguments, e.namespace_entry, loc);
3285                 }               
3286         }
3287
3288         /// <summary>
3289         ///   MethodGroupExpr represents a group of method candidates which
3290         ///   can be resolved to the best method overload
3291         /// </summary>
3292         public class MethodGroupExpr : MemberExpr
3293         {
3294                 public interface IErrorHandler
3295                 {
3296                         bool AmbiguousCall (ResolveContext ec, MethodBase ambiguous);
3297                         bool NoExactMatch (ResolveContext ec, MethodBase method);
3298                 }
3299
3300                 public IErrorHandler CustomErrorHandler;                
3301                 public MethodBase [] Methods;
3302                 MethodBase best_candidate;
3303                 // TODO: make private
3304                 public TypeArguments type_arguments;
3305                 bool identical_type_name;
3306                 bool has_inaccessible_candidates_only;
3307                 Type delegate_type;
3308                 Type queried_type;
3309                 
3310                 public MethodGroupExpr (MemberInfo [] mi, Type type, Location l)
3311                         : this (type, l)
3312                 {
3313                         Methods = new MethodBase [mi.Length];
3314                         mi.CopyTo (Methods, 0);
3315                 }
3316
3317                 public MethodGroupExpr (MemberInfo[] mi, Type type, Location l, bool inacessibleCandidatesOnly)
3318                         : this (mi, type, l)
3319                 {
3320                         has_inaccessible_candidates_only = inacessibleCandidatesOnly;
3321                 }
3322
3323                 public MethodGroupExpr (ArrayList list, Type type, Location l)
3324                         : this (type, l)
3325                 {
3326                         try {
3327                                 Methods = (MethodBase[])list.ToArray (typeof (MethodBase));
3328                         } catch {
3329                                 foreach (MemberInfo m in list){
3330                                         if (!(m is MethodBase)){
3331                                                 Console.WriteLine ("Name " + m.Name);
3332                                                 Console.WriteLine ("Found a: " + m.GetType ().FullName);
3333                                         }
3334                                 }
3335                                 throw;
3336                         }
3337
3338
3339                 }
3340
3341                 protected MethodGroupExpr (Type type, Location loc)
3342                 {
3343                         this.loc = loc;
3344                         eclass = ExprClass.MethodGroup;
3345                         this.type = InternalType.MethodGroup;
3346                         queried_type = type;
3347                 }
3348
3349                 public override Type DeclaringType {
3350                         get {
3351                                 return queried_type;
3352                         }
3353                 }
3354
3355                 public Type DelegateType {
3356                         set {
3357                                 delegate_type = value;
3358                         }
3359                 }
3360
3361                 public bool IdenticalTypeName {
3362                         get {
3363                                 return identical_type_name;
3364                         }
3365                 }
3366
3367                 public override string GetSignatureForError ()
3368                 {
3369                         if (best_candidate != null)
3370                                 return TypeManager.CSharpSignature (best_candidate);
3371                         
3372                         return TypeManager.CSharpSignature (Methods [0]);
3373                 }
3374
3375                 public override string Name {
3376                         get {
3377                                 return Methods [0].Name;
3378                         }
3379                 }
3380
3381                 public override bool IsInstance {
3382                         get {
3383                                 if (best_candidate != null)
3384                                         return !best_candidate.IsStatic;
3385
3386                                 foreach (MethodBase mb in Methods)
3387                                         if (!mb.IsStatic)
3388                                                 return true;
3389
3390                                 return false;
3391                         }
3392                 }
3393
3394                 public override bool IsStatic {
3395                         get {
3396                                 if (best_candidate != null)
3397                                         return best_candidate.IsStatic;
3398
3399                                 foreach (MethodBase mb in Methods)
3400                                         if (mb.IsStatic)
3401                                                 return true;
3402
3403                                 return false;
3404                         }
3405                 }
3406                 
3407                 public static explicit operator ConstructorInfo (MethodGroupExpr mg)
3408                 {
3409                         return (ConstructorInfo)mg.best_candidate;
3410                 }
3411
3412                 public static explicit operator MethodInfo (MethodGroupExpr mg)
3413                 {
3414                         return (MethodInfo)mg.best_candidate;
3415                 }
3416
3417                 //
3418                 //  7.4.3.3  Better conversion from expression
3419                 //  Returns :   1    if a->p is better,
3420                 //              2    if a->q is better,
3421                 //              0 if neither is better
3422                 //
3423                 static int BetterExpressionConversion (ResolveContext ec, Argument a, Type p, Type q)
3424                 {
3425                         Type argument_type = TypeManager.TypeToCoreType (a.Type);
3426                         if (argument_type == InternalType.AnonymousMethod && RootContext.Version > LanguageVersion.ISO_2) {
3427                                 //
3428                                 // Uwrap delegate from Expression<T>
3429                                 //
3430                                 if (TypeManager.DropGenericTypeArguments (p) == TypeManager.expression_type) {
3431                                         p = TypeManager.GetTypeArguments (p) [0];
3432                                 }
3433                                 if (TypeManager.DropGenericTypeArguments (q) == TypeManager.expression_type) {
3434                                         q = TypeManager.GetTypeArguments (q) [0];
3435                                 }
3436                                 
3437                                 p = Delegate.GetInvokeMethod (ec.Compiler, null, p).ReturnType;
3438                                 q = Delegate.GetInvokeMethod (ec.Compiler, null, q).ReturnType;
3439                                 if (p == TypeManager.void_type && q != TypeManager.void_type)
3440                                         return 2;
3441                                 if (q == TypeManager.void_type && p != TypeManager.void_type)
3442                                         return 1;
3443                         } else {
3444                                 if (argument_type == p)
3445                                         return 1;
3446
3447                                 if (argument_type == q)
3448                                         return 2;
3449                         }
3450
3451                         return BetterTypeConversion (ec, p, q);
3452                 }
3453
3454                 //
3455                 // 7.4.3.4  Better conversion from type
3456                 //
3457                 public static int BetterTypeConversion (ResolveContext ec, Type p, Type q)
3458                 {
3459                         if (p == null || q == null)
3460                                 throw new InternalErrorException ("BetterTypeConversion got a null conversion");
3461
3462                         if (p == TypeManager.int32_type) {
3463                                 if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
3464                                         return 1;
3465                         } else if (p == TypeManager.int64_type) {
3466                                 if (q == TypeManager.uint64_type)
3467                                         return 1;
3468                         } else if (p == TypeManager.sbyte_type) {
3469                                 if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
3470                                         q == TypeManager.uint32_type || q == TypeManager.uint64_type)
3471                                         return 1;
3472                         } else if (p == TypeManager.short_type) {
3473                                 if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
3474                                         q == TypeManager.uint64_type)
3475                                         return 1;
3476                         }
3477
3478                         if (q == TypeManager.int32_type) {
3479                                 if (p == TypeManager.uint32_type || p == TypeManager.uint64_type)
3480                                         return 2;
3481                         } if (q == TypeManager.int64_type) {
3482                                 if (p == TypeManager.uint64_type)
3483                                         return 2;
3484                         } else if (q == TypeManager.sbyte_type) {
3485                                 if (p == TypeManager.byte_type || p == TypeManager.ushort_type ||
3486                                         p == TypeManager.uint32_type || p == TypeManager.uint64_type)
3487                                         return 2;
3488                         } if (q == TypeManager.short_type) {
3489                                 if (p == TypeManager.ushort_type || p == TypeManager.uint32_type ||
3490                                         p == TypeManager.uint64_type)
3491                                         return 2;
3492                         }
3493
3494                         // TODO: this is expensive
3495                         Expression p_tmp = new EmptyExpression (p);
3496                         Expression q_tmp = new EmptyExpression (q);
3497
3498                         bool p_to_q = Convert.ImplicitConversionExists (ec, p_tmp, q);
3499                         bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p);
3500
3501                         if (p_to_q && !q_to_p)
3502                                 return 1;
3503
3504                         if (q_to_p && !p_to_q)
3505                                 return 2;
3506
3507                         return 0;
3508                 }
3509
3510                 /// <summary>
3511                 ///   Determines "Better function" between candidate
3512                 ///   and the current best match
3513                 /// </summary>
3514                 /// <remarks>
3515                 ///    Returns a boolean indicating :
3516                 ///     false if candidate ain't better
3517                 ///     true  if candidate is better than the current best match
3518                 /// </remarks>
3519                 static bool BetterFunction (ResolveContext ec, Arguments args, int argument_count,
3520                         MethodBase candidate, bool candidate_params,
3521                         MethodBase best, bool best_params)
3522                 {
3523                         AParametersCollection candidate_pd = TypeManager.GetParameterData (candidate);
3524                         AParametersCollection best_pd = TypeManager.GetParameterData (best);
3525                 
3526                         bool better_at_least_one = false;
3527                         bool same = true;
3528                         for (int j = 0, c_idx = 0, b_idx = 0; j < argument_count; ++j, ++c_idx, ++b_idx) 
3529                         {
3530                                 Argument a = args [j];
3531
3532                                 // Provided default argument value is never better
3533                                 if (a.IsDefaultArgument && candidate_params == best_params)
3534                                         return false;
3535
3536                                 Type ct = candidate_pd.Types [c_idx];
3537                                 Type bt = best_pd.Types [b_idx];
3538
3539                                 if (candidate_params && candidate_pd.FixedParameters [c_idx].ModFlags == Parameter.Modifier.PARAMS) 
3540                                 {
3541                                         ct = TypeManager.GetElementType (ct);
3542                                         --c_idx;
3543                                 }
3544
3545                                 if (best_params && best_pd.FixedParameters [b_idx].ModFlags == Parameter.Modifier.PARAMS) 
3546                                 {
3547                                         bt = TypeManager.GetElementType (bt);
3548                                         --b_idx;
3549                                 }
3550
3551                                 if (ct.Equals (bt))
3552                                         continue;
3553
3554                                 same = false;
3555                                 int result = BetterExpressionConversion (ec, a, ct, bt);
3556
3557                                 // for each argument, the conversion to 'ct' should be no worse than 
3558                                 // the conversion to 'bt'.
3559                                 if (result == 2)
3560                                         return false;
3561
3562                                 // for at least one argument, the conversion to 'ct' should be better than 
3563                                 // the conversion to 'bt'.
3564                                 if (result != 0)
3565                                         better_at_least_one = true;
3566                         }
3567
3568                         if (better_at_least_one)
3569                                 return true;
3570
3571                         //
3572                         // This handles the case
3573                         //
3574                         //   Add (float f1, float f2, float f3);
3575                         //   Add (params decimal [] foo);
3576                         //
3577                         // The call Add (3, 4, 5) should be ambiguous.  Without this check, the
3578                         // first candidate would've chosen as better.
3579                         //
3580                         if (!same)
3581                                 return false;
3582
3583                         //
3584                         // The two methods have equal parameter types.  Now apply tie-breaking rules
3585                         //
3586                         if (TypeManager.IsGenericMethod (best)) {
3587                                 if (!TypeManager.IsGenericMethod (candidate))
3588                                         return true;
3589                         } else if (TypeManager.IsGenericMethod (candidate)) {
3590                                 return false;
3591                         }
3592
3593                         //
3594                         // This handles the following cases:
3595                         //
3596                         //   Trim () is better than Trim (params char[] chars)
3597                         //   Concat (string s1, string s2, string s3) is better than
3598                         //     Concat (string s1, params string [] srest)
3599                         //   Foo (int, params int [] rest) is better than Foo (params int [] rest)
3600                         //
3601                         if (!candidate_params && best_params)
3602                                 return true;
3603                         if (candidate_params && !best_params)
3604                                 return false;
3605
3606                         int candidate_param_count = candidate_pd.Count;
3607                         int best_param_count = best_pd.Count;
3608
3609                         if (candidate_param_count != best_param_count)
3610                                 // can only happen if (candidate_params && best_params)
3611                                 return candidate_param_count > best_param_count && best_pd.HasParams;
3612
3613                         //
3614                         // now, both methods have the same number of parameters, and the parameters have the same types
3615                         // Pick the "more specific" signature
3616                         //
3617
3618                         MethodBase orig_candidate = TypeManager.DropGenericMethodArguments (candidate);
3619                         MethodBase orig_best = TypeManager.DropGenericMethodArguments (best);
3620
3621                         AParametersCollection orig_candidate_pd = TypeManager.GetParameterData (orig_candidate);
3622                         AParametersCollection orig_best_pd = TypeManager.GetParameterData (orig_best);
3623
3624                         bool specific_at_least_once = false;
3625                         for (int j = 0; j < candidate_param_count; ++j) 
3626                         {
3627                                 Type ct = orig_candidate_pd.Types [j];
3628                                 Type bt = orig_best_pd.Types [j];
3629                                 if (ct.Equals (bt))
3630                                         continue;
3631                                 Type specific = MoreSpecific (ct, bt);
3632                                 if (specific == bt)
3633                                         return false;
3634                                 if (specific == ct)
3635                                         specific_at_least_once = true;
3636                         }
3637
3638                         if (specific_at_least_once)
3639                                 return true;
3640
3641                         // FIXME: handle lifted operators
3642                         // ...
3643
3644                         return false;
3645                 }
3646
3647                 protected override MemberExpr ResolveExtensionMemberAccess (ResolveContext ec, Expression left)
3648                 {
3649                         if (!IsStatic)
3650                                 return base.ResolveExtensionMemberAccess (ec, left);
3651
3652                         //
3653                         // When left side is an expression and at least one candidate method is 
3654                         // static, it can be extension method
3655                         //
3656                         InstanceExpression = left;
3657                         return this;
3658                 }
3659
3660                 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
3661                                                                 SimpleName original)
3662                 {
3663                         if (!(left is TypeExpr) &&
3664                             original != null && original.IdenticalNameAndTypeName (ec, left, loc))
3665                                 identical_type_name = true;
3666
3667                         return base.ResolveMemberAccess (ec, left, loc, original);
3668                 }
3669
3670                 public override Expression CreateExpressionTree (ResolveContext ec)
3671                 {
3672                         if (best_candidate == null) {
3673                                 ec.Report.Error (1953, loc, "An expression tree cannot contain an expression with method group");
3674                                 return null;
3675                         }
3676
3677                         IMethodData md = TypeManager.GetMethod (best_candidate);
3678                         if (md != null && md.IsExcluded ())
3679                                 ec.Report.Error (765, loc,
3680                                         "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
3681                         
3682                         return new TypeOfMethod (best_candidate, loc);
3683                 }
3684                 
3685                 override public Expression DoResolve (ResolveContext ec)
3686                 {
3687                         if (InstanceExpression != null) {
3688                                 InstanceExpression = InstanceExpression.DoResolve (ec);
3689                                 if (InstanceExpression == null)
3690                                         return null;
3691                         }
3692
3693                         return this;
3694                 }
3695
3696                 public void ReportUsageError (ResolveContext ec)
3697                 {
3698                         ec.Report.Error (654, loc, "Method `" + DeclaringType + "." +
3699                                       Name + "()' is referenced without parentheses");
3700                 }
3701
3702                 override public void Emit (EmitContext ec)
3703                 {
3704                         throw new NotSupportedException ();
3705                         // ReportUsageError ();
3706                 }
3707                 
3708                 public void EmitCall (EmitContext ec, Arguments arguments)
3709                 {
3710                         Invocation.EmitCall (ec, IsBase, InstanceExpression, best_candidate, arguments, loc);                   
3711                 }
3712
3713                 void Error_AmbiguousCall (ResolveContext ec, MethodBase ambiguous)
3714                 {
3715                         if (CustomErrorHandler != null && CustomErrorHandler.AmbiguousCall (ec, ambiguous))
3716                                 return;
3717
3718                         ec.Report.SymbolRelatedToPreviousError (best_candidate);
3719                         ec.Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'",
3720                                 TypeManager.CSharpSignature (ambiguous), TypeManager.CSharpSignature (best_candidate));
3721                 }
3722
3723                 protected virtual void Error_InvalidArguments (ResolveContext ec, Location loc, int idx, MethodBase method,
3724                                                                                                         Argument a, AParametersCollection expected_par, Type paramType)
3725                 {
3726                         ExtensionMethodGroupExpr emg = this as ExtensionMethodGroupExpr;
3727
3728                         if (a is CollectionElementInitializer.ElementInitializerArgument) {
3729                                 ec.Report.SymbolRelatedToPreviousError (method);
3730                                 if ((expected_par.FixedParameters [idx].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
3731                                         ec.Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier",
3732                                                 TypeManager.CSharpSignature (method));
3733                                         return;
3734                                 }
3735                                 ec.Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments",
3736                                           TypeManager.CSharpSignature (method));
3737                         } else if (TypeManager.IsDelegateType (method.DeclaringType)) {
3738                                 ec.Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments",
3739                                         TypeManager.CSharpName (method.DeclaringType));
3740                         } else {
3741                                 ec.Report.SymbolRelatedToPreviousError (method);
3742                                 if (emg != null) {
3743                                         ec.Report.Error (1928, loc,
3744                                                 "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' has some invalid arguments",
3745                                                 emg.ExtensionExpression.GetSignatureForError (),
3746                                                 emg.Name, TypeManager.CSharpSignature (method));
3747                                 } else {
3748                                         ec.Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments",
3749                                                 TypeManager.CSharpSignature (method));
3750                                 }
3751                         }
3752
3753                         Parameter.Modifier mod = idx >= expected_par.Count ? 0 : expected_par.FixedParameters [idx].ModFlags;
3754
3755                         string index = (idx + 1).ToString ();
3756                         if (((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) ^
3757                                 (a.Modifier & (Parameter.Modifier.REF | Parameter.Modifier.OUT))) != 0) {
3758                                 if ((mod & Parameter.Modifier.ISBYREF) == 0)
3759                                         ec.Report.Error (1615, loc, "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' modifier",
3760                                                 index, Parameter.GetModifierSignature (a.Modifier));
3761                                 else
3762                                         ec.Report.Error (1620, loc, "Argument `#{0}' is missing `{1}' modifier",
3763                                                 index, Parameter.GetModifierSignature (mod));
3764                         } else {
3765                                 string p1 = a.GetSignatureForError ();
3766                                 string p2 = TypeManager.CSharpName (paramType);
3767
3768                                 if (p1 == p2) {
3769                                         ec.Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous ");
3770                                         ec.Report.SymbolRelatedToPreviousError (a.Expr.Type);
3771                                         ec.Report.SymbolRelatedToPreviousError (paramType);
3772                                 }
3773
3774                                 if (idx == 0 && emg != null) {
3775                                         ec.Report.Error (1929, loc,
3776                                                 "Extension method instance type `{0}' cannot be converted to `{1}'", p1, p2);
3777                                 } else {
3778                                         ec.Report.Error (1503, loc,
3779                                                 "Argument `#{0}' cannot convert `{1}' expression to type `{2}'", index, p1, p2);
3780                                 }
3781                         }
3782                 }
3783
3784                 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, Type target, bool expl)
3785                 {
3786                         ec.Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method",
3787                                 Name, TypeManager.CSharpName (target));
3788                 }
3789
3790                 void Error_ArgumentCountWrong (ResolveContext ec, int arg_count)
3791                 {
3792                         ec.Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments",
3793                                       Name, arg_count.ToString ());
3794                 }
3795                 
3796                 protected virtual int GetApplicableParametersCount (MethodBase method, AParametersCollection parameters)
3797                 {
3798                         return parameters.Count;
3799                 }               
3800
3801                 public static bool IsAncestralType (Type first_type, Type second_type)
3802                 {
3803                         return first_type != second_type &&
3804                                 (TypeManager.IsSubclassOf (second_type, first_type) ||
3805                                 TypeManager.ImplementsInterface (second_type, first_type));
3806                 }
3807
3808                 ///
3809                 /// Determines if the candidate method is applicable (section 14.4.2.1)
3810                 /// to the given set of arguments
3811                 /// A return value rates candidate method compatibility,
3812                 /// 0 = the best, int.MaxValue = the worst
3813                 ///
3814                 public int IsApplicable (ResolveContext ec,
3815                                                 ref Arguments arguments, int arg_count, ref MethodBase method, ref bool params_expanded_form)
3816                 {
3817                         MethodBase candidate = method;
3818
3819                         AParametersCollection pd = TypeManager.GetParameterData (candidate);
3820                         int param_count = GetApplicableParametersCount (candidate, pd);
3821                         int optional_count = 0;
3822
3823                         if (arg_count != param_count) {
3824                                 for (int i = 0; i < pd.Count; ++i) {
3825                                         if (pd.FixedParameters [i].HasDefaultValue) {
3826                                                 optional_count = pd.Count - i;
3827                                                 break;
3828                                         }
3829                                 }
3830
3831                                 int args_gap = Math.Abs (arg_count - param_count);
3832                                 if (optional_count != 0) {
3833                                         if (args_gap > optional_count)
3834                                                 return int.MaxValue - 10000 + args_gap - optional_count;
3835
3836                                         // Readjust expected number when params used
3837                                         if (pd.HasParams) {
3838                                                 optional_count--;
3839                                                 if (arg_count < param_count)
3840                                                         param_count--;
3841                                         } else if (arg_count > param_count) {
3842                                                 return int.MaxValue - 10000 + args_gap;
3843                                         }
3844                                 } else if (arg_count != param_count) {
3845                                         if (!pd.HasParams)
3846                                                 return int.MaxValue - 10000 + args_gap;
3847                                         if (arg_count < param_count - 1)
3848                                                 return int.MaxValue - 10000 + args_gap;
3849                                 }
3850
3851                                 // Initialize expanded form of a method with 1 params parameter
3852                                 params_expanded_form = param_count == 1 && pd.HasParams;
3853
3854                                 // Resize to fit optional arguments
3855                                 if (optional_count != 0) {
3856                                         Arguments resized;
3857                                         if (arguments == null) {
3858                                                 resized = new Arguments (optional_count);
3859                                         } else {
3860                                                 resized = new Arguments (param_count);
3861                                                 resized.AddRange (arguments);
3862                                         }
3863
3864                                         for (int i = arg_count; i < param_count; ++i)
3865                                                 resized.Add (null);
3866                                         arguments = resized;
3867                                 }
3868                         }
3869
3870                         if (arg_count > 0) {
3871                                 //
3872                                 // Shuffle named arguments to the right positions if there are any
3873                                 //
3874                                 if (arguments [arg_count - 1] is NamedArgument) {
3875                                         arg_count = arguments.Count;
3876
3877                                         for (int i = 0; i < arg_count; ++i) {
3878                                                 bool arg_moved = false;
3879                                                 while (true) {
3880                                                         NamedArgument na = arguments[i] as NamedArgument;
3881                                                         if (na == null)
3882                                                                 break;
3883
3884                                                         int index = pd.GetParameterIndexByName (na.Name.Value);
3885
3886                                                         // Named parameter not found or already reordered
3887                                                         if (index <= i)
3888                                                                 break;
3889
3890                                                         // When using parameters which should not be available to the user
3891                                                         if (index >= param_count)
3892                                                                 break;
3893
3894                                                         if (!arg_moved) {
3895                                                                 arguments.MarkReorderedArgument (na);
3896                                                                 arg_moved = true;
3897                                                         }
3898
3899                                                         Argument temp = arguments[index];
3900                                                         arguments[index] = arguments[i];
3901                                                         arguments[i] = temp;
3902
3903                                                         if (temp == null)
3904                                                                 break;
3905                                                 }
3906                                         }
3907                                 } else {
3908                                         arg_count = arguments.Count;
3909                                 }
3910                         } else if (arguments != null) {
3911                                 arg_count = arguments.Count;
3912                         }
3913
3914                         //
3915                         // 1. Handle generic method using type arguments when specified or type inference
3916                         //
3917                         if (TypeManager.IsGenericMethod (candidate)) {
3918                                 if (type_arguments != null) {
3919                                         Type [] g_args = candidate.GetGenericArguments ();
3920                                         if (g_args.Length != type_arguments.Count)
3921                                                 return int.MaxValue - 20000 + Math.Abs (type_arguments.Count - g_args.Length);
3922
3923                                         // TODO: Don't create new method, create Parameters only
3924                                         method = ((MethodInfo) candidate).MakeGenericMethod (type_arguments.Arguments);
3925                                         candidate = method;
3926                                         pd = TypeManager.GetParameterData (candidate);
3927                                 } else {
3928                                         int score = TypeManager.InferTypeArguments (ec, arguments, ref candidate);
3929                                         if (score != 0)
3930                                                 return score - 20000;
3931
3932                                         if (TypeManager.IsGenericMethodDefinition (candidate))
3933                                                 throw new InternalErrorException ("A generic method `{0}' definition took part in overload resolution",
3934                                                         TypeManager.CSharpSignature (candidate));
3935
3936                                         pd = TypeManager.GetParameterData (candidate);
3937                                 }
3938                         } else {
3939                                 if (type_arguments != null)
3940                                         return int.MaxValue - 15000;
3941                         }
3942
3943                         //
3944                         // 2. Each argument has to be implicitly convertible to method parameter
3945                         //
3946                         method = candidate;
3947                         Parameter.Modifier p_mod = 0;
3948                         Type pt = null;
3949                         for (int i = 0; i < arg_count; i++) {
3950                                 Argument a = arguments [i];
3951                                 if (a == null) {
3952                                         if (!pd.FixedParameters [i].HasDefaultValue)
3953                                                 throw new InternalErrorException ();
3954
3955                                         Expression e = pd.FixedParameters [i].DefaultValue as Constant;
3956                                         if (e == null)
3957                                                 e = new DefaultValueExpression (new TypeExpression (pd.Types [i], loc), loc).Resolve (ec);
3958
3959                                         arguments [i] = new Argument (e, Argument.AType.Default);
3960                                         continue;
3961                                 }
3962
3963                                 if (p_mod != Parameter.Modifier.PARAMS) {
3964                                         p_mod = pd.FixedParameters [i].ModFlags & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
3965                                         pt = pd.Types [i];
3966                                 } else {
3967                                         params_expanded_form = true;
3968                                 }
3969
3970                                 Parameter.Modifier a_mod = a.Modifier & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
3971                                 int score = 1;
3972                                 if (!params_expanded_form)
3973                                         score = IsArgumentCompatible (ec, a_mod, a, p_mod & ~Parameter.Modifier.PARAMS, pt);
3974
3975                                 if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && delegate_type == null) {
3976                                         // It can be applicable in expanded form
3977                                         score = IsArgumentCompatible (ec, a_mod, a, 0, TypeManager.GetElementType (pt));
3978                                         if (score == 0)
3979                                                 params_expanded_form = true;
3980                                 }
3981
3982                                 if (score != 0) {
3983                                         if (params_expanded_form)
3984                                                 ++score;
3985                                         return (arg_count - i) * 2 + score;
3986                                 }
3987                         }
3988                         
3989                         if (arg_count != param_count)
3990                                 params_expanded_form = true;    
3991                         
3992                         return 0;
3993                 }
3994
3995                 int IsArgumentCompatible (ResolveContext ec, Parameter.Modifier arg_mod, Argument argument, Parameter.Modifier param_mod, Type parameter)
3996                 {
3997                         //
3998                         // Types have to be identical when ref or out modifer is used 
3999                         //
4000                         if (arg_mod != 0 || param_mod != 0) {
4001                                 if (TypeManager.HasElementType (parameter))
4002                                         parameter = TypeManager.GetElementType (parameter);
4003
4004                                 Type a_type = argument.Type;
4005                                 if (TypeManager.HasElementType (a_type))
4006                                         a_type = TypeManager.GetElementType (a_type);
4007
4008                                 if (a_type != parameter)
4009                                         return 2;
4010                         } else {
4011                                 if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter))
4012                                         return 2;
4013                         }
4014
4015                         if (arg_mod != param_mod)
4016                                 return 1;
4017
4018                         return 0;
4019                 }
4020
4021                 public static bool IsOverride (MethodBase cand_method, MethodBase base_method)
4022                 {
4023                         if (!IsAncestralType (base_method.DeclaringType, cand_method.DeclaringType))
4024                                 return false;
4025
4026                         AParametersCollection cand_pd = TypeManager.GetParameterData (cand_method);
4027                         AParametersCollection base_pd = TypeManager.GetParameterData (base_method);
4028                 
4029                         if (cand_pd.Count != base_pd.Count)
4030                                 return false;
4031
4032                         for (int j = 0; j < cand_pd.Count; ++j) 
4033                         {
4034                                 Parameter.Modifier cm = cand_pd.FixedParameters [j].ModFlags;
4035                                 Parameter.Modifier bm = base_pd.FixedParameters [j].ModFlags;
4036                                 Type ct = cand_pd.Types [j];
4037                                 Type bt = base_pd.Types [j];
4038
4039                                 if (cm != bm || ct != bt)
4040                                         return false;
4041                         }
4042
4043                         return true;
4044                 }
4045
4046                 public static MethodGroupExpr MakeUnionSet (MethodGroupExpr mg1, MethodGroupExpr mg2, Location loc)
4047                 {
4048                         if (mg1 == null) {
4049                                 if (mg2 == null)
4050                                         return null;
4051                                 return mg2;
4052                         }
4053
4054                         if (mg2 == null)
4055                                 return mg1;
4056                         
4057                         ArrayList all = new ArrayList (mg1.Methods);
4058                         foreach (MethodBase m in mg2.Methods){
4059                                 if (!TypeManager.ArrayContainsMethod (mg1.Methods, m, false))
4060                                         all.Add (m);
4061                         }
4062
4063                         return new MethodGroupExpr (all, null, loc);
4064                 }               
4065
4066                 static Type MoreSpecific (Type p, Type q)
4067                 {
4068                         if (TypeManager.IsGenericParameter (p) && !TypeManager.IsGenericParameter (q))
4069                                 return q;
4070                         if (!TypeManager.IsGenericParameter (p) && TypeManager.IsGenericParameter (q))
4071                                 return p;
4072
4073                         if (TypeManager.HasElementType (p)) 
4074                         {
4075                                 Type pe = TypeManager.GetElementType (p);
4076                                 Type qe = TypeManager.GetElementType (q);
4077                                 Type specific = MoreSpecific (pe, qe);
4078                                 if (specific == pe)
4079                                         return p;
4080                                 if (specific == qe)
4081                                         return q;
4082                         } 
4083                         else if (TypeManager.IsGenericType (p)) 
4084                         {
4085                                 Type[] pargs = TypeManager.GetTypeArguments (p);
4086                                 Type[] qargs = TypeManager.GetTypeArguments (q);
4087
4088                                 bool p_specific_at_least_once = false;
4089                                 bool q_specific_at_least_once = false;
4090
4091                                 for (int i = 0; i < pargs.Length; i++) 
4092                                 {
4093                                         Type specific = MoreSpecific (TypeManager.TypeToCoreType (pargs [i]), TypeManager.TypeToCoreType (qargs [i]));
4094                                         if (specific == pargs [i])
4095                                                 p_specific_at_least_once = true;
4096                                         if (specific == qargs [i])
4097                                                 q_specific_at_least_once = true;
4098                                 }
4099
4100                                 if (p_specific_at_least_once && !q_specific_at_least_once)
4101                                         return p;
4102                                 if (!p_specific_at_least_once && q_specific_at_least_once)
4103                                         return q;
4104                         }
4105
4106                         return null;
4107                 }
4108
4109                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
4110                 {
4111                         base.MutateHoistedGenericType (storey);
4112
4113                         MethodInfo mi = best_candidate as MethodInfo;
4114                         if (mi != null) {
4115                                 best_candidate = storey.MutateGenericMethod (mi);
4116                                 return;
4117                         }
4118
4119                         best_candidate = storey.MutateConstructor ((ConstructorInfo) this);
4120                 }
4121
4122                 /// <summary>
4123                 ///   Find the Applicable Function Members (7.4.2.1)
4124                 ///
4125                 ///   me: Method Group expression with the members to select.
4126                 ///       it might contain constructors or methods (or anything
4127                 ///       that maps to a method).
4128                 ///
4129                 ///   Arguments: ArrayList containing resolved Argument objects.
4130                 ///
4131                 ///   loc: The location if we want an error to be reported, or a Null
4132                 ///        location for "probing" purposes.
4133                 ///
4134                 ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
4135                 ///            that is the best match of me on Arguments.
4136                 ///
4137                 /// </summary>
4138                 public virtual MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments Arguments,
4139                         bool may_fail, Location loc)
4140                 {
4141                         bool method_params = false;
4142                         Type applicable_type = null;
4143                         ArrayList candidates = new ArrayList (2);
4144                         ArrayList candidate_overrides = null;
4145
4146                         //
4147                         // Used to keep a map between the candidate
4148                         // and whether it is being considered in its
4149                         // normal or expanded form
4150                         //
4151                         // false is normal form, true is expanded form
4152                         //
4153                         Hashtable candidate_to_form = null;
4154                         Hashtable candidates_expanded = null;
4155                         Arguments candidate_args = Arguments;
4156
4157                         int arg_count = Arguments != null ? Arguments.Count : 0;
4158
4159                         if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
4160                                 if (!may_fail)
4161                                         ec.Report.Error (1533, loc, "Invoke cannot be called directly on a delegate");
4162                                 return null;
4163                         }
4164
4165                         int nmethods = Methods.Length;
4166
4167                         if (!IsBase) {
4168                                 //
4169                                 // Methods marked 'override' don't take part in 'applicable_type'
4170                                 // computation, nor in the actual overload resolution.
4171                                 // However, they still need to be emitted instead of a base virtual method.
4172                                 // So, we salt them away into the 'candidate_overrides' array.
4173                                 //
4174                                 // In case of reflected methods, we replace each overriding method with
4175                                 // its corresponding base virtual method.  This is to improve compatibility
4176                                 // with non-C# libraries which change the visibility of overrides (#75636)
4177                                 //
4178                                 int j = 0;
4179                                 for (int i = 0; i < Methods.Length; ++i) {
4180                                         MethodBase m = Methods [i];
4181                                         if (TypeManager.IsOverride (m)) {
4182                                                 if (candidate_overrides == null)
4183                                                         candidate_overrides = new ArrayList ();
4184                                                 candidate_overrides.Add (m);
4185                                                 m = TypeManager.TryGetBaseDefinition (m);
4186                                         }
4187                                         if (m != null)
4188                                                 Methods [j++] = m;
4189                                 }
4190                                 nmethods = j;
4191                         }
4192
4193                         //
4194                         // Enable message recording, it's used mainly by lambda expressions
4195                         //
4196                         SessionReportPrinter msg_recorder = new SessionReportPrinter ();
4197                         ReportPrinter prev_recorder = ec.Report.SetPrinter (msg_recorder);
4198
4199                         //
4200                         // First we construct the set of applicable methods
4201                         //
4202                         bool is_sorted = true;
4203                         int best_candidate_rate = int.MaxValue;
4204                         for (int i = 0; i < nmethods; i++) {
4205                                 Type decl_type = Methods [i].DeclaringType;
4206
4207                                 //
4208                                 // If we have already found an applicable method
4209                                 // we eliminate all base types (Section 14.5.5.1)
4210                                 //
4211                                 if (applicable_type != null && IsAncestralType (decl_type, applicable_type))
4212                                         continue;
4213
4214                                 //
4215                                 // Check if candidate is applicable (section 14.4.2.1)
4216                                 //
4217                                 bool params_expanded_form = false;
4218                                 int candidate_rate = IsApplicable (ec, ref candidate_args, arg_count, ref Methods [i], ref params_expanded_form);
4219
4220                                 if (candidate_rate < best_candidate_rate) {
4221                                         best_candidate_rate = candidate_rate;
4222                                         best_candidate = Methods [i];
4223                                 }
4224                                 
4225                                 if (params_expanded_form) {
4226                                         if (candidate_to_form == null)
4227                                                 candidate_to_form = new PtrHashtable ();
4228                                         MethodBase candidate = Methods [i];
4229                                         candidate_to_form [candidate] = candidate;
4230                                 }
4231                                 
4232                                 if (candidate_args != Arguments) {
4233                                         if (candidates_expanded == null)
4234                                                 candidates_expanded = new Hashtable (2);
4235
4236                                         candidates_expanded.Add (Methods [i], candidate_args);
4237                                         candidate_args = Arguments;
4238                                 }
4239
4240                                 if (candidate_rate != 0 || has_inaccessible_candidates_only) {
4241                                         if (msg_recorder != null)
4242                                                 msg_recorder.EndSession ();
4243                                         continue;
4244                                 }
4245
4246                                 msg_recorder = null;
4247                                 candidates.Add (Methods [i]);
4248
4249                                 if (applicable_type == null)
4250                                         applicable_type = decl_type;
4251                                 else if (applicable_type != decl_type) {
4252                                         is_sorted = false;
4253                                         if (IsAncestralType (applicable_type, decl_type))
4254                                                 applicable_type = decl_type;
4255                                 }
4256                         }
4257
4258                         ec.Report.SetPrinter (prev_recorder);
4259                         if (msg_recorder != null && !msg_recorder.IsEmpty) {
4260                                 if (!may_fail)
4261                                         msg_recorder.Merge (prev_recorder);
4262
4263                                 return null;
4264                         }
4265                         
4266                         int candidate_top = candidates.Count;
4267
4268                         if (applicable_type == null) {
4269                                 //
4270                                 // When we found a top level method which does not match and it's 
4271                                 // not an extension method. We start extension methods lookup from here
4272                                 //
4273                                 if (InstanceExpression != null) {
4274                                         ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (type, Name, loc);
4275                                         if (ex_method_lookup != null) {
4276                                                 ex_method_lookup.ExtensionExpression = InstanceExpression;
4277                                                 ex_method_lookup.SetTypeArguments (ec, type_arguments);
4278                                                 return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc);
4279                                         }
4280                                 }
4281                                 
4282                                 if (may_fail)
4283                                         return null;
4284
4285                                 //
4286                                 // Okay so we have failed to find exact match so we
4287                                 // return error info about the closest match
4288                                 //
4289                                 if (best_candidate != null) {
4290                                         if (CustomErrorHandler != null && !has_inaccessible_candidates_only && CustomErrorHandler.NoExactMatch (ec, best_candidate))
4291                                                 return null;
4292
4293                                         AParametersCollection pd = TypeManager.GetParameterData (best_candidate);
4294                                         bool cand_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
4295                                         if (arg_count == pd.Count || pd.HasParams) {
4296                                                 if (TypeManager.IsGenericMethodDefinition (best_candidate)) {
4297                                                         if (type_arguments == null) {
4298                                                                 ec.Report.Error (411, loc,
4299                                                                         "The type arguments for method `{0}' cannot be inferred from " +
4300                                                                         "the usage. Try specifying the type arguments explicitly",
4301                                                                         TypeManager.CSharpSignature (best_candidate));
4302                                                                 return null;
4303                                                         }
4304
4305                                                         Type[] g_args = TypeManager.GetGenericArguments (best_candidate);
4306                                                         if (type_arguments.Count != g_args.Length) {
4307                                                                 ec.Report.SymbolRelatedToPreviousError (best_candidate);
4308                                                                 ec.Report.Error (305, loc, "Using the generic method `{0}' requires `{1}' type argument(s)",
4309                                                                         TypeManager.CSharpSignature (best_candidate),
4310                                                                         g_args.Length.ToString ());
4311                                                                 return null;
4312                                                         }
4313                                                 } else {
4314                                                         if (type_arguments != null && !TypeManager.IsGenericMethod (best_candidate)) {
4315                                                                 Error_TypeArgumentsCannotBeUsed (ec.Report, loc);
4316                                                                 return null;
4317                                                         }
4318                                                 }
4319
4320                                                 if (has_inaccessible_candidates_only) {
4321                                                         if (InstanceExpression != null && type != ec.CurrentType && TypeManager.IsNestedFamilyAccessible (ec.CurrentType, best_candidate.DeclaringType)) {
4322                                                                 // Although a derived class can access protected members of
4323                                                                 // its base class it cannot do so through an instance of the
4324                                                                 // base class (CS1540).  If the qualifier_type is a base of the
4325                                                                 // ec.CurrentType and the lookup succeeds with the latter one,
4326                                                                 // then we are in this situation.
4327                                                                 Error_CannotAccessProtected (ec, loc, best_candidate, queried_type, ec.CurrentType);
4328                                                         } else {
4329                                                                 ec.Report.SymbolRelatedToPreviousError (best_candidate);
4330                                                                 ErrorIsInaccesible (loc, GetSignatureForError (), ec.Report);
4331                                                         }
4332                                                 }
4333
4334                                                 if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, cand_params, may_fail, loc))
4335                                                         return null;
4336
4337                                                 if (has_inaccessible_candidates_only)
4338                                                         return null;
4339
4340                                                 throw new InternalErrorException ("VerifyArgumentsCompat didn't find any problem with rejected candidate " + best_candidate);
4341                                         }
4342                                 }
4343
4344                                 //
4345                                 // We failed to find any method with correct argument count
4346                                 //
4347                                 if (Name == ConstructorInfo.ConstructorName) {
4348                                         ec.Report.SymbolRelatedToPreviousError (queried_type);
4349                                         ec.Report.Error (1729, loc,
4350                                                 "The type `{0}' does not contain a constructor that takes `{1}' arguments",
4351                                                 TypeManager.CSharpName (queried_type), arg_count);
4352                                 } else {
4353                                         Error_ArgumentCountWrong (ec, arg_count);
4354                                 }
4355                                 
4356                                 return null;
4357                         }
4358
4359                         if (!is_sorted) {
4360                                 //
4361                                 // At this point, applicable_type is _one_ of the most derived types
4362                                 // in the set of types containing the methods in this MethodGroup.
4363                                 // Filter the candidates so that they only contain methods from the
4364                                 // most derived types.
4365                                 //
4366
4367                                 int finalized = 0; // Number of finalized candidates
4368
4369                                 do {
4370                                         // Invariant: applicable_type is a most derived type
4371                                         
4372                                         // We'll try to complete Section 14.5.5.1 for 'applicable_type' by 
4373                                         // eliminating all it's base types.  At the same time, we'll also move
4374                                         // every unrelated type to the end of the array, and pick the next
4375                                         // 'applicable_type'.
4376
4377                                         Type next_applicable_type = null;
4378                                         int j = finalized; // where to put the next finalized candidate
4379                                         int k = finalized; // where to put the next undiscarded candidate
4380                                         for (int i = finalized; i < candidate_top; ++i) {
4381                                                 MethodBase candidate = (MethodBase) candidates [i];
4382                                                 Type decl_type = candidate.DeclaringType;
4383
4384                                                 if (decl_type == applicable_type) {
4385                                                         candidates [k++] = candidates [j];
4386                                                         candidates [j++] = candidates [i];
4387                                                         continue;
4388                                                 }
4389
4390                                                 if (IsAncestralType (decl_type, applicable_type))
4391                                                         continue;
4392
4393                                                 if (next_applicable_type != null &&
4394                                                         IsAncestralType (decl_type, next_applicable_type))
4395                                                         continue;
4396
4397                                                 candidates [k++] = candidates [i];
4398
4399                                                 if (next_applicable_type == null ||
4400                                                         IsAncestralType (next_applicable_type, decl_type))
4401                                                         next_applicable_type = decl_type;
4402                                         }
4403
4404                                         applicable_type = next_applicable_type;
4405                                         finalized = j;
4406                                         candidate_top = k;
4407                                 } while (applicable_type != null);
4408                         }
4409
4410                         //
4411                         // Now we actually find the best method
4412                         //
4413
4414                         best_candidate = (MethodBase) candidates [0];
4415                         method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
4416
4417                         //
4418                         // TODO: Broken inverse order of candidates logic does not work with optional
4419                         // parameters used for method overrides and I am not going to fix it for SRE
4420                         //
4421                         if (candidates_expanded != null && candidates_expanded.Contains (best_candidate)) {
4422                                 candidate_args = (Arguments) candidates_expanded [best_candidate];
4423                                 arg_count = candidate_args.Count;
4424                         }
4425
4426                         for (int ix = 1; ix < candidate_top; ix++) {
4427                                 MethodBase candidate = (MethodBase) candidates [ix];
4428
4429                                 if (candidate == best_candidate)
4430                                         continue;
4431
4432                                 bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
4433
4434                                 if (BetterFunction (ec, candidate_args, arg_count, 
4435                                         candidate, cand_params,
4436                                         best_candidate, method_params)) {
4437                                         best_candidate = candidate;
4438                                         method_params = cand_params;
4439                                 }
4440                         }
4441                         //
4442                         // Now check that there are no ambiguities i.e the selected method
4443                         // should be better than all the others
4444                         //
4445                         MethodBase ambiguous = null;
4446                         for (int ix = 1; ix < candidate_top; ix++) {
4447                                 MethodBase candidate = (MethodBase) candidates [ix];
4448
4449                                 if (candidate == best_candidate)
4450                                         continue;
4451
4452                                 bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
4453                                 if (!BetterFunction (ec, candidate_args, arg_count,
4454                                         best_candidate, method_params,
4455                                         candidate, cand_params)) 
4456                                 {
4457                                         if (!may_fail)
4458                                                 ec.Report.SymbolRelatedToPreviousError (candidate);
4459                                         ambiguous = candidate;
4460                                 }
4461                         }
4462
4463                         if (ambiguous != null) {
4464                                 Error_AmbiguousCall (ec, ambiguous);
4465                                 return this;
4466                         }
4467
4468                         //
4469                         // If the method is a virtual function, pick an override closer to the LHS type.
4470                         //
4471                         if (!IsBase && best_candidate.IsVirtual) {
4472                                 if (TypeManager.IsOverride (best_candidate))
4473                                         throw new InternalErrorException (
4474                                                 "Should not happen.  An 'override' method took part in overload resolution: " + best_candidate);
4475
4476                                 if (candidate_overrides != null) {
4477                                         Type[] gen_args = null;
4478                                         bool gen_override = false;
4479                                         if (TypeManager.IsGenericMethod (best_candidate))
4480                                                 gen_args = TypeManager.GetGenericArguments (best_candidate);
4481
4482                                         foreach (MethodBase candidate in candidate_overrides) {
4483                                                 if (TypeManager.IsGenericMethod (candidate)) {
4484                                                         if (gen_args == null)
4485                                                                 continue;
4486
4487                                                         if (gen_args.Length != TypeManager.GetGenericArguments (candidate).Length)
4488                                                                 continue;
4489                                                 } else {
4490                                                         if (gen_args != null)
4491                                                                 continue;
4492                                                 }
4493                                                 
4494                                                 if (IsOverride (candidate, best_candidate)) {
4495                                                         gen_override = true;
4496                                                         best_candidate = candidate;
4497                                                 }
4498                                         }
4499
4500                                         if (gen_override && gen_args != null) {
4501                                                 best_candidate = ((MethodInfo) best_candidate).MakeGenericMethod (gen_args);
4502                                         }
4503                                 }
4504                         }
4505
4506                         //
4507                         // And now check if the arguments are all
4508                         // compatible, perform conversions if
4509                         // necessary etc. and return if everything is
4510                         // all right
4511                         //
4512                         if (!VerifyArgumentsCompat (ec, ref candidate_args, arg_count, best_candidate,
4513                                 method_params, may_fail, loc))
4514                                 return null;
4515
4516                         if (best_candidate == null)
4517                                 return null;
4518
4519                         MethodBase the_method = TypeManager.DropGenericMethodArguments (best_candidate);
4520                         if (TypeManager.IsGenericMethodDefinition (the_method) &&
4521                             !ConstraintChecker.CheckConstraints (ec, the_method, best_candidate, loc))
4522                                 return null;
4523
4524                         //
4525                         // Check ObsoleteAttribute on the best method
4526                         //
4527                         ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (the_method);
4528                         if (oa != null && !ec.IsObsolete)
4529                                 AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
4530
4531                         IMethodData data = TypeManager.GetMethod (the_method);
4532                         if (data != null)
4533                                 data.SetMemberIsUsed ();
4534
4535                         Arguments = candidate_args;
4536                         return this;
4537                 }
4538                 
4539                 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
4540                 {
4541                         type_arguments = ta;
4542                 }
4543
4544                 public bool VerifyArgumentsCompat (ResolveContext ec, ref Arguments arguments,
4545                                                           int arg_count, MethodBase method,
4546                                                           bool chose_params_expanded,
4547                                                           bool may_fail, Location loc)
4548                 {
4549                         AParametersCollection pd = TypeManager.GetParameterData (method);
4550                         int param_count = GetApplicableParametersCount (method, pd);
4551
4552                         int errors = ec.Report.Errors;
4553                         Parameter.Modifier p_mod = 0;
4554                         Type pt = null;
4555                         int a_idx = 0, a_pos = 0;
4556                         Argument a = null;
4557                         ArrayList params_initializers = null;
4558                         bool has_unsafe_arg = method is MethodInfo ? ((MethodInfo) method).ReturnType.IsPointer : false;
4559
4560                         for (; a_idx < arg_count; a_idx++, ++a_pos) {
4561                                 a = arguments [a_idx];
4562                                 if (p_mod != Parameter.Modifier.PARAMS) {
4563                                         p_mod = pd.FixedParameters [a_idx].ModFlags;
4564                                         pt = pd.Types [a_idx];
4565                                         has_unsafe_arg |= pt.IsPointer;
4566
4567                                         if (p_mod == Parameter.Modifier.PARAMS) {
4568                                                 if (chose_params_expanded) {
4569                                                         params_initializers = new ArrayList (arg_count - a_idx);
4570                                                         pt = TypeManager.GetElementType (pt);
4571                                                 }
4572                                         }
4573                                 }
4574
4575                                 //
4576                                 // Types have to be identical when ref or out modifer is used 
4577                                 //
4578                                 if (a.Modifier != 0 || (p_mod & ~Parameter.Modifier.PARAMS) != 0) {
4579                                         if ((p_mod & ~Parameter.Modifier.PARAMS) != a.Modifier)
4580                                                 break;
4581
4582                                         if (!TypeManager.IsEqual (a.Expr.Type, pt))
4583                                                 break;
4584
4585                                         continue;
4586                                 } else {
4587                                         NamedArgument na = a as NamedArgument;
4588                                         if (na != null) {
4589                                                 int name_index = pd.GetParameterIndexByName (na.Name.Value);
4590                                                 if (name_index < 0 || name_index >= param_count) {
4591                                                         if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType)) {
4592                                                                 ec.Report.SymbolRelatedToPreviousError (DeclaringType);
4593                                                                 ec.Report.Error (1746, na.Name.Location,
4594                                                                         "The delegate `{0}' does not contain a parameter named `{1}'",
4595                                                                         TypeManager.CSharpName (DeclaringType), na.Name.Value);
4596                                                         } else {
4597                                                                 ec.Report.SymbolRelatedToPreviousError (best_candidate);
4598                                                                 ec.Report.Error (1739, na.Name.Location,
4599                                                                         "The best overloaded method match for `{0}' does not contain a parameter named `{1}'",
4600                                                                         TypeManager.CSharpSignature (method), na.Name.Value);
4601                                                         }
4602                                                 } else if (arguments[name_index] != a) {
4603                                                         if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType))
4604                                                                 ec.Report.SymbolRelatedToPreviousError (DeclaringType);
4605                                                         else
4606                                                                 ec.Report.SymbolRelatedToPreviousError (best_candidate);
4607
4608                                                         ec.Report.Error (1744, na.Name.Location,
4609                                                                 "Named argument `{0}' cannot be used for a parameter which has positional argument specified",
4610                                                                 na.Name.Value);
4611                                                 }
4612                                         }
4613                                 }
4614
4615                                 if (delegate_type != null && !Delegate.IsTypeCovariant (a.Expr, pt))
4616                                         break;
4617
4618                                 Expression conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc);
4619                                 if (conv == null)
4620                                         break;
4621
4622                                 //
4623                                 // Convert params arguments to an array initializer
4624                                 //
4625                                 if (params_initializers != null) {
4626                                         // we choose to use 'a.Expr' rather than 'conv' so that
4627                                         // we don't hide the kind of expression we have (esp. CompoundAssign.Helper)
4628                                         params_initializers.Add (a.Expr);
4629                                         arguments.RemoveAt (a_idx--);
4630                                         --arg_count;
4631                                         continue;
4632                                 }
4633
4634                                 // Update the argument with the implicit conversion
4635                                 a.Expr = conv;
4636                         }
4637
4638                         if (a_idx != arg_count) {
4639                                 if (!may_fail && ec.Report.Errors == errors) {
4640                                         if (CustomErrorHandler != null)
4641                                                 CustomErrorHandler.NoExactMatch (ec, best_candidate);
4642                                         else
4643                                                 Error_InvalidArguments (ec, loc, a_pos, method, a, pd, pt);
4644                                 }
4645                                 return false;
4646                         }
4647
4648                         //
4649                         // Fill not provided arguments required by params modifier
4650                         //
4651                         if (params_initializers == null && pd.HasParams && arg_count + 1 == param_count) {
4652                                 if (arguments == null)
4653                                         arguments = new Arguments (1);
4654
4655                                 pt = pd.Types [param_count - 1];
4656                                 pt = TypeManager.GetElementType (pt);
4657                                 has_unsafe_arg |= pt.IsPointer;
4658                                 params_initializers = new ArrayList (0);
4659                         }
4660
4661                         //
4662                         // Append an array argument with all params arguments
4663                         //
4664                         if (params_initializers != null) {
4665                                 arguments.Add (new Argument (
4666                                                        new ArrayCreation (new TypeExpression (pt, loc), "[]",
4667                                                                           params_initializers, loc).Resolve (ec)));
4668                                 arg_count++;
4669                         }
4670
4671                         if (arg_count < param_count) {
4672                                 if (!may_fail)
4673                                         Error_ArgumentCountWrong (ec, arg_count);
4674                                 return false;
4675                         }
4676
4677                         if (has_unsafe_arg && !ec.IsUnsafe) {
4678                                 if (!may_fail)
4679                                         UnsafeError (ec, loc);
4680                                 return false;
4681                         }
4682
4683                         return true;
4684                 }
4685         }
4686
4687         public class ConstantExpr : MemberExpr
4688         {
4689                 FieldInfo constant;
4690
4691                 public ConstantExpr (FieldInfo constant, Location loc)
4692                 {
4693                         this.constant = constant;
4694                         this.loc = loc;
4695                 }
4696
4697                 public override string Name {
4698                         get { throw new NotImplementedException (); }
4699                 }
4700
4701                 public override bool IsInstance {
4702                         get { return !IsStatic; }
4703                 }
4704
4705                 public override bool IsStatic {
4706                         get { return constant.IsStatic; }
4707                 }
4708
4709                 public override Type DeclaringType {
4710                         get { return constant.DeclaringType; }
4711                 }
4712
4713                 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc, SimpleName original)
4714                 {
4715                         constant = TypeManager.GetGenericFieldDefinition (constant);
4716
4717                         IConstant ic = TypeManager.GetConstant (constant);
4718                         if (ic == null) {
4719                                 if (constant.IsLiteral) {
4720                                         ic = new ExternalConstant (constant);
4721                                 } else {
4722                                         ic = ExternalConstant.CreateDecimal (constant);
4723                                         // HACK: decimal field was not resolved as constant
4724                                         if (ic == null)
4725                                                 return new FieldExpr (constant, loc).ResolveMemberAccess (ec, left, loc, original);
4726                                 }
4727                                 TypeManager.RegisterConstant (constant, ic);
4728                         }
4729
4730                         return base.ResolveMemberAccess (ec, left, loc, original);
4731                 }
4732
4733                 public override Expression CreateExpressionTree (ResolveContext ec)
4734                 {
4735                         throw new NotSupportedException ("ET");
4736                 }
4737
4738                 public override Expression DoResolve (ResolveContext ec)
4739                 {
4740                         IConstant ic = TypeManager.GetConstant (constant);
4741                         if (ic.ResolveValue ()) {
4742                                 if (!ec.IsObsolete)
4743                                         ic.CheckObsoleteness (loc);
4744                         }
4745
4746                         return ic.CreateConstantReference (loc);
4747                 }
4748
4749                 public override void Emit (EmitContext ec)
4750                 {
4751                         throw new NotSupportedException ();
4752                 }
4753
4754                 public override string GetSignatureForError ()
4755                 {
4756                         return TypeManager.GetFullNameSignature (constant);
4757                 }
4758         }
4759
4760         /// <summary>
4761         ///   Fully resolved expression that evaluates to a Field
4762         /// </summary>
4763         public class FieldExpr : MemberExpr, IDynamicAssign, IMemoryLocation, IVariableReference {
4764                 public FieldInfo FieldInfo;
4765                 readonly Type constructed_generic_type;
4766                 VariableInfo variable_info;
4767                 
4768                 LocalTemporary temp;
4769                 bool prepared;
4770                 
4771                 protected FieldExpr (Location l)
4772                 {
4773                         loc = l;
4774                 }
4775                 
4776                 public FieldExpr (FieldInfo fi, Location l)
4777                 {
4778                         FieldInfo = fi;
4779                         type = TypeManager.TypeToCoreType (fi.FieldType);
4780                         loc = l;
4781                 }
4782
4783                 public FieldExpr (FieldInfo fi, Type genericType, Location l)
4784                         : this (fi, l)
4785                 {
4786                         if (TypeManager.IsGenericTypeDefinition (genericType))
4787                                 return;
4788                         this.constructed_generic_type = genericType;
4789                 }
4790
4791                 public override string Name {
4792                         get {
4793                                 return FieldInfo.Name;
4794                         }
4795                 }
4796
4797                 public override bool IsInstance {
4798                         get {
4799                                 return !FieldInfo.IsStatic;
4800                         }
4801                 }
4802
4803                 public override bool IsStatic {
4804                         get {
4805                                 return FieldInfo.IsStatic;
4806                         }
4807                 }
4808
4809                 public override Type DeclaringType {
4810                         get {
4811                                 return FieldInfo.DeclaringType;
4812                         }
4813                 }
4814
4815                 public override string GetSignatureForError ()
4816                 {
4817                         return TypeManager.GetFullNameSignature (FieldInfo);
4818                 }
4819
4820                 public VariableInfo VariableInfo {
4821                         get {
4822                                 return variable_info;
4823                         }
4824                 }
4825
4826                 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
4827                                                                 SimpleName original)
4828                 {
4829                         FieldInfo fi = TypeManager.GetGenericFieldDefinition (FieldInfo);
4830                         Type t = fi.FieldType;
4831
4832                         if (t.IsPointer && !ec.IsUnsafe) {
4833                                 UnsafeError (ec, loc);
4834                         }
4835
4836                         return base.ResolveMemberAccess (ec, left, loc, original);
4837                 }
4838
4839                 public void SetHasAddressTaken ()
4840                 {
4841                         IVariableReference vr = InstanceExpression as IVariableReference;
4842                         if (vr != null)
4843                                 vr.SetHasAddressTaken ();
4844                 }
4845
4846                 public override Expression CreateExpressionTree (ResolveContext ec)
4847                 {
4848                         Expression instance;
4849                         if (InstanceExpression == null) {
4850                                 instance = new NullLiteral (loc);
4851                         } else {
4852                                 instance = InstanceExpression.CreateExpressionTree (ec);
4853                         }
4854
4855                         Arguments args = Arguments.CreateForExpressionTree (ec, null,
4856                                 instance,
4857                                 CreateTypeOfExpression ());
4858
4859                         return CreateExpressionFactoryCall (ec, "Field", args);
4860                 }
4861
4862                 public Expression CreateTypeOfExpression ()
4863                 {
4864                         return new TypeOfField (GetConstructedFieldInfo (), loc);
4865                 }
4866
4867                 override public Expression DoResolve (ResolveContext ec)
4868                 {
4869                         return DoResolve (ec, false, false);
4870                 }
4871
4872                 Expression DoResolve (ResolveContext ec, bool lvalue_instance, bool out_access)
4873                 {
4874                         if (!FieldInfo.IsStatic){
4875                                 if (InstanceExpression == null){
4876                                         //
4877                                         // This can happen when referencing an instance field using
4878                                         // a fully qualified type expression: TypeName.InstanceField = xxx
4879                                         // 
4880                                         SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
4881                                         return null;
4882                                 }
4883
4884                                 // Resolve the field's instance expression while flow analysis is turned
4885                                 // off: when accessing a field "a.b", we must check whether the field
4886                                 // "a.b" is initialized, not whether the whole struct "a" is initialized.
4887
4888                                 if (lvalue_instance) {
4889                                         using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
4890                                                 Expression right_side =
4891                                                         out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
4892
4893                                                 if (InstanceExpression != EmptyExpression.Null)
4894                                                         InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
4895                                         }
4896                                 } else {
4897                                         ResolveFlags rf = ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis;
4898
4899                                         if (InstanceExpression != EmptyExpression.Null)
4900                                                 InstanceExpression = InstanceExpression.Resolve (ec, rf);
4901                                 }
4902
4903                                 if (InstanceExpression == null)
4904                                         return null;
4905
4906                                 using (ec.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
4907                                         InstanceExpression.CheckMarshalByRefAccess (ec);
4908                                 }
4909                         }
4910
4911                         // TODO: the code above uses some non-standard multi-resolve rules
4912                         if (eclass != ExprClass.Invalid)
4913                                 return this;
4914
4915                         if (!ec.IsObsolete) {
4916                                 FieldBase f = TypeManager.GetField (FieldInfo);
4917                                 if (f != null) {
4918                                         f.CheckObsoleteness (loc);
4919                                 } else {
4920                                         ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
4921                                         if (oa != null)
4922                                                 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc, ec.Report);
4923                                 }
4924                         }
4925
4926                         IFixedBuffer fb = AttributeTester.GetFixedBuffer (FieldInfo);
4927                         IVariableReference var = InstanceExpression as IVariableReference;
4928                         
4929                         if (fb != null) {
4930                                 IFixedExpression fe = InstanceExpression as IFixedExpression;
4931                                 if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) {
4932                                         ec.Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement");
4933                                 }
4934
4935                                 if (InstanceExpression.eclass != ExprClass.Variable) {
4936                                         ec.Report.SymbolRelatedToPreviousError (FieldInfo);
4937                                         ec.Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields",
4938                                                 TypeManager.GetFullNameSignature (FieldInfo));
4939                                 } else if (var != null && var.IsHoisted) {
4940                                         AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, var, loc);
4941                                 }
4942                                 
4943                                 return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec);
4944                         }
4945
4946                         eclass = ExprClass.Variable;
4947
4948                         // If the instance expression is a local variable or parameter.
4949                         if (var == null || var.VariableInfo == null)
4950                                 return this;
4951
4952                         VariableInfo vi = var.VariableInfo;
4953                         if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc))
4954                                 return null;
4955
4956                         variable_info = vi.GetSubStruct (FieldInfo.Name);
4957                         eclass = ExprClass.Variable;
4958                         return this;
4959                 }
4960
4961                 static readonly int [] codes = {
4962                         191,    // instance, write access
4963                         192,    // instance, out access
4964                         198,    // static, write access
4965                         199,    // static, out access
4966                         1648,   // member of value instance, write access
4967                         1649,   // member of value instance, out access
4968                         1650,   // member of value static, write access
4969                         1651    // member of value static, out access
4970                 };
4971
4972                 static readonly string [] msgs = {
4973                         /*0191*/ "A readonly field `{0}' cannot be assigned to (except in a constructor or a variable initializer)",
4974                         /*0192*/ "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
4975                         /*0198*/ "A static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
4976                         /*0199*/ "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
4977                         /*1648*/ "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)",
4978                         /*1649*/ "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)",
4979                         /*1650*/ "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
4980                         /*1651*/ "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)"
4981                 };
4982
4983                 // The return value is always null.  Returning a value simplifies calling code.
4984                 Expression Report_AssignToReadonly (ResolveContext ec, Expression right_side)
4985                 {
4986                         int i = 0;
4987                         if (right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess)
4988                                 i += 1;
4989                         if (IsStatic)
4990                                 i += 2;
4991                         if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess)
4992                                 i += 4;
4993                         ec.Report.Error (codes [i], loc, msgs [i], GetSignatureForError ());
4994
4995                         return null;
4996                 }
4997                 
4998                 override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
4999                 {
5000                         IVariableReference var = InstanceExpression as IVariableReference;
5001                         if (var != null && var.VariableInfo != null)
5002                                 var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
5003
5004                         bool lvalue_instance = !FieldInfo.IsStatic && TypeManager.IsValueType (FieldInfo.DeclaringType);
5005                         bool out_access = right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess;
5006
5007                         Expression e = DoResolve (ec, lvalue_instance, out_access);
5008
5009                         if (e == null)
5010                                 return null;
5011
5012                         FieldBase fb = TypeManager.GetField (FieldInfo);
5013                         if (fb != null) {
5014                                 fb.SetAssigned ();
5015
5016                                 if ((right_side == EmptyExpression.UnaryAddress || right_side == EmptyExpression.OutAccess) &&
5017                                         (fb.ModFlags & Modifiers.VOLATILE) != 0) {
5018                                         ec.Report.Warning (420, 1, loc,
5019                                                 "`{0}': A volatile field references will not be treated as volatile",
5020                                                 fb.GetSignatureForError ());
5021                                 }
5022                         }
5023
5024                         if (FieldInfo.IsInitOnly) {
5025                                 // InitOnly fields can only be assigned in constructors or initializers
5026                                 if (!ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.ConstructorScope))
5027                                         return Report_AssignToReadonly (ec, right_side);
5028
5029                                 if (ec.HasSet (ResolveContext.Options.ConstructorScope)) {
5030                                         Type ctype = ec.CurrentType;
5031
5032                                         // InitOnly fields cannot be assigned-to in a different constructor from their declaring type
5033                                         if (!TypeManager.IsEqual (ctype, FieldInfo.DeclaringType))
5034                                                 return Report_AssignToReadonly (ec, right_side);
5035                                         // static InitOnly fields cannot be assigned-to in an instance constructor
5036                                         if (IsStatic && !ec.IsStatic)
5037                                                 return Report_AssignToReadonly (ec, right_side);
5038                                         // instance constructors can't modify InitOnly fields of other instances of the same type
5039                                         if (!IsStatic && !(InstanceExpression is This))
5040                                                 return Report_AssignToReadonly (ec, right_side);
5041                                 }
5042                         }
5043
5044                         if (right_side == EmptyExpression.OutAccess &&
5045                             !IsStatic && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type)) {
5046                                 ec.Report.SymbolRelatedToPreviousError (DeclaringType);
5047                                 ec.Report.Warning (197, 1, loc,
5048                                                 "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",
5049                                                 GetSignatureForError ());
5050                         }
5051
5052                         eclass = ExprClass.Variable;
5053                         return this;
5054                 }
5055
5056                 bool is_marshal_by_ref ()
5057                 {
5058                         return !IsStatic && TypeManager.IsStruct (Type) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type);
5059                 }
5060
5061                 public override void CheckMarshalByRefAccess (ResolveContext ec)
5062                 {
5063                         if (is_marshal_by_ref () && !(InstanceExpression is This)) {
5064                                 ec.Report.SymbolRelatedToPreviousError (DeclaringType);
5065                                 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",
5066                                                 GetSignatureForError ());
5067                         }
5068                 }
5069
5070                 public override int GetHashCode ()
5071                 {
5072                         return FieldInfo.GetHashCode ();
5073                 }
5074                 
5075                 public bool IsFixed {
5076                         get {
5077                                 //
5078                                 // A variable of the form V.I is fixed when V is a fixed variable of a struct type
5079                                 //
5080                                 IVariableReference variable = InstanceExpression as IVariableReference;
5081                                 if (variable != null)
5082                                         return TypeManager.IsStruct (InstanceExpression.Type) && variable.IsFixed;
5083
5084                                 IFixedExpression fe = InstanceExpression as IFixedExpression;
5085                                 return fe != null && fe.IsFixed;
5086                         }
5087                 }
5088
5089                 public bool IsHoisted {
5090                         get {
5091                                 IVariableReference hv = InstanceExpression as IVariableReference;
5092                                 return hv != null && hv.IsHoisted;
5093                         }
5094                 }
5095
5096                 public override bool Equals (object obj)
5097                 {
5098                         FieldExpr fe = obj as FieldExpr;
5099                         if (fe == null)
5100                                 return false;
5101
5102                         if (FieldInfo != fe.FieldInfo)
5103                                 return false;
5104
5105                         if (InstanceExpression == null || fe.InstanceExpression == null)
5106                                 return true;
5107
5108                         return InstanceExpression.Equals (fe.InstanceExpression);
5109                 }
5110                 
5111                 public void Emit (EmitContext ec, bool leave_copy)
5112                 {
5113                         ILGenerator ig = ec.ig;
5114                         bool is_volatile = false;
5115
5116                         FieldBase f = TypeManager.GetField (FieldInfo);
5117                         if (f != null){
5118                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5119                                         is_volatile = true;
5120
5121                                 f.SetMemberIsUsed ();
5122                         }
5123                         
5124                         if (FieldInfo.IsStatic){
5125                                 if (is_volatile)
5126                                         ig.Emit (OpCodes.Volatile);
5127
5128                                 ig.Emit (OpCodes.Ldsfld, GetConstructedFieldInfo ());
5129                         } else {
5130                                 if (!prepared)
5131                                         EmitInstance (ec, false);
5132
5133                                 // Optimization for build-in types
5134                                 if (TypeManager.IsStruct (type) && TypeManager.IsEqual (type, ec.MemberContext.CurrentType)) {
5135                                         LoadFromPtr (ig, type);
5136                                 } else {
5137                                         IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
5138                                         if (ff != null) {
5139                                                 ig.Emit (OpCodes.Ldflda, GetConstructedFieldInfo ());
5140                                                 ig.Emit (OpCodes.Ldflda, ff.Element);
5141                                         } else {
5142                                                 if (is_volatile)
5143                                                         ig.Emit (OpCodes.Volatile);
5144
5145                                                 ig.Emit (OpCodes.Ldfld, GetConstructedFieldInfo ());
5146                                         }
5147                                 }
5148                         }
5149
5150                         if (leave_copy) {
5151                                 ec.ig.Emit (OpCodes.Dup);
5152                                 if (!FieldInfo.IsStatic) {
5153                                         temp = new LocalTemporary (this.Type);
5154                                         temp.Store (ec);
5155                                 }
5156                         }
5157                 }
5158
5159                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
5160                 {
5161                         FieldAttributes fa = FieldInfo.Attributes;
5162                         bool is_static = (fa & FieldAttributes.Static) != 0;
5163                         ILGenerator ig = ec.ig;
5164
5165                         prepared = prepare_for_load;
5166                         EmitInstance (ec, prepared);
5167
5168                         source.Emit (ec);
5169                         if (leave_copy) {
5170                                 ec.ig.Emit (OpCodes.Dup);
5171                                 if (!FieldInfo.IsStatic) {
5172                                         temp = new LocalTemporary (this.Type);
5173                                         temp.Store (ec);
5174                                 }
5175                         }
5176
5177                         FieldBase f = TypeManager.GetField (FieldInfo);
5178                         if (f != null){
5179                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5180                                         ig.Emit (OpCodes.Volatile);
5181                                         
5182                                 f.SetAssigned ();
5183                         }
5184
5185                         if (is_static)
5186                                 ig.Emit (OpCodes.Stsfld, GetConstructedFieldInfo ());
5187                         else
5188                                 ig.Emit (OpCodes.Stfld, GetConstructedFieldInfo ());
5189                         
5190                         if (temp != null) {
5191                                 temp.Emit (ec);
5192                                 temp.Release (ec);
5193                                 temp = null;
5194                         }
5195                 }
5196
5197                 public override void Emit (EmitContext ec)
5198                 {
5199                         Emit (ec, false);
5200                 }
5201
5202                 public override void EmitSideEffect (EmitContext ec)
5203                 {
5204                         FieldBase f = TypeManager.GetField (FieldInfo);
5205                         bool is_volatile = f != null && (f.ModFlags & Modifiers.VOLATILE) != 0;
5206
5207                         if (is_volatile || is_marshal_by_ref ())
5208                                 base.EmitSideEffect (ec);
5209                 }
5210
5211                 public override void Error_VariableIsUsedBeforeItIsDeclared (Report r, string name)
5212                 {
5213                         r.Error (844, loc,
5214                                 "A local variable `{0}' cannot be used before it is declared. Consider renaming the local variable when it hides the field `{1}'",
5215                                 name, GetSignatureForError ());
5216                 }
5217
5218                 public void AddressOf (EmitContext ec, AddressOp mode)
5219                 {
5220                         ILGenerator ig = ec.ig;
5221
5222                         FieldBase f = TypeManager.GetField (FieldInfo);
5223                         if (f != null){                         
5224                                 if ((mode & AddressOp.Store) != 0)
5225                                         f.SetAssigned ();
5226                                 if ((mode & AddressOp.Load) != 0)
5227                                         f.SetMemberIsUsed ();
5228                         }
5229
5230                         //
5231                         // Handle initonly fields specially: make a copy and then
5232                         // get the address of the copy.
5233                         //
5234                         bool need_copy;
5235                         if (FieldInfo.IsInitOnly){
5236                                 need_copy = true;
5237                                 if (ec.HasSet (EmitContext.Options.ConstructorScope)){
5238                                         if (FieldInfo.IsStatic){
5239                                                 if (ec.IsStatic)
5240                                                         need_copy = false;
5241                                         } else
5242                                                 need_copy = false;
5243                                 }
5244                         } else
5245                                 need_copy = false;
5246                         
5247                         if (need_copy){
5248                                 LocalBuilder local;
5249                                 Emit (ec);
5250                                 local = ig.DeclareLocal (type);
5251                                 ig.Emit (OpCodes.Stloc, local);
5252                                 ig.Emit (OpCodes.Ldloca, local);
5253                                 return;
5254                         }
5255
5256
5257                         if (FieldInfo.IsStatic){
5258                                 ig.Emit (OpCodes.Ldsflda, GetConstructedFieldInfo ());
5259                         } else {
5260                                 if (!prepared)
5261                                         EmitInstance (ec, false);
5262                                 ig.Emit (OpCodes.Ldflda, GetConstructedFieldInfo ());
5263                         }
5264                 }
5265
5266                 FieldInfo GetConstructedFieldInfo ()
5267                 {
5268                         if (constructed_generic_type == null)
5269                                 return FieldInfo;
5270
5271                         return TypeBuilder.GetField (constructed_generic_type, FieldInfo);
5272                 }
5273
5274 #if NET_4_0
5275                 public SLE.Expression MakeAssignExpression (BuilderContext ctx)
5276                 {
5277                         return MakeExpression (ctx);
5278                 }
5279
5280                 public override SLE.Expression MakeExpression (BuilderContext ctx)
5281                 {
5282                         return SLE.Expression.Field (InstanceExpression.MakeExpression (ctx), FieldInfo);
5283                 }
5284 #endif
5285                 
5286                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
5287                 {
5288                         FieldInfo = storey.MutateField (FieldInfo);
5289                         base.MutateHoistedGenericType (storey);
5290                 }               
5291         }
5292
5293         
5294         /// <summary>
5295         ///   Expression that evaluates to a Property.  The Assign class
5296         ///   might set the `Value' expression if we are in an assignment.
5297         ///
5298         ///   This is not an LValue because we need to re-write the expression, we
5299         ///   can not take data from the stack and store it.  
5300         /// </summary>
5301         public class PropertyExpr : MemberExpr, IDynamicAssign
5302         {
5303                 public readonly PropertyInfo PropertyInfo;
5304                 MethodInfo getter, setter;
5305                 bool is_static;
5306
5307                 bool resolved;
5308                 TypeArguments targs;
5309                 
5310                 LocalTemporary temp;
5311                 bool prepared;
5312
5313                 public PropertyExpr (Type container_type, PropertyInfo pi, Location l)
5314                 {
5315                         PropertyInfo = pi;
5316                         eclass = ExprClass.PropertyAccess;
5317                         is_static = false;
5318                         loc = l;
5319
5320                         type = TypeManager.TypeToCoreType (pi.PropertyType);
5321
5322                         ResolveAccessors (container_type);
5323                 }
5324
5325                 public override string Name {
5326                         get {
5327                                 return PropertyInfo.Name;
5328                         }
5329                 }
5330
5331                 public override bool IsInstance {
5332                         get {
5333                                 return !is_static;
5334                         }
5335                 }
5336
5337                 public override bool IsStatic {
5338                         get {
5339                                 return is_static;
5340                         }
5341                 }
5342
5343                 public override Expression CreateExpressionTree (ResolveContext ec)
5344                 {
5345                         Arguments args;
5346                         if (IsSingleDimensionalArrayLength ()) {
5347                                 args = new Arguments (1);
5348                                 args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
5349                                 return CreateExpressionFactoryCall (ec, "ArrayLength", args);
5350                         }
5351
5352                         if (is_base) {
5353                                 Error_BaseAccessInExpressionTree (ec, loc);
5354                                 return null;
5355                         }
5356
5357                         args = new Arguments (2);
5358                         if (InstanceExpression == null)
5359                                 args.Add (new Argument (new NullLiteral (loc)));
5360                         else
5361                                 args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
5362                         args.Add (new Argument (new TypeOfMethod (getter, loc)));
5363                         return CreateExpressionFactoryCall (ec, "Property", args);
5364                 }
5365
5366                 public Expression CreateSetterTypeOfExpression ()
5367                 {
5368                         return new TypeOfMethod (setter, loc);
5369                 }
5370
5371                 public override Type DeclaringType {
5372                         get {
5373                                 return PropertyInfo.DeclaringType;
5374                         }
5375                 }
5376
5377                 public override string GetSignatureForError ()
5378                 {
5379                         return TypeManager.GetFullNameSignature (PropertyInfo);
5380                 }
5381
5382                 void FindAccessors (Type invocation_type)
5383                 {
5384                         const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
5385                                 BindingFlags.Static | BindingFlags.Instance |
5386                                 BindingFlags.DeclaredOnly;
5387
5388                         Type current = PropertyInfo.DeclaringType;
5389                         for (; current != null; current = current.BaseType) {
5390                                 MemberInfo[] group = TypeManager.MemberLookup (
5391                                         invocation_type, invocation_type, current,
5392                                         MemberTypes.Property, flags, PropertyInfo.Name, null);
5393
5394                                 if (group == null)
5395                                         continue;
5396
5397                                 if (group.Length != 1)
5398                                         // Oooops, can this ever happen ?
5399                                         return;
5400
5401                                 PropertyInfo pi = (PropertyInfo) group [0];
5402
5403                                 if (getter == null)
5404                                         getter = pi.GetGetMethod (true);
5405
5406                                 if (setter == null)
5407                                         setter = pi.GetSetMethod (true);
5408
5409                                 MethodInfo accessor = getter != null ? getter : setter;
5410
5411                                 if (!accessor.IsVirtual)
5412                                         return;
5413                         }
5414                 }
5415
5416                 //
5417                 // We also perform the permission checking here, as the PropertyInfo does not
5418                 // hold the information for the accessibility of its setter/getter
5419                 //
5420                 // TODO: Refactor to use some kind of cache together with GetPropertyFromAccessor
5421                 void ResolveAccessors (Type container_type)
5422                 {
5423                         FindAccessors (container_type);
5424
5425                         if (getter != null) {
5426                                 MethodBase the_getter = TypeManager.DropGenericMethodArguments (getter);
5427                                 IMethodData md = TypeManager.GetMethod (the_getter);
5428                                 if (md != null)
5429                                         md.SetMemberIsUsed ();
5430
5431                                 is_static = getter.IsStatic;
5432                         }
5433
5434                         if (setter != null) {
5435                                 MethodBase the_setter = TypeManager.DropGenericMethodArguments (setter);
5436                                 IMethodData md = TypeManager.GetMethod (the_setter);
5437                                 if (md != null)
5438                                         md.SetMemberIsUsed ();
5439
5440                                 is_static = setter.IsStatic;
5441                         }
5442                 }
5443
5444 #if NET_4_0
5445                 public SLE.Expression MakeAssignExpression (BuilderContext ctx)
5446                 {
5447                         return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), setter);
5448                 }
5449
5450                 public override SLE.Expression MakeExpression (BuilderContext ctx)
5451                 {
5452                         return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), getter);
5453                 }
5454 #endif
5455
5456                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
5457                 {
5458                         if (InstanceExpression != null)
5459                                 InstanceExpression.MutateHoistedGenericType (storey);
5460
5461                         type = storey.MutateType (type);
5462                         if (getter != null)
5463                                 getter = storey.MutateGenericMethod (getter);
5464                         if (setter != null)
5465                                 setter = storey.MutateGenericMethod (setter);
5466                 }
5467
5468                 bool InstanceResolve (ResolveContext ec, bool lvalue_instance, bool must_do_cs1540_check)
5469                 {
5470                         if (is_static) {
5471                                 InstanceExpression = null;
5472                                 return true;
5473                         }
5474
5475                         if (InstanceExpression == null) {
5476                                 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
5477                                 return false;
5478                         }
5479
5480                         InstanceExpression = InstanceExpression.DoResolve (ec);
5481                         if (lvalue_instance && InstanceExpression != null)
5482                                 InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess);
5483
5484                         if (InstanceExpression == null)
5485                                 return false;
5486
5487                         InstanceExpression.CheckMarshalByRefAccess (ec);
5488
5489                         if (must_do_cs1540_check && (InstanceExpression != EmptyExpression.Null) &&
5490                             !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.CurrentType) &&
5491                             !TypeManager.IsNestedChildOf (ec.CurrentType, InstanceExpression.Type) &&
5492                             !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.CurrentType)) {
5493                                 ec.Report.SymbolRelatedToPreviousError (PropertyInfo);
5494                                 Error_CannotAccessProtected (ec, loc, PropertyInfo, InstanceExpression.Type, ec.CurrentType);
5495                                 return false;
5496                         }
5497
5498                         return true;
5499                 }
5500
5501                 void Error_PropertyNotFound (ResolveContext ec, MethodInfo mi, bool getter)
5502                 {
5503                         // TODO: correctly we should compare arguments but it will lead to bigger changes
5504                         if (mi is MethodBuilder) {
5505                                 Error_TypeDoesNotContainDefinition (ec, loc, PropertyInfo.DeclaringType, Name);
5506                                 return;
5507                         }
5508                         
5509                         StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
5510                         sig.Append ('.');
5511                         AParametersCollection iparams = TypeManager.GetParameterData (mi);
5512                         sig.Append (getter ? "get_" : "set_");
5513                         sig.Append (Name);
5514                         sig.Append (iparams.GetSignatureForError ());
5515
5516                         ec.Report.SymbolRelatedToPreviousError (mi);
5517                         ec.Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
5518                                 Name, sig.ToString ());
5519                 }
5520
5521                 public bool IsAccessibleFrom (Type invocation_type, bool lvalue)
5522                 {
5523                         bool dummy;
5524                         MethodInfo accessor = lvalue ? setter : getter;
5525                         if (accessor == null && lvalue)
5526                                 accessor = getter;
5527                         return accessor != null && IsAccessorAccessible (invocation_type, accessor, out dummy);
5528                 }
5529
5530                 bool IsSingleDimensionalArrayLength ()
5531                 {
5532                         if (DeclaringType != TypeManager.array_type || getter == null || Name != "Length")
5533                                 return false;
5534
5535                         string t_name = InstanceExpression.Type.Name;
5536                         int t_name_len = t_name.Length;
5537                         return t_name_len > 2 && t_name [t_name_len - 2] == '[';
5538                 }
5539
5540                 public override Expression DoResolve (ResolveContext ec)
5541                 {
5542                         if (resolved)
5543                                 return this;
5544
5545                         bool must_do_cs1540_check = false;
5546                         ec.Report.DisableReporting ();
5547                         bool res = ResolveGetter (ec, ref must_do_cs1540_check);
5548                         ec.Report.EnableReporting ();
5549
5550                         if (!res) {
5551                                 if (InstanceExpression != null) {
5552                                         Type expr_type = InstanceExpression.Type;
5553                                         ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (expr_type, Name, loc);
5554                                         if (ex_method_lookup != null) {
5555                                                 ex_method_lookup.ExtensionExpression = InstanceExpression;
5556                                                 ex_method_lookup.SetTypeArguments (ec, targs);
5557                                                 return ex_method_lookup.DoResolve (ec);
5558                                         }
5559                                 }
5560
5561                                 ResolveGetter (ec, ref must_do_cs1540_check);
5562                                 return null;
5563                         }
5564
5565                         if (!InstanceResolve (ec, false, must_do_cs1540_check))
5566                                 return null;
5567
5568                         //
5569                         // Only base will allow this invocation to happen.
5570                         //
5571                         if (IsBase && getter.IsAbstract) {
5572                                 Error_CannotCallAbstractBase (ec, TypeManager.GetFullNameSignature (PropertyInfo));
5573                         }
5574
5575                         if (PropertyInfo.PropertyType.IsPointer && !ec.IsUnsafe){
5576                                 UnsafeError (ec, loc);
5577                         }
5578
5579                         if (!ec.IsObsolete) {
5580                                 PropertyBase pb = TypeManager.GetProperty (PropertyInfo);
5581                                 if (pb != null) {
5582                                         pb.CheckObsoleteness (loc);
5583                                 } else {
5584                                         ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (PropertyInfo);
5585                                         if (oa != null)
5586                                                 AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
5587                                 }
5588                         }
5589
5590                         resolved = true;
5591
5592                         return this;
5593                 }
5594
5595                 override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
5596                 {
5597                         if (right_side == EmptyExpression.OutAccess) {
5598                                 if (ec.CurrentBlock.Toplevel.GetParameterReference (PropertyInfo.Name, loc) is MemberAccess) {
5599                                         ec.Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter",
5600                                             PropertyInfo.Name);
5601                                 } else {
5602                                         ec.Report.Error (206, loc, "A property or indexer `{0}' may not be passed as `ref' or `out' parameter",
5603                                               GetSignatureForError ());
5604                                 }
5605                                 return null;
5606                         }
5607
5608                         if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) {
5609                                 Error_CannotModifyIntermediateExpressionValue (ec);
5610                         }
5611
5612                         if (setter == null){
5613                                 //
5614                                 // The following condition happens if the PropertyExpr was
5615                                 // created, but is invalid (ie, the property is inaccessible),
5616                                 // and we did not want to embed the knowledge about this in
5617                                 // the caller routine.  This only avoids double error reporting.
5618                                 //
5619                                 if (getter == null)
5620                                         return null;
5621
5622                                 if (ec.CurrentBlock.Toplevel.GetParameterReference (PropertyInfo.Name, loc) is MemberAccess) {
5623                                         ec.Report.Error (1947, loc, "A range variable `{0}' cannot be assigned to. Consider using `let' clause to store the value",
5624                                                 PropertyInfo.Name);
5625                                 } else {
5626                                         ec.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read only)",
5627                                                 GetSignatureForError ());
5628                                 }
5629                                 return null;
5630                         }
5631
5632                         if (targs != null) {
5633                                 base.SetTypeArguments (ec, targs);
5634                                 return null;
5635                         }
5636
5637                         if (TypeManager.GetParameterData (setter).Count != 1){
5638                                 Error_PropertyNotFound (ec, setter, false);
5639                                 return null;
5640                         }
5641
5642                         bool must_do_cs1540_check;
5643                         if (!IsAccessorAccessible (ec.CurrentType, setter, out must_do_cs1540_check)) {
5644                                 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
5645                                 if (pm != null && pm.HasCustomAccessModifier) {
5646                                         ec.Report.SymbolRelatedToPreviousError (pm);
5647                                         ec.Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
5648                                                 TypeManager.CSharpSignature (setter));
5649                                 }
5650                                 else {
5651                                         ec.Report.SymbolRelatedToPreviousError (setter);
5652                                         ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter), ec.Report);
5653                                 }
5654                                 return null;
5655                         }
5656                         
5657                         if (!InstanceResolve (ec, TypeManager.IsStruct (PropertyInfo.DeclaringType), must_do_cs1540_check))
5658                                 return null;
5659                         
5660                         //
5661                         // Only base will allow this invocation to happen.
5662                         //
5663                         if (IsBase && setter.IsAbstract){
5664                                 Error_CannotCallAbstractBase (ec, TypeManager.GetFullNameSignature (PropertyInfo));
5665                         }
5666
5667                         if (PropertyInfo.PropertyType.IsPointer && !ec.IsUnsafe) {
5668                                 UnsafeError (ec, loc);
5669                         }
5670
5671                         if (!ec.IsObsolete) {
5672                                 PropertyBase pb = TypeManager.GetProperty (PropertyInfo);
5673                                 if (pb != null) {
5674                                         pb.CheckObsoleteness (loc);
5675                                 } else {
5676                                         ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (PropertyInfo);
5677                                         if (oa != null)
5678                                                 AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
5679                                 }
5680                         }
5681
5682                         return this;
5683                 }
5684                 
5685                 public override void Emit (EmitContext ec)
5686                 {
5687                         Emit (ec, false);
5688                 }
5689                 
5690                 public void Emit (EmitContext ec, bool leave_copy)
5691                 {
5692                         //
5693                         // Special case: length of single dimension array property is turned into ldlen
5694                         //
5695                         if (IsSingleDimensionalArrayLength ()) {
5696                                 if (!prepared)
5697                                         EmitInstance (ec, false);
5698                                 ec.ig.Emit (OpCodes.Ldlen);
5699                                 ec.ig.Emit (OpCodes.Conv_I4);
5700                                 return;
5701                         }
5702
5703                         Invocation.EmitCall (ec, IsBase, InstanceExpression, getter, null, loc, prepared, false);
5704                         
5705                         if (leave_copy) {
5706                                 ec.ig.Emit (OpCodes.Dup);
5707                                 if (!is_static) {
5708                                         temp = new LocalTemporary (this.Type);
5709                                         temp.Store (ec);
5710                                 }
5711                         }
5712                 }
5713
5714                 //
5715                 // Implements the IAssignMethod interface for assignments
5716                 //
5717                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
5718                 {
5719                         Expression my_source = source;
5720
5721                         if (prepare_for_load) {
5722                                 prepared = true;
5723                                 source.Emit (ec);
5724                                 
5725                                 if (leave_copy) {
5726                                         ec.ig.Emit (OpCodes.Dup);
5727                                         if (!is_static) {
5728                                                 temp = new LocalTemporary (this.Type);
5729                                                 temp.Store (ec);
5730                                         }
5731                                 }
5732                         } else if (leave_copy) {
5733                                 source.Emit (ec);
5734                                 temp = new LocalTemporary (this.Type);
5735                                 temp.Store (ec);
5736                                 my_source = temp;
5737                         }
5738
5739                         Arguments args = new Arguments (1);
5740                         args.Add (new Argument (my_source));
5741                         
5742                         Invocation.EmitCall (ec, IsBase, InstanceExpression, setter, args, loc, false, prepared);
5743                         
5744                         if (temp != null) {
5745                                 temp.Emit (ec);
5746                                 temp.Release (ec);
5747                         }
5748                 }
5749
5750                 bool ResolveGetter (ResolveContext ec, ref bool must_do_cs1540_check)
5751                 {
5752                         if (targs != null) {
5753                                 base.SetTypeArguments (ec, targs);
5754                                 return false;
5755                         }
5756
5757                         if (getter != null) {
5758                                 if (TypeManager.GetParameterData (getter).Count != 0) {
5759                                         Error_PropertyNotFound (ec, getter, true);
5760                                         return false;
5761                                 }
5762                         }
5763
5764                         if (getter == null) {
5765                                 //
5766                                 // The following condition happens if the PropertyExpr was
5767                                 // created, but is invalid (ie, the property is inaccessible),
5768                                 // and we did not want to embed the knowledge about this in
5769                                 // the caller routine.  This only avoids double error reporting.
5770                                 //
5771                                 if (setter == null)
5772                                         return false;
5773
5774                                 if (InstanceExpression != EmptyExpression.Null) {
5775                                         ec.Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
5776                                                 TypeManager.GetFullNameSignature (PropertyInfo));
5777                                         return false;
5778                                 }
5779                         }
5780
5781                         if (getter != null &&
5782                                 !IsAccessorAccessible (ec.CurrentType, getter, out must_do_cs1540_check)) {
5783                                 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
5784                                 if (pm != null && pm.HasCustomAccessModifier) {
5785                                         ec.Report.SymbolRelatedToPreviousError (pm);
5786                                         ec.Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
5787                                                 TypeManager.CSharpSignature (getter));
5788                                 } else {
5789                                         ec.Report.SymbolRelatedToPreviousError (getter);
5790                                         ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter), ec.Report);
5791                                 }
5792
5793                                 return false;
5794                         }
5795
5796                         return true;
5797                 }
5798
5799                 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
5800                 {
5801                         targs = ta;
5802                 }
5803         }
5804
5805         /// <summary>
5806         ///   Fully resolved expression that evaluates to an Event
5807         /// </summary>
5808         public class EventExpr : MemberExpr {
5809                 public readonly EventInfo EventInfo;
5810
5811                 bool is_static;
5812                 MethodInfo add_accessor, remove_accessor;
5813
5814                 public EventExpr (EventInfo ei, Location loc)
5815                 {
5816                         EventInfo = ei;
5817                         this.loc = loc;
5818                         eclass = ExprClass.EventAccess;
5819
5820                         add_accessor = TypeManager.GetAddMethod (ei);
5821                         remove_accessor = TypeManager.GetRemoveMethod (ei);
5822                         if (add_accessor.IsStatic || remove_accessor.IsStatic)
5823                                 is_static = true;
5824
5825                         if (EventInfo is MyEventBuilder){
5826                                 MyEventBuilder eb = (MyEventBuilder) EventInfo;
5827                                 type = eb.EventType;
5828                                 eb.SetUsed ();
5829                         } else
5830                                 type = EventInfo.EventHandlerType;
5831                 }
5832
5833                 public override string Name {
5834                         get {
5835                                 return EventInfo.Name;
5836                         }
5837                 }
5838
5839                 public override bool IsInstance {
5840                         get {
5841                                 return !is_static;
5842                         }
5843                 }
5844
5845                 public override bool IsStatic {
5846                         get {
5847                                 return is_static;
5848                         }
5849                 }
5850
5851                 public override Type DeclaringType {
5852                         get {
5853                                 return EventInfo.DeclaringType;
5854                         }
5855                 }
5856                 
5857                 public void Error_AssignmentEventOnly (ResolveContext ec)
5858                 {
5859                         ec.Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator",
5860                                 GetSignatureForError ());
5861                 }
5862
5863                 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
5864                                                                 SimpleName original)
5865                 {
5866                         //
5867                         // If the event is local to this class, we transform ourselves into a FieldExpr
5868                         //
5869
5870                         if (EventInfo.DeclaringType == ec.CurrentType ||
5871                             TypeManager.IsNestedChildOf(ec.CurrentType, EventInfo.DeclaringType)) {
5872                                 EventField mi = TypeManager.GetEventField (EventInfo);
5873
5874                                 if (mi != null) {
5875                                         if (!ec.IsObsolete)
5876                                                 mi.CheckObsoleteness (loc);
5877
5878                                         if ((mi.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0 && !ec.HasSet (ResolveContext.Options.CompoundAssignmentScope))
5879                                                 Error_AssignmentEventOnly (ec);
5880                                         
5881                                         FieldExpr ml = new FieldExpr (mi.BackingField.FieldBuilder, loc);
5882
5883                                         InstanceExpression = null;
5884                                 
5885                                         return ml.ResolveMemberAccess (ec, left, loc, original);
5886                                 }
5887                         }
5888
5889                         if (left is This && !ec.HasSet (ResolveContext.Options.CompoundAssignmentScope))                        
5890                                 Error_AssignmentEventOnly (ec);
5891
5892                         return base.ResolveMemberAccess (ec, left, loc, original);
5893                 }
5894
5895                 bool InstanceResolve (ResolveContext ec, bool must_do_cs1540_check)
5896                 {
5897                         if (is_static) {
5898                                 InstanceExpression = null;
5899                                 return true;
5900                         }
5901
5902                         if (InstanceExpression == null) {
5903                                 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
5904                                 return false;
5905                         }
5906
5907                         InstanceExpression = InstanceExpression.DoResolve (ec);
5908                         if (InstanceExpression == null)
5909                                 return false;
5910
5911                         if (IsBase && add_accessor.IsAbstract) {
5912                                 Error_CannotCallAbstractBase (ec, TypeManager.CSharpSignature(add_accessor));
5913                                 return false;
5914                         }
5915
5916                         //
5917                         // This is using the same mechanism as the CS1540 check in PropertyExpr.
5918                         // However, in the Event case, we reported a CS0122 instead.
5919                         //
5920                         // TODO: Exact copy from PropertyExpr
5921                         //
5922                         if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
5923                             !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.CurrentType) &&
5924                             !TypeManager.IsNestedChildOf (ec.CurrentType, InstanceExpression.Type) &&
5925                             !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.CurrentType)) {
5926                                 ec.Report.SymbolRelatedToPreviousError (EventInfo);
5927                                 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo), ec.Report);
5928                                 return false;
5929                         }
5930
5931                         return true;
5932                 }
5933
5934                 public bool IsAccessibleFrom (Type invocation_type)
5935                 {
5936                         bool dummy;
5937                         return IsAccessorAccessible (invocation_type, add_accessor, out dummy) &&
5938                                 IsAccessorAccessible (invocation_type, remove_accessor, out dummy);
5939                 }
5940
5941                 public override Expression CreateExpressionTree (ResolveContext ec)
5942                 {
5943                         throw new NotSupportedException ("ET");
5944                 }
5945
5946                 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
5947                 {
5948                         // contexts where an LValue is valid have already devolved to FieldExprs
5949                         Error_CannotAssign (ec);
5950                         return null;
5951                 }
5952
5953                 public override Expression DoResolve (ResolveContext ec)
5954                 {
5955                         bool must_do_cs1540_check;
5956                         if (!(IsAccessorAccessible (ec.CurrentType, add_accessor, out must_do_cs1540_check) &&
5957                               IsAccessorAccessible (ec.CurrentType, remove_accessor, out must_do_cs1540_check))) {
5958                                 ec.Report.SymbolRelatedToPreviousError (EventInfo);
5959                                 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo), ec.Report);
5960                                 return null;
5961                         }
5962
5963                         if (!InstanceResolve (ec, must_do_cs1540_check))
5964                                 return null;
5965
5966                         if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) {
5967                                 Error_CannotAssign (ec);
5968                                 return null;
5969                         }
5970
5971                         if (!ec.IsObsolete) {
5972                                 EventField ev = TypeManager.GetEventField (EventInfo);
5973                                 if (ev != null) {
5974                                         ev.CheckObsoleteness (loc);
5975                                 } else {
5976                                         ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (EventInfo);
5977                                         if (oa != null)
5978                                                 AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
5979                                 }
5980                         }
5981                         
5982                         return this;
5983                 }               
5984
5985                 public override void Emit (EmitContext ec)
5986                 {
5987                         throw new NotSupportedException ();
5988                         //Error_CannotAssign ();
5989                 }
5990
5991                 public void Error_CannotAssign (ResolveContext ec)
5992                 {
5993                         ec.Report.Error (70, loc,
5994                                 "The event `{0}' can only appear on the left hand side of += or -= when used outside of the type `{1}'",
5995                                 GetSignatureForError (), TypeManager.CSharpName (EventInfo.DeclaringType));
5996                 }
5997
5998                 public override string GetSignatureForError ()
5999                 {
6000                         return TypeManager.CSharpSignature (EventInfo);
6001                 }
6002
6003                 public void EmitAddOrRemove (EmitContext ec, bool is_add, Expression source)
6004                 {
6005                         Arguments args = new Arguments (1);
6006                         args.Add (new Argument (source));
6007                         Invocation.EmitCall (ec, IsBase, InstanceExpression, is_add ? add_accessor : remove_accessor, args, loc);
6008                 }
6009         }
6010
6011         public class TemporaryVariable : VariableReference
6012         {
6013                 LocalInfo li;
6014
6015                 public TemporaryVariable (Type type, Location loc)
6016                 {
6017                         this.type = type;
6018                         this.loc = loc;
6019                         eclass = ExprClass.Variable;
6020                 }
6021
6022                 public override Expression CreateExpressionTree (ResolveContext ec)
6023                 {
6024                         throw new NotSupportedException ("ET");
6025                 }
6026
6027                 public override Expression DoResolve (ResolveContext ec)
6028                 {
6029                         if (li != null)
6030                                 return this;
6031
6032                         TypeExpr te = new TypeExpression (type, loc);
6033                         li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
6034                         if (!li.Resolve (ec))
6035                                 return null;
6036
6037                         //
6038                         // Don't capture temporary variables except when using
6039                         // iterator redirection
6040                         //
6041                         if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.IsIterator && ec.IsVariableCapturingRequired) {
6042                                 AnonymousMethodStorey storey = li.Block.Explicit.CreateAnonymousMethodStorey (ec);
6043                                 storey.CaptureLocalVariable (ec, li);
6044                         }
6045
6046                         return this;
6047                 }
6048
6049                 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
6050                 {
6051                         return DoResolve (ec);
6052                 }
6053                 
6054                 public override void Emit (EmitContext ec)
6055                 {
6056                         Emit (ec, false);
6057                 }
6058
6059                 public void EmitAssign (EmitContext ec, Expression source)
6060                 {
6061                         EmitAssign (ec, source, false, false);
6062                 }
6063
6064                 public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
6065                 {
6066                         return li.HoistedVariableReference;
6067                 }
6068
6069                 public override bool IsFixed {
6070                         get { return true; }
6071                 }
6072
6073                 public override bool IsRef {
6074                         get { return false; }
6075                 }
6076
6077                 public override string Name {
6078                         get { throw new NotImplementedException (); }
6079                 }
6080
6081                 public override void SetHasAddressTaken ()
6082                 {
6083                         throw new NotImplementedException ();
6084                 }
6085
6086                 protected override ILocalVariable Variable {
6087                         get { return li; }
6088                 }
6089
6090                 public override VariableInfo VariableInfo {
6091                         get { throw new NotImplementedException (); }
6092                 }
6093         }
6094
6095         /// 
6096         /// Handles `var' contextual keyword; var becomes a keyword only
6097         /// if no type called var exists in a variable scope
6098         /// 
6099         class VarExpr : SimpleName
6100         {
6101                 // Used for error reporting only
6102                 ArrayList initializer;
6103
6104                 public VarExpr (Location loc)
6105                         : base ("var", loc)
6106                 {
6107                 }
6108
6109                 public ArrayList VariableInitializer {
6110                         set {
6111                                 this.initializer = value;
6112                         }
6113                 }
6114
6115                 public bool InferType (ResolveContext ec, Expression right_side)
6116                 {
6117                         if (type != null)
6118                                 throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
6119                         
6120                         type = right_side.Type;
6121                         if (type == TypeManager.null_type || type == TypeManager.void_type || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) {
6122                                 ec.Report.Error (815, loc, "An implicitly typed local variable declaration cannot be initialized with `{0}'",
6123                                               right_side.GetSignatureForError ());
6124                                 return false;
6125                         }
6126
6127                         eclass = ExprClass.Variable;
6128                         return true;
6129                 }
6130
6131                 protected override void Error_TypeOrNamespaceNotFound (IMemberContext ec)
6132                 {
6133                         if (RootContext.Version < LanguageVersion.V_3)
6134                                 base.Error_TypeOrNamespaceNotFound (ec);
6135                         else
6136                                 ec.Compiler.Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration");
6137                 }
6138
6139                 public override TypeExpr ResolveAsContextualType (IMemberContext rc, bool silent)
6140                 {
6141                         TypeExpr te = base.ResolveAsContextualType (rc, true);
6142                         if (te != null)
6143                                 return te;
6144
6145                         if (RootContext.Version < LanguageVersion.V_3)
6146                                 rc.Compiler.Report.FeatureIsNotAvailable (loc, "implicitly typed local variable");
6147
6148                         if (initializer == null)
6149                                 return null;
6150
6151                         if (initializer.Count > 1) {
6152                                 Location loc_init = ((CSharpParser.VariableDeclaration) initializer[1]).Location;
6153                                 rc.Compiler.Report.Error (819, loc_init, "An implicitly typed local variable declaration cannot include multiple declarators");
6154                                 initializer = null;
6155                                 return null;
6156                         }
6157
6158                         Expression variable_initializer = ((CSharpParser.VariableDeclaration) initializer[0]).expression_or_array_initializer;
6159                         if (variable_initializer == null) {
6160                                 rc.Compiler.Report.Error (818, loc, "An implicitly typed local variable declarator must include an initializer");
6161                                 return null;
6162                         }
6163
6164                         return null;
6165                 }
6166         }
6167 }