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