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