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