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