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