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