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