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