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