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