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