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