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