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