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