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