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