9486475305452e2ab5c326d264e3f0954e58a661
[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                         orig_expr.FlowAnalysis (fc);
2433                 }
2434
2435                 public override void FlowAnalysisConditional (FlowAnalysisContext fc)
2436                 {
2437                         orig_expr.FlowAnalysisConditional (fc);
2438                 }
2439
2440                 public override SLE.Expression MakeExpression (BuilderContext ctx)
2441                 {
2442                         return orig_expr.MakeExpression (ctx);
2443                 }
2444
2445                 public override Reachability MarkReachable (Reachability rc)
2446                 {
2447                         return expr.MarkReachable (rc);
2448                 }
2449         }
2450
2451         //
2452         // Standard composite pattern
2453         //
2454         public abstract class CompositeExpression : Expression
2455         {
2456                 protected Expression expr;
2457
2458                 protected CompositeExpression (Expression expr)
2459                 {
2460                         this.expr = expr;
2461                         this.loc = expr.Location;
2462                 }
2463
2464                 public override bool ContainsEmitWithAwait ()
2465                 {
2466                         return expr.ContainsEmitWithAwait ();
2467                 }
2468
2469                 public override Expression CreateExpressionTree (ResolveContext rc)
2470                 {
2471                         return expr.CreateExpressionTree (rc);
2472                 }
2473
2474                 public Expression Child {
2475                         get { return expr; }
2476                 }
2477
2478                 protected override Expression DoResolve (ResolveContext rc)
2479                 {
2480                         expr = expr.Resolve (rc);
2481                         if (expr == null)
2482                                 return null;
2483
2484                         type = expr.Type;
2485                         eclass = expr.eclass;
2486                         return this;
2487                 }
2488
2489                 public override void Emit (EmitContext ec)
2490                 {
2491                         expr.Emit (ec);
2492                 }
2493
2494                 public override bool IsNull {
2495                         get { return expr.IsNull; }
2496                 }
2497         }
2498
2499         //
2500         // Base of expressions used only to narrow resolve flow
2501         //
2502         public abstract class ShimExpression : Expression
2503         {
2504                 protected Expression expr;
2505
2506                 protected ShimExpression (Expression expr)
2507                 {
2508                         this.expr = expr;
2509                 }
2510
2511                 public Expression Expr {
2512                         get {
2513                                 return expr;
2514                         }
2515                 }
2516
2517                 protected override void CloneTo (CloneContext clonectx, Expression t)
2518                 {
2519                         if (expr == null)
2520                                 return;
2521
2522                         ShimExpression target = (ShimExpression) t;
2523                         target.expr = expr.Clone (clonectx);
2524                 }
2525
2526                 public override bool ContainsEmitWithAwait ()
2527                 {
2528                         return expr.ContainsEmitWithAwait ();
2529                 }
2530
2531                 public override Expression CreateExpressionTree (ResolveContext ec)
2532                 {
2533                         throw new NotSupportedException ("ET");
2534                 }
2535
2536                 public override void Emit (EmitContext ec)
2537                 {
2538                         throw new InternalErrorException ("Missing Resolve call");
2539                 }
2540         }
2541
2542         public class UnreachableExpression : Expression
2543         {
2544                 public UnreachableExpression (Expression expr)
2545                 {
2546                         this.loc = expr.Location;
2547                 }
2548
2549                 public override Expression CreateExpressionTree (ResolveContext ec)
2550                 {
2551                         // TODO: is it ok
2552                         throw new NotImplementedException ();
2553                 }
2554
2555                 protected override Expression DoResolve (ResolveContext rc)
2556                 {
2557                         throw new NotSupportedException ();
2558                 }
2559
2560                 public override void FlowAnalysis (FlowAnalysisContext fc)
2561                 {
2562                         fc.Report.Warning (429, 4, loc, "Unreachable expression code detected");
2563                 }
2564
2565                 public override void Emit (EmitContext ec)
2566                 {
2567                 }
2568
2569                 public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
2570                 {
2571                 }
2572         }
2573
2574         //
2575         // Unresolved type name expressions
2576         //
2577         public abstract class ATypeNameExpression : FullNamedExpression
2578         {
2579                 string name;
2580                 protected TypeArguments targs;
2581
2582                 protected ATypeNameExpression (string name, Location l)
2583                 {
2584                         this.name = name;
2585                         loc = l;
2586                 }
2587
2588                 protected ATypeNameExpression (string name, TypeArguments targs, Location l)
2589                 {
2590                         this.name = name;
2591                         this.targs = targs;
2592                         loc = l;
2593                 }
2594
2595                 protected ATypeNameExpression (string name, int arity, Location l)
2596                         : this (name, new UnboundTypeArguments (arity, l), l)
2597                 {
2598                 }
2599
2600                 #region Properties
2601
2602                 public int Arity {
2603                         get {
2604                                 return targs == null ? 0 : targs.Count;
2605                         }
2606                 }
2607
2608                 public bool HasTypeArguments {
2609                         get {
2610                                 return targs != null && !targs.IsEmpty;
2611                         }
2612                 }
2613
2614                 public string Name {
2615                         get {
2616                                 return name;
2617                         }
2618                         set {
2619                                 name = value;
2620                         }
2621                 }
2622
2623                 public TypeArguments TypeArguments {
2624                         get {
2625                                 return targs;
2626                         }
2627                 }
2628
2629                 #endregion
2630
2631                 public override bool Equals (object obj)
2632                 {
2633                         ATypeNameExpression atne = obj as ATypeNameExpression;
2634                         return atne != null && atne.Name == Name &&
2635                                 (targs == null || targs.Equals (atne.targs));
2636                 }
2637
2638                 public override int GetHashCode ()
2639                 {
2640                         return Name.GetHashCode ();
2641                 }
2642
2643                 // TODO: Move it to MemberCore
2644                 public static string GetMemberType (MemberCore mc)
2645                 {
2646                         if (mc is Property)
2647                                 return "property";
2648                         if (mc is Indexer)
2649                                 return "indexer";
2650                         if (mc is FieldBase)
2651                                 return "field";
2652                         if (mc is MethodCore)
2653                                 return "method";
2654                         if (mc is EnumMember)
2655                                 return "enum";
2656                         if (mc is Event)
2657                                 return "event";
2658
2659                         return "type";
2660                 }
2661
2662                 public override string GetSignatureForError ()
2663                 {
2664                         if (targs != null) {
2665                                 return Name + "<" + targs.GetSignatureForError () + ">";
2666                         }
2667
2668                         return Name;
2669                 }
2670
2671                 public abstract Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restriction);
2672         }
2673         
2674         /// <summary>
2675         ///   SimpleName expressions are formed of a single word and only happen at the beginning 
2676         ///   of a dotted-name.
2677         /// </summary>
2678         public class SimpleName : ATypeNameExpression
2679         {
2680                 public SimpleName (string name, Location l)
2681                         : base (name, l)
2682                 {
2683                 }
2684
2685                 public SimpleName (string name, TypeArguments args, Location l)
2686                         : base (name, args, l)
2687                 {
2688                 }
2689
2690                 public SimpleName (string name, int arity, Location l)
2691                         : base (name, arity, l)
2692                 {
2693                 }
2694
2695                 public SimpleName GetMethodGroup ()
2696                 {
2697                         return new SimpleName (Name, targs, loc);
2698                 }
2699
2700                 protected override Expression DoResolve (ResolveContext rc)
2701                 {
2702                         return SimpleNameResolve (rc, null);
2703                 }
2704
2705                 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
2706                 {
2707                         return SimpleNameResolve (ec, right_side);
2708                 }
2709
2710                 public void Error_NameDoesNotExist (ResolveContext rc)
2711                 {
2712                         rc.Report.Error (103, loc, "The name `{0}' does not exist in the current context", Name);
2713                 }
2714
2715                 protected virtual void Error_TypeOrNamespaceNotFound (IMemberContext ctx)
2716                 {
2717                         if (ctx.CurrentType != null) {
2718                                 var member = MemberLookup (ctx, false, ctx.CurrentType, Name, 0, MemberLookupRestrictions.ExactArity, loc) as MemberExpr;
2719                                 if (member != null) {
2720                                         Error_UnexpectedKind (ctx, member, "type", member.KindName, loc);
2721                                         return;
2722                                 }
2723                         }
2724
2725                         var report = ctx.Module.Compiler.Report;
2726
2727                         var retval = ctx.LookupNamespaceOrType (Name, Arity, LookupMode.IgnoreAccessibility, loc);
2728                         if (retval != null) {
2729                                 report.SymbolRelatedToPreviousError (retval.Type);
2730                                 ErrorIsInaccesible (ctx, retval.GetSignatureForError (), loc);
2731                                 return;
2732                         }
2733
2734                         retval = ctx.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), LookupMode.Probing, loc);
2735                         if (retval != null) {
2736                                 Error_TypeArgumentsCannotBeUsed (ctx, retval.Type, loc);
2737                                 return;
2738                         }
2739
2740                         var ns_candidates = ctx.Module.GlobalRootNamespace.FindTypeNamespaces (ctx, Name, Arity);
2741                         if (ns_candidates != null) {
2742                                 if (ctx is UsingAliasNamespace.AliasContext) {
2743                                         report.Error (246, loc,
2744                                                 "The type or namespace name `{1}' could not be found. Consider using fully qualified name `{0}.{1}'",
2745                                                 ns_candidates[0], Name);
2746                                 } else {
2747                                         string usings = string.Join ("' or `", ns_candidates.ToArray ());
2748                                         report.Error (246, loc,
2749                                                 "The type or namespace name `{0}' could not be found. Are you missing `{1}' using directive?",
2750                                                 Name, usings);
2751                                 }
2752                         } else {
2753                                 report.Error (246, loc,
2754                                         "The type or namespace name `{0}' could not be found. Are you missing an assembly reference?",
2755                                         Name);
2756                         }
2757                 }
2758
2759                 public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc, bool allowUnboundTypeArguments)
2760                 {
2761                         FullNamedExpression fne = mc.LookupNamespaceOrType (Name, Arity, LookupMode.Normal, loc);
2762
2763                         if (fne != null) {
2764                                 if (fne.Type != null && Arity > 0) {
2765                                         if (HasTypeArguments) {
2766                                                 GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc);
2767                                                 if (ct.ResolveAsType (mc) == null)
2768                                                         return null;
2769
2770                                                 return ct;
2771                                         }
2772
2773                                         targs.Resolve (mc, allowUnboundTypeArguments);
2774
2775                                         return new GenericOpenTypeExpr (fne.Type, loc);
2776                                 }
2777
2778                                 //
2779                                 // dynamic namespace is ignored when dynamic is allowed (does not apply to types)
2780                                 //
2781                                 if (!(fne is NamespaceExpression))
2782                                         return fne;
2783                         }
2784
2785                         if (Arity == 0 && Name == "dynamic" && !(mc is NamespaceContainer) && mc.Module.Compiler.Settings.Version > LanguageVersion.V_3) {
2786                                 if (!mc.Module.PredefinedAttributes.Dynamic.IsDefined) {
2787                                         mc.Module.Compiler.Report.Error (1980, Location,
2788                                                 "Dynamic keyword requires `{0}' to be defined. Are you missing System.Core.dll assembly reference?",
2789                                                 mc.Module.PredefinedAttributes.Dynamic.GetSignatureForError ());
2790                                 }
2791
2792                                 fne = new DynamicTypeExpr (loc);
2793                                 fne.ResolveAsType (mc);
2794                         }
2795
2796                         if (fne != null)
2797                                 return fne;
2798
2799                         Error_TypeOrNamespaceNotFound (mc);
2800                         return null;
2801                 }
2802
2803                 bool IsPossibleTypeOrNamespace (IMemberContext mc)
2804                 {
2805                         //
2806                         // Has to ignore static usings because we are looking for any member not just type
2807                         // in this context
2808                         //
2809                         return mc.LookupNamespaceOrType (Name, Arity, LookupMode.Probing | LookupMode.IgnoreStaticUsing, loc) != null;
2810                 }
2811
2812                 public bool IsPossibleType (IMemberContext mc)
2813                 {
2814                         return mc.LookupNamespaceOrType (Name, Arity, LookupMode.Probing, loc) is TypeExpr;
2815                 }
2816
2817                 public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions)
2818                 {
2819                         int lookup_arity = Arity;
2820                         bool errorMode = false;
2821                         Expression e;
2822                         Block current_block = rc.CurrentBlock;
2823                         INamedBlockVariable variable = null;
2824                         bool variable_found = false;
2825
2826                         while (true) {
2827                                 //
2828                                 // Stage 1: binding to local variables or parameters
2829                                 //
2830                                 // LAMESPEC: It should take invocableOnly into account but that would break csc compatibility
2831                                 //
2832                                 if (current_block != null && lookup_arity == 0) {
2833                                         if (current_block.ParametersBlock.TopBlock.GetLocalName (Name, current_block.Original, ref variable)) {
2834                                                 if (!variable.IsDeclared) {
2835                                                         // We found local name in accessible block but it's not
2836                                                         // initialized yet, maybe the user wanted to bind to something else
2837                                                         errorMode = true;
2838                                                         variable_found = true;
2839                                                 } else {
2840                                                         e = variable.CreateReferenceExpression (rc, loc);
2841                                                         if (e != null) {
2842                                                                 if (Arity > 0)
2843                                                                         Error_TypeArgumentsCannotBeUsed (rc, "variable", Name, loc);
2844
2845                                                                 return e;
2846                                                         }
2847                                                 }
2848                                         }
2849                                 }
2850
2851                                 //
2852                                 // Stage 2: Lookup members if we are inside a type up to top level type for nested types
2853                                 //
2854                                 TypeSpec member_type = rc.CurrentType;
2855                                 for (; member_type != null; member_type = member_type.DeclaringType) {
2856                                         e = MemberLookup (rc, errorMode, member_type, Name, lookup_arity, restrictions, loc);
2857                                         if (e == null)
2858                                                 continue;
2859
2860                                         var me = e as MemberExpr;
2861                                         if (me == null) {
2862                                                 // The name matches a type, defer to ResolveAsTypeStep
2863                                                 if (e is TypeExpr)
2864                                                         break;
2865
2866                                                 continue;
2867                                         }
2868
2869                                         if (errorMode) {
2870                                                 if (variable != null) {
2871                                                         if (me is FieldExpr || me is ConstantExpr || me is EventExpr || me is PropertyExpr) {
2872                                                                 rc.Report.Error (844, loc,
2873                                                                         "A local variable `{0}' cannot be used before it is declared. Consider renaming the local variable when it hides the member `{1}'",
2874                                                                         Name, me.GetSignatureForError ());
2875                                                         } else {
2876                                                                 break;
2877                                                         }
2878                                                 } else if (me is MethodGroupExpr || me is PropertyExpr || me is IndexerExpr) {
2879                                                         // Leave it to overload resolution to report correct error
2880                                                 } else {
2881                                                         // TODO: rc.Report.SymbolRelatedToPreviousError ()
2882                                                         ErrorIsInaccesible (rc, me.GetSignatureForError (), loc);
2883                                                 }
2884                                         } else {
2885                                                 //
2886                                                 // MemberLookup does not check accessors availability, this is actually needed for properties only
2887                                                 //
2888                                                 var pe = me as PropertyExpr;
2889                                                 if (pe != null) {
2890
2891                                                         // Break as there is no other overload available anyway
2892                                                         if ((restrictions & MemberLookupRestrictions.ReadAccess) != 0) {
2893                                                                 if (!pe.PropertyInfo.HasGet || !pe.PropertyInfo.Get.IsAccessible (rc))
2894                                                                         break;
2895
2896                                                                 pe.Getter = pe.PropertyInfo.Get;
2897                                                         } else {
2898                                                                 if (!pe.PropertyInfo.HasSet) {
2899                                                                         if (rc.HasSet (ResolveContext.Options.ConstructorScope) && pe.IsAutoPropertyAccess &&
2900                                                                                 pe.PropertyInfo.DeclaringType == rc.CurrentType && pe.IsStatic == rc.IsStatic) {
2901                                                                                 var p = (Property) pe.PropertyInfo.MemberDefinition;
2902                                                                                 return new FieldExpr (p.BackingField, loc);
2903                                                                         }
2904
2905                                                                         variable_found = true;
2906                                                                         break;
2907                                                                 }
2908
2909                                                                 if (!pe.PropertyInfo.Set.IsAccessible (rc)) {
2910                                                                         variable_found = true;
2911                                                                         break;
2912                                                                 }
2913
2914                                                                 pe.Setter = pe.PropertyInfo.Set;
2915                                                         }
2916                                                 }
2917                                         }
2918
2919                                         // TODO: It's used by EventExpr -> FieldExpr transformation only
2920                                         // TODO: Should go to MemberAccess
2921                                         me = me.ResolveMemberAccess (rc, null, null);
2922
2923                                         if (Arity > 0) {
2924                                                 targs.Resolve (rc, false);
2925                                                 me.SetTypeArguments (rc, targs);
2926                                         }
2927
2928                                         return me;
2929                                 }
2930
2931                                 //
2932                                 // Stage 3: Lookup nested types, namespaces and type parameters in the context
2933                                 //
2934                                 if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0 && !variable_found) {
2935                                         if (IsPossibleTypeOrNamespace (rc)) {
2936                                                 return ResolveAsTypeOrNamespace (rc, false);
2937                                         }
2938                                 }
2939
2940                                 var expr = NamespaceContainer.LookupStaticUsings (rc, Name, Arity, loc);
2941                                 if (expr != null) {
2942                                         if (Arity > 0) {
2943                                                 targs.Resolve (rc, false);
2944
2945                                                 var me = expr as MemberExpr;
2946                                                 if (me != null)
2947                                                         me.SetTypeArguments (rc, targs);
2948                                         }
2949                                         return expr;
2950                                 }
2951
2952                                 if ((restrictions & MemberLookupRestrictions.NameOfExcluded) == 0 && Name == "nameof")
2953                                         return new NameOf (this);
2954
2955                                 if (errorMode) {
2956                                         if (variable_found) {
2957                                                 rc.Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", Name);
2958                                         } else {
2959                                                 if (Arity > 0) {
2960                                                         var tparams = rc.CurrentTypeParameters;
2961                                                         if (tparams != null) {
2962                                                                 if (tparams.Find (Name) != null) {
2963                                                                         Error_TypeArgumentsCannotBeUsed (rc, "type parameter", Name, loc);
2964                                                                         return null;
2965                                                                 }
2966                                                         }
2967
2968                                                         var ct = rc.CurrentType;
2969                                                         do {
2970                                                                 if (ct.MemberDefinition.TypeParametersCount > 0) {
2971                                                                         foreach (var ctp in ct.MemberDefinition.TypeParameters) {
2972                                                                                 if (ctp.Name == Name) {
2973                                                                                         Error_TypeArgumentsCannotBeUsed (rc, "type parameter", Name, loc);
2974                                                                                         return null;
2975                                                                                 }
2976                                                                         }
2977                                                                 }
2978
2979                                                                 ct = ct.DeclaringType;
2980                                                         } while (ct != null);
2981                                                 }
2982
2983                                                 if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0) {
2984                                                         e = rc.LookupNamespaceOrType (Name, Arity, LookupMode.IgnoreAccessibility, loc);
2985                                                         if (e != null) {
2986                                                                 rc.Report.SymbolRelatedToPreviousError (e.Type);
2987                                                                 ErrorIsInaccesible (rc, e.GetSignatureForError (), loc);
2988                                                                 return e;
2989                                                         }
2990                                                 } else {
2991                                                         var me = MemberLookup (rc, false, rc.CurrentType, Name, Arity, restrictions & ~MemberLookupRestrictions.InvocableOnly, loc) as MemberExpr;
2992                                                         if (me != null) {
2993                                                                 Error_UnexpectedKind (rc, me, "method group", me.KindName, loc);
2994                                                                 return ErrorExpression.Instance;
2995                                                         }
2996                                                 }
2997
2998                                                 e = rc.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), LookupMode.Probing, loc);
2999                                                 if (e != null) {
3000                                                         if (e.Type.Arity != Arity && (restrictions & MemberLookupRestrictions.IgnoreArity) == 0) {
3001                                                                 Error_TypeArgumentsCannotBeUsed (rc, e.Type, loc);
3002                                                                 return e;
3003                                                         }
3004
3005                                                         if (e is TypeExpr) {
3006                                                                 // TypeExpression does not have correct location
3007                                                                 if (e is TypeExpression)
3008                                                                         e = new TypeExpression (e.Type, loc);
3009
3010                                                                 return e;
3011                                                         }
3012                                                 }
3013
3014                                                 Error_NameDoesNotExist (rc);
3015                                         }
3016
3017                                         return ErrorExpression.Instance;
3018                                 }
3019
3020                                 if (rc.Module.Evaluator != null) {
3021                                         var fi = rc.Module.Evaluator.LookupField (Name);
3022                                         if (fi != null)
3023                                                 return new FieldExpr (fi.Item1, loc);
3024                                 }
3025
3026                                 lookup_arity = 0;
3027                                 errorMode = true;
3028                         }
3029                 }
3030                 
3031                 Expression SimpleNameResolve (ResolveContext ec, Expression right_side)
3032                 {
3033                         Expression e = LookupNameExpression (ec, right_side == null ? MemberLookupRestrictions.ReadAccess : MemberLookupRestrictions.None);
3034
3035                         if (e == null)
3036                                 return null;
3037
3038                         if (e is FullNamedExpression && e.eclass != ExprClass.Unresolved) {
3039                                 Error_UnexpectedKind (ec, e, "variable", e.ExprClassName, loc);
3040                                 return e;
3041                         }
3042
3043                         if (right_side != null) {
3044                                 e = e.ResolveLValue (ec, right_side);
3045                         } else {
3046                                 e = e.Resolve (ec);
3047                         }
3048
3049                         return e;
3050                 }
3051                 
3052                 public override object Accept (StructuralVisitor visitor)
3053                 {
3054                         return visitor.Visit (this);
3055                 }
3056         }
3057
3058         /// <summary>
3059         ///   Represents a namespace or a type.  The name of the class was inspired by
3060         ///   section 10.8.1 (Fully Qualified Names).
3061         /// </summary>
3062         public abstract class FullNamedExpression : Expression
3063         {
3064                 protected override void CloneTo (CloneContext clonectx, Expression target)
3065                 {
3066                         // Do nothing, most unresolved type expressions cannot be
3067                         // resolved to different type
3068                 }
3069
3070                 public override bool ContainsEmitWithAwait ()
3071                 {
3072                         return false;
3073                 }
3074
3075                 public override Expression CreateExpressionTree (ResolveContext ec)
3076                 {
3077                         throw new NotSupportedException ("ET");
3078                 }
3079
3080                 public abstract FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc, bool allowUnboundTypeArguments);
3081
3082                 //
3083                 // This is used to resolve the expression as a type, a null
3084                 // value will be returned if the expression is not a type
3085                 // reference
3086                 //
3087                 public override TypeSpec ResolveAsType (IMemberContext mc, bool allowUnboundTypeArguments = false)
3088                 {
3089                         FullNamedExpression fne = ResolveAsTypeOrNamespace (mc, allowUnboundTypeArguments);
3090
3091                         if (fne == null)
3092                                 return null;
3093
3094                         TypeExpr te = fne as TypeExpr;
3095                         if (te == null) {
3096                                 Error_UnexpectedKind (mc, fne, "type", fne.ExprClassName, loc);
3097                                 return null;
3098                         }
3099
3100                         te.loc = loc;
3101
3102                         type = te.Type;
3103
3104                         var dep = type.GetMissingDependencies ();
3105                         if (dep != null) {
3106                                 ImportedTypeDefinition.Error_MissingDependency (mc, dep, loc);
3107                         }
3108
3109                         if (type.Kind == MemberKind.Void) {
3110                                 mc.Module.Compiler.Report.Error (673, loc, "System.Void cannot be used from C#. Consider using `void'");
3111                         }
3112
3113                         //
3114                         // Obsolete checks cannot be done when resolving base context as they
3115                         // require type dependencies to be set but we are in process of resolving them
3116                         //
3117                         if (mc is ResolveContext) {
3118                                 var oa = type.GetAttributeObsolete ();
3119                                 if (oa != null && !mc.IsObsolete)
3120                                         AttributeTester.Report_ObsoleteMessage (oa, type.GetSignatureForError (), fne.Location, mc.Module.Compiler.Report);
3121                         }
3122
3123                         return type;
3124                 }
3125
3126
3127                 public override void Emit (EmitContext ec)
3128                 {
3129                         throw new InternalErrorException ("FullNamedExpression `{0}' found in resolved tree",
3130                                 GetSignatureForError ());
3131                 }
3132         }
3133         
3134         /// <summary>
3135         ///   Expression that evaluates to a type
3136         /// </summary>
3137         public abstract class TypeExpr : FullNamedExpression
3138         {
3139                 public sealed override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc, bool allowUnboundTypeArguments)
3140                 {
3141                         ResolveAsType (mc);
3142                         return this;
3143                 }
3144
3145                 protected sealed override Expression DoResolve (ResolveContext ec)
3146                 {
3147                         ResolveAsType (ec);
3148                         return this;
3149                 }
3150
3151                 public override bool Equals (object obj)
3152                 {
3153                         TypeExpr tobj = obj as TypeExpr;
3154                         if (tobj == null)
3155                                 return false;
3156
3157                         return Type == tobj.Type;
3158                 }
3159
3160                 public override int GetHashCode ()
3161                 {
3162                         return Type.GetHashCode ();
3163                 }
3164         }
3165
3166         /// <summary>
3167         ///   Fully resolved Expression that already evaluated to a type
3168         /// </summary>
3169         public class TypeExpression : TypeExpr
3170         {
3171                 public TypeExpression (TypeSpec t, Location l)
3172                 {
3173                         Type = t;
3174                         eclass = ExprClass.Type;
3175                         loc = l;
3176                 }
3177
3178                 public sealed override TypeSpec ResolveAsType (IMemberContext mc, bool allowUnboundTypeArguments = false)
3179                 {
3180                         return type;
3181                 }
3182         }
3183
3184         public class NamespaceExpression : FullNamedExpression
3185         {
3186                 readonly Namespace ns;
3187
3188                 public NamespaceExpression (Namespace ns, Location loc)
3189                 {
3190                         this.ns = ns;
3191                         this.Type = InternalType.Namespace;
3192                         this.eclass = ExprClass.Namespace;
3193                         this.loc = loc;
3194                 }
3195
3196                 public Namespace Namespace {
3197                         get {
3198                                 return ns;
3199                         }
3200                 }
3201
3202                 protected override Expression DoResolve (ResolveContext rc)
3203                 {
3204                         throw new NotImplementedException ();
3205                 }
3206
3207                 public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc, bool allowUnboundTypeArguments)
3208                 {
3209                         return this;
3210                 }
3211
3212                 public void Error_NamespaceDoesNotExist (IMemberContext ctx, string name, int arity, Location loc)
3213                 {
3214                         var retval = Namespace.LookupType (ctx, name, arity, LookupMode.IgnoreAccessibility, loc);
3215                         if (retval != null) {
3216 //                              ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (retval.MemberDefinition);
3217                                 ErrorIsInaccesible (ctx, retval.GetSignatureForError (), loc);
3218                                 return;
3219                         }
3220
3221                         retval = Namespace.LookupType (ctx, name, -System.Math.Max (1, arity), LookupMode.Probing, loc);
3222                         if (retval != null) {
3223                                 Error_TypeArgumentsCannotBeUsed (ctx, retval, loc);
3224                                 return;
3225                         }
3226
3227                         Namespace ns;
3228                         if (arity > 0 && Namespace.TryGetNamespace (name, out ns)) {
3229                                 Error_TypeArgumentsCannotBeUsed (ctx, ExprClassName, ns.GetSignatureForError (), loc);
3230                                 return;
3231                         }
3232
3233                         string assembly = null;
3234                         string possible_name = Namespace.GetSignatureForError () + "." + name;
3235
3236                         // Only assembly unique name should be added
3237                         switch (possible_name) {
3238                         case "System.Drawing":
3239                         case "System.Web.Services":
3240                         case "System.Web":
3241                         case "System.Data":
3242                         case "System.Configuration":
3243                         case "System.Data.Services":
3244                         case "System.DirectoryServices":
3245                         case "System.Json":
3246                         case "System.Net.Http":
3247                         case "System.Numerics":
3248                         case "System.Runtime.Caching":
3249                         case "System.ServiceModel":
3250                         case "System.Transactions":
3251                         case "System.Web.Routing":
3252                         case "System.Xml.Linq":
3253                         case "System.Xml":
3254                                 assembly = possible_name;
3255                                 break;
3256
3257                         case "System.Linq":
3258                         case "System.Linq.Expressions":
3259                                 assembly = "System.Core";
3260                                 break;
3261
3262                         case "System.Windows.Forms":
3263                         case "System.Windows.Forms.Layout":
3264                                 assembly = "System.Windows.Forms";
3265                                 break;
3266                         }
3267
3268                         assembly = assembly == null ? "an" : "`" + assembly + "'";
3269
3270                         if (Namespace is GlobalRootNamespace) {
3271                                 ctx.Module.Compiler.Report.Error (400, loc,
3272                                         "The type or namespace name `{0}' could not be found in the global namespace. Are you missing {1} assembly reference?",
3273                                         name, assembly);
3274                         } else {
3275                                 ctx.Module.Compiler.Report.Error (234, loc,
3276                                         "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing {2} assembly reference?",
3277                                         name, GetSignatureForError (), assembly);
3278                         }
3279                 }
3280
3281                 public override string GetSignatureForError ()
3282                 {
3283                         return ns.GetSignatureForError ();
3284                 }
3285
3286                 public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc)
3287                 {
3288                         return ns.LookupTypeOrNamespace (ctx, name, arity, mode, loc);
3289                 }
3290
3291                 public override string ToString ()
3292                 {
3293                         return Namespace.Name;
3294                 }
3295     }
3296
3297         /// <summary>
3298         ///   This class denotes an expression which evaluates to a member
3299         ///   of a struct or a class.
3300         /// </summary>
3301         public abstract class MemberExpr : Expression, OverloadResolver.IInstanceQualifier
3302         {
3303                 protected bool conditional_access_receiver;
3304
3305                 //
3306                 // An instance expression associated with this member, if it's a
3307                 // non-static member
3308                 //
3309                 public Expression InstanceExpression;
3310
3311                 /// <summary>
3312                 ///   The name of this member.
3313                 /// </summary>
3314                 public abstract string Name {
3315                         get;
3316                 }
3317
3318                 //
3319                 // When base.member is used
3320                 //
3321                 public bool IsBase {
3322                         get { return InstanceExpression is BaseThis; }
3323                 }
3324
3325                 /// <summary>
3326                 ///   Whether this is an instance member.
3327                 /// </summary>
3328                 public abstract bool IsInstance {
3329                         get;
3330                 }
3331
3332                 /// <summary>
3333                 ///   Whether this is a static member.
3334                 /// </summary>
3335                 public abstract bool IsStatic {
3336                         get;
3337                 }
3338
3339                 public abstract string KindName {
3340                         get;
3341                 }
3342
3343                 public bool ConditionalAccess { get; set; }
3344
3345                 protected abstract TypeSpec DeclaringType {
3346                         get;
3347                 }
3348
3349                 TypeSpec OverloadResolver.IInstanceQualifier.InstanceType {
3350                         get {
3351                                 return InstanceExpression.Type;
3352                         }
3353                 }
3354
3355                 //
3356                 // Converts best base candidate for virtual method starting from QueriedBaseType
3357                 //
3358                 protected MethodSpec CandidateToBaseOverride (ResolveContext rc, MethodSpec method)
3359                 {
3360                         //
3361                         // Only when base.member is used and method is virtual
3362                         //
3363                         if (!IsBase)
3364                                 return method;
3365
3366                         //
3367                         // Overload resulution works on virtual or non-virtual members only (no overrides). That
3368                         // means for base.member access we have to find the closest match after we found best candidate
3369                         //
3370                         if ((method.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3371                                 //
3372                                 // The method could already be what we are looking for
3373                                 //
3374                                 TypeSpec[] targs = null;
3375                                 if (method.DeclaringType != InstanceExpression.Type) {
3376                                         //
3377                                         // Candidate can have inflated MVAR parameters and we need to find
3378                                         // base match for original definition not inflated parameter types
3379                                         //
3380                                         var parameters = method.Parameters;
3381                                         if (method.Arity > 0) {
3382                                                 parameters = ((IParametersMember) method.MemberDefinition).Parameters;
3383                                                 var inflated = method.DeclaringType as InflatedTypeSpec;
3384                                                 if (inflated != null) {
3385                                                         parameters = parameters.Inflate (inflated.CreateLocalInflator (rc));
3386                                                 }
3387                                         }
3388
3389                                         var filter = new MemberFilter (method.Name, method.Arity, MemberKind.Method, parameters, null);
3390                                         var base_override = MemberCache.FindMember (InstanceExpression.Type, filter, BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly) as MethodSpec;
3391                                         if (base_override != null && base_override.DeclaringType != method.DeclaringType) {
3392                                                 if (base_override.IsGeneric)
3393                                                         targs = method.TypeArguments;
3394
3395                                                 method = base_override;
3396                                         }
3397                                 }
3398
3399                                 //
3400                                 // When base access is used inside anonymous method/iterator/etc we need to
3401                                 // get back to the context of original type. We do it by emiting proxy
3402                                 // method in original class and rewriting base call to this compiler
3403                                 // generated method call which does the actual base invocation. This may
3404                                 // introduce redundant storey but with `this' only but it's tricky to avoid
3405                                 // at this stage as we don't know what expressions follow base
3406                                 //
3407                                 // TODO: It's needed only when the method with base call is moved to a storey
3408                                 //
3409                                 if (rc.CurrentAnonymousMethod != null) {
3410                                         if (targs == null && method.IsGeneric) {
3411                                                 targs = method.TypeArguments;
3412                                                 method = method.GetGenericMethodDefinition ();
3413                                         }
3414
3415                                         if (method.Parameters.HasArglist)
3416                                                 throw new NotImplementedException ("__arglist base call proxy");
3417
3418                                         method = rc.CurrentMemberDefinition.Parent.PartialContainer.CreateHoistedBaseCallProxy (rc, method);
3419
3420                                         // Ideally this should apply to any proxy rewrite but in the case of unary mutators on
3421                                         // get/set member expressions second call would fail to proxy because left expression
3422                                         // would be of 'this' and not 'base' because we share InstanceExpression for get/set
3423                                         // FIXME: The async check is another hack but will probably fail with mutators
3424                                         if (rc.CurrentType.IsStruct || rc.CurrentAnonymousMethod.Storey is AsyncTaskStorey)
3425                                                 InstanceExpression = new This (loc).Resolve (rc);
3426                                 }
3427
3428                                 if (targs != null)
3429                                         method = method.MakeGenericMethod (rc, targs);
3430                         }
3431
3432                         //
3433                         // Only base will allow this invocation to happen.
3434                         //
3435                         if (method.IsAbstract) {
3436                                 rc.Report.SymbolRelatedToPreviousError (method);
3437                                 Error_CannotCallAbstractBase (rc, method.GetSignatureForError ());
3438                         }
3439
3440                         return method;
3441                 }
3442
3443                 protected void CheckProtectedMemberAccess (ResolveContext rc, MemberSpec member)
3444                 {
3445                         if (InstanceExpression == null)
3446                                 return;
3447
3448                         if ((member.Modifiers & Modifiers.PROTECTED) != 0 && !(InstanceExpression is This)) {
3449                                 if (!CheckProtectedMemberAccess (rc, member, InstanceExpression.Type)) {
3450                                         Error_ProtectedMemberAccess (rc, member, InstanceExpression.Type, loc);
3451                                 }
3452                         }
3453                 }
3454
3455                 bool OverloadResolver.IInstanceQualifier.CheckProtectedMemberAccess (ResolveContext rc, MemberSpec member)
3456                 {
3457                         if (InstanceExpression == null)
3458                                 return true;
3459
3460                         return InstanceExpression is This || CheckProtectedMemberAccess (rc, member, InstanceExpression.Type);
3461                 }
3462
3463                 public static bool CheckProtectedMemberAccess<T> (ResolveContext rc, T member, TypeSpec qualifier) where T : MemberSpec
3464                 {
3465                         var ct = rc.CurrentType;
3466                         if (ct == qualifier)
3467                                 return true;
3468
3469                         if ((member.Modifiers & Modifiers.INTERNAL) != 0 && member.DeclaringType.MemberDefinition.IsInternalAsPublic (ct.MemberDefinition.DeclaringAssembly))
3470                                 return true;
3471
3472                         qualifier = qualifier.GetDefinition ();
3473                         if (ct != qualifier && !IsSameOrBaseQualifier (ct, qualifier)) {
3474                                 return false;
3475                         }
3476
3477                         return true;
3478                 }
3479
3480                 public override bool ContainsEmitWithAwait ()
3481                 {
3482                         return InstanceExpression != null && InstanceExpression.ContainsEmitWithAwait ();
3483                 }
3484
3485                 public override bool HasConditionalAccess ()
3486                 {
3487                         return ConditionalAccess || (InstanceExpression != null && InstanceExpression.HasConditionalAccess ());
3488                 }
3489
3490                 static bool IsSameOrBaseQualifier (TypeSpec type, TypeSpec qtype)
3491                 {
3492                         do {
3493                                 type = type.GetDefinition ();
3494
3495                                 if (type == qtype || TypeManager.IsFamilyAccessible (qtype, type))
3496                                         return true;
3497
3498                                 type = type.DeclaringType;
3499                         } while (type != null);
3500
3501                         return false;
3502                 }
3503
3504                 protected void DoBestMemberChecks<T> (ResolveContext rc, T member) where T : MemberSpec, IInterfaceMemberSpec
3505                 {
3506                         if (InstanceExpression != null) {
3507                                 InstanceExpression = InstanceExpression.Resolve (rc);
3508                                 CheckProtectedMemberAccess (rc, member);
3509                         }
3510
3511                         if (member.MemberType.IsPointer) {
3512                                 if (rc.CurrentIterator != null) {
3513                                         UnsafeInsideIteratorError (rc, loc);
3514                                 } else if (!rc.IsUnsafe) {
3515                                         UnsafeError (rc, loc);
3516                                 }
3517                         }
3518
3519                         var dep = member.GetMissingDependencies ();
3520                         if (dep != null) {
3521                                 ImportedTypeDefinition.Error_MissingDependency (rc, dep, loc);
3522                         }
3523
3524                         member.CheckObsoleteness (rc, loc);
3525
3526                         if (!(member is FieldSpec))
3527                                 member.MemberDefinition.SetIsUsed ();
3528                 }
3529
3530                 protected virtual void Error_CannotCallAbstractBase (ResolveContext rc, string name)
3531                 {
3532                         rc.Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
3533                 }
3534
3535                 public static void Error_ProtectedMemberAccess (ResolveContext rc, MemberSpec member, TypeSpec qualifier, Location loc)
3536                 {
3537                         rc.Report.SymbolRelatedToPreviousError (member);
3538                         rc.Report.Error (1540, loc,
3539                                 "Cannot access protected member `{0}' via a qualifier of type `{1}'. The qualifier must be of type `{2}' or derived from it",
3540                                 member.GetSignatureForError (), qualifier.GetSignatureForError (), rc.CurrentType.GetSignatureForError ());
3541                 }
3542
3543                 public override void FlowAnalysis (FlowAnalysisContext fc)
3544                 {
3545                         if (InstanceExpression != null) {
3546                                 InstanceExpression.FlowAnalysis (fc);
3547                         }
3548                 }
3549
3550                 protected void ResolveConditionalAccessReceiver (ResolveContext rc)
3551                 {
3552                         if (!rc.HasSet (ResolveContext.Options.DontSetConditionalAccessReceiver) && HasConditionalAccess ()) {
3553                                 conditional_access_receiver = true;
3554                         }
3555                 }
3556
3557                 public bool ResolveInstanceExpression (ResolveContext rc, Expression rhs)
3558                 {
3559                         if (!ResolveInstanceExpressionCore (rc, rhs))
3560                                 return false;
3561
3562                         //
3563                         // Check intermediate value modification which won't have any effect
3564                         //
3565                         if (rhs != null && TypeSpec.IsValueType (InstanceExpression.Type)) {
3566                                 var fexpr = InstanceExpression as FieldExpr;
3567                                 if (fexpr != null) {
3568                                         if (!fexpr.Spec.IsReadOnly || rc.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.ConstructorScope))
3569                                                 return true;
3570
3571                                         if (fexpr.IsStatic) {
3572                                                 rc.Report.Error (1650, loc, "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
3573                                                         fexpr.GetSignatureForError ());
3574                                         } else {
3575                                                 rc.Report.Error (1648, loc, "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)",
3576                                                         fexpr.GetSignatureForError ());
3577                                         }
3578
3579                                         return true;
3580                                 }
3581
3582                                 if (InstanceExpression is PropertyExpr || InstanceExpression is IndexerExpr || InstanceExpression is Invocation) {
3583                                         if (rc.CurrentInitializerVariable != null) {
3584                                                 rc.Report.Error (1918, loc, "Members of value type `{0}' cannot be assigned using a property `{1}' object initializer",
3585                                                         InstanceExpression.Type.GetSignatureForError (), InstanceExpression.GetSignatureForError ());
3586                                         } else {
3587                                                 rc.Report.Error (1612, loc,
3588                                                         "Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable",
3589                                                         InstanceExpression.GetSignatureForError ());
3590                                         }
3591
3592                                         return true;
3593                                 }
3594
3595                                 var lvr = InstanceExpression as LocalVariableReference;
3596                                 if (lvr != null) {
3597
3598                                         if (!lvr.local_info.IsReadonly)
3599                                                 return true;
3600
3601                                         rc.Report.Error (1654, loc, "Cannot assign to members of `{0}' because it is a `{1}'",
3602                                                 InstanceExpression.GetSignatureForError (), lvr.local_info.GetReadOnlyContext ());
3603                                 }
3604                         }
3605
3606                         return true;
3607                 }
3608
3609                 bool ResolveInstanceExpressionCore (ResolveContext rc, Expression rhs)
3610                 {
3611                         if (IsStatic) {
3612                                 if (InstanceExpression != null) {
3613                                         if (InstanceExpression is TypeExpr) {
3614                                                 var t = InstanceExpression.Type;
3615                                                 do {
3616                                                         t.CheckObsoleteness (rc, loc);
3617
3618                                                         t = t.DeclaringType;
3619                                                 } while (t != null);
3620                                         } else {
3621                                                 var runtime_expr = InstanceExpression as RuntimeValueExpression;
3622                                                 if (runtime_expr == null || !runtime_expr.IsSuggestionOnly) {
3623                                                         rc.Report.Error (176, loc,
3624                                                                 "Static member `{0}' cannot be accessed with an instance reference, qualify it with a type name instead",
3625                                                                 GetSignatureForError ());
3626                                                 }
3627                                         }
3628
3629                                         InstanceExpression = null;
3630                                 }
3631
3632                                 return false;
3633                         }
3634
3635                         if (InstanceExpression == null || InstanceExpression is TypeExpr) {
3636                                 if (InstanceExpression != null || !This.IsThisAvailable (rc, true)) {
3637                                         if (rc.HasSet (ResolveContext.Options.FieldInitializerScope)) {
3638                                                 rc.Report.Error (236, loc,
3639                                                         "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
3640                                                         GetSignatureForError ());
3641                                         } else {
3642                                                 var fe = this as FieldExpr;
3643                                                 if (fe != null && fe.Spec.MemberDefinition is PrimaryConstructorField) {
3644                                                         if (rc.HasSet (ResolveContext.Options.BaseInitializer)) {
3645                                                                 rc.Report.Error (9005, loc, "Constructor initializer cannot access primary constructor parameters");
3646                                                         } else  {
3647                                                                 rc.Report.Error (9006, loc, "An object reference is required to access primary constructor parameter `{0}'",
3648                                                                         fe.Name);
3649                                                         }
3650                                                 } else {
3651                                                         rc.Report.Error (120, loc,
3652                                                                 "An object reference is required to access non-static member `{0}'",
3653                                                                 GetSignatureForError ());
3654                                                 }
3655                                         }
3656
3657                                         InstanceExpression = new CompilerGeneratedThis (rc.CurrentType, loc).Resolve (rc);
3658                                         return false;
3659                                 }
3660
3661                                 if (!TypeManager.IsFamilyAccessible (rc.CurrentType, DeclaringType)) {
3662                                         rc.Report.Error (38, loc,
3663                                                 "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
3664                                                 DeclaringType.GetSignatureForError (), rc.CurrentType.GetSignatureForError ());
3665                                 }
3666
3667                                 InstanceExpression = new This (loc).Resolve (rc);
3668                                 return false;
3669                         }
3670
3671                         var me = InstanceExpression as MemberExpr;
3672                         if (me != null) {
3673                                 me.ResolveInstanceExpressionCore (rc, rhs);
3674
3675                                 var fe = me as FieldExpr;
3676                                 if (fe != null && fe.IsMarshalByRefAccess (rc)) {
3677                                         rc.Report.SymbolRelatedToPreviousError (me.DeclaringType);
3678                                         rc.Report.Warning (1690, 1, loc,
3679                                                 "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
3680                                                 me.GetSignatureForError ());
3681                                 }
3682
3683                                 return true;
3684                         }
3685
3686                         //
3687                         // Additional checks for l-value member access
3688                         //
3689                         if (rhs != null) {
3690                                 if (InstanceExpression is UnboxCast) {
3691                                         rc.Report.Error (445, InstanceExpression.Location, "Cannot modify the result of an unboxing conversion");
3692                                 }
3693                         }
3694
3695                         return true;
3696                 }
3697
3698                 public virtual MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
3699                 {
3700                         if (left != null && !ConditionalAccess && !ec.HasSet (ResolveContext.Options.NameOfScope) && left.IsNull && TypeSpec.IsReferenceType (left.Type)) {
3701                                 ec.Report.Warning (1720, 1, left.Location,
3702                                         "Expression will always cause a `{0}'", "System.NullReferenceException");
3703                         }
3704
3705                         InstanceExpression = left;
3706                         return this;
3707                 }
3708
3709                 public virtual void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
3710                 {
3711
3712                 }
3713
3714                 protected void EmitInstance (EmitContext ec, bool prepare_for_load)
3715                 {
3716                         var inst = new InstanceEmitter (InstanceExpression, TypeSpec.IsValueType (InstanceExpression.Type));
3717                         inst.Emit (ec, ConditionalAccess);
3718
3719                         if (prepare_for_load)
3720                                 ec.Emit (OpCodes.Dup);
3721                 }
3722
3723                 public abstract void SetTypeArguments (ResolveContext ec, TypeArguments ta);
3724         }
3725
3726         public class ExtensionMethodCandidates
3727         {
3728                 readonly NamespaceContainer container;
3729                 readonly IList<MethodSpec> methods;
3730                 readonly int index;
3731                 readonly IMemberContext context;
3732
3733                 public ExtensionMethodCandidates (IMemberContext context, IList<MethodSpec> methods, NamespaceContainer nsContainer, int lookupIndex)
3734                 {
3735                         this.context = context;
3736                         this.methods = methods;
3737                         this.container = nsContainer;
3738                         this.index = lookupIndex;
3739                 }
3740
3741                 public NamespaceContainer Container {
3742                         get {
3743                                 return container;
3744                         }
3745                 }
3746
3747                 public IMemberContext Context {
3748                         get {
3749                                 return context;
3750                         }
3751                 }
3752
3753                 public int LookupIndex {
3754                         get {
3755                                 return index;
3756                         }
3757                 }
3758
3759                 public IList<MethodSpec> Methods {
3760                         get {
3761                                 return methods;
3762                         }
3763                 }
3764         }
3765
3766         // 
3767         // Represents a group of extension method candidates for whole namespace
3768         // 
3769         class ExtensionMethodGroupExpr : MethodGroupExpr, OverloadResolver.IErrorHandler
3770         {
3771                 ExtensionMethodCandidates candidates;
3772                 public Expression ExtensionExpression;
3773
3774                 public ExtensionMethodGroupExpr (ExtensionMethodCandidates candidates, Expression extensionExpr, Location loc)
3775                         : base (candidates.Methods.Cast<MemberSpec>().ToList (), extensionExpr.Type, loc)
3776                 {
3777                         this.candidates = candidates;
3778                         this.ExtensionExpression = extensionExpr;
3779                 }
3780
3781                 public override bool IsStatic {
3782                         get { return true; }
3783                 }
3784
3785                 //
3786                 // For extension methodgroup we are not looking for base members but parent
3787                 // namespace extension methods
3788                 //
3789                 public override IList<MemberSpec> GetBaseMembers (TypeSpec type)
3790                 {
3791                         // TODO: candidates are null only when doing error reporting, that's
3792                         // incorrect. We have to discover same extension methods in error mode
3793                         if (candidates == null)
3794                                 return null;
3795
3796                         int arity = type_arguments == null ? 0 : type_arguments.Count;
3797
3798                         candidates = candidates.Container.LookupExtensionMethod (candidates.Context, Name, arity, candidates.LookupIndex);
3799                         if (candidates == null)
3800                                 return null;
3801
3802                         return candidates.Methods.Cast<MemberSpec> ().ToList ();
3803                 }
3804
3805                 public static bool IsExtensionTypeCompatible (TypeSpec argType, TypeSpec extensionType)
3806                 {
3807                         //
3808                         // Indentity, implicit reference or boxing conversion must exist for the extension parameter
3809                         //
3810                         // LAMESPEC: or implicit type parameter conversion
3811                         //
3812                         return argType == extensionType ||
3813                                 TypeSpecComparer.IsEqual (argType, extensionType) ||
3814                                 Convert.ImplicitReferenceConversionExists (argType, extensionType, false) ||
3815                                 Convert.ImplicitBoxingConversion (null, argType, extensionType) != null;
3816                 }
3817
3818                 public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
3819                 {
3820                         rc.Report.Error (8093, expr.Location, "An argument to nameof operator cannot be extension method group");
3821                 }
3822
3823                 public override MethodGroupExpr LookupExtensionMethod (ResolveContext rc)
3824                 {
3825                         // We are already here
3826                         return null;
3827                 }
3828
3829                 public override MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments arguments, OverloadResolver.IErrorHandler ehandler, OverloadResolver.Restrictions restr)
3830                 {
3831                         if (arguments == null)
3832                                 arguments = new Arguments (1);
3833
3834                         ExtensionExpression = ExtensionExpression.Resolve (ec);
3835                         if (ExtensionExpression == null)
3836                                 return null;
3837
3838                         var cand = candidates;
3839                         var atype = ConditionalAccess ? Argument.AType.ExtensionTypeConditionalAccess : Argument.AType.ExtensionType;
3840                         arguments.Insert (0, new Argument (ExtensionExpression, atype));
3841                         var res = base.OverloadResolve (ec, ref arguments, ehandler ?? this, restr);
3842                         
3843                         // Restore candidates in case we are running in probing mode 
3844                         candidates = cand;
3845
3846                         // Store resolved argument and restore original arguments
3847                         if (res == null) {
3848                                 // Clean-up modified arguments for error reporting
3849                                 arguments.RemoveAt (0);
3850                                 return null;
3851                         }
3852
3853                         var me = ExtensionExpression as MemberExpr;
3854                         if (me != null) {
3855                                 me.ResolveInstanceExpression (ec, null);
3856                                 var fe = me as FieldExpr;
3857                                 if (fe != null)
3858                                         fe.Spec.MemberDefinition.SetIsUsed ();
3859                         }
3860
3861                         InstanceExpression = null;
3862                         return this;
3863                 }
3864
3865                 #region IErrorHandler Members
3866
3867                 bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext rc, MemberSpec best, MemberSpec ambiguous)
3868                 {
3869                         return false;
3870                 }
3871
3872                 bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index)
3873                 {
3874                         rc.Report.SymbolRelatedToPreviousError (best);
3875
3876                         if (index == 0) {
3877                                 rc.Report.Error (1929, loc,
3878                                         "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' requires an instance of type `{3}'",
3879                                         queried_type.GetSignatureForError (), Name, best.GetSignatureForError (), ((MethodSpec)best).Parameters.ExtensionMethodType.GetSignatureForError ());
3880                         } else {
3881                                 rc.Report.Error (1928, loc,
3882                                         "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' has some invalid arguments",
3883                                         queried_type.GetSignatureForError (), Name, best.GetSignatureForError ());
3884                         }
3885
3886                         return true;
3887                 }
3888
3889                 bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best)
3890                 {
3891                         return false;
3892                 }
3893
3894                 bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best)
3895                 {
3896                         return false;
3897                 }
3898
3899                 #endregion
3900         }
3901
3902         /// <summary>
3903         ///   MethodGroupExpr represents a group of method candidates which
3904         ///   can be resolved to the best method overload
3905         /// </summary>
3906         public class MethodGroupExpr : MemberExpr, OverloadResolver.IBaseMembersProvider
3907         {
3908                 static readonly MemberSpec[] Excluded = new MemberSpec[0];
3909
3910                 protected IList<MemberSpec> Methods;
3911                 MethodSpec best_candidate;
3912                 TypeSpec best_candidate_return;
3913                 protected TypeArguments type_arguments;
3914
3915                 SimpleName simple_name;
3916                 protected TypeSpec queried_type;
3917
3918                 public MethodGroupExpr (IList<MemberSpec> mi, TypeSpec type, Location loc)
3919                 {
3920                         Methods = mi;
3921                         this.loc = loc;
3922                         this.type = InternalType.MethodGroup;
3923
3924                         eclass = ExprClass.MethodGroup;
3925                         queried_type = type;
3926                 }
3927
3928                 public MethodGroupExpr (MethodSpec m, TypeSpec type, Location loc)
3929                         : this (new MemberSpec[] { m }, type, loc)
3930                 {
3931                 }
3932
3933                 #region Properties
3934
3935                 public MethodSpec BestCandidate {
3936                         get {
3937                                 return best_candidate;
3938                         }
3939                 }
3940
3941                 public TypeSpec BestCandidateReturnType {
3942                         get {
3943                                 return best_candidate_return;
3944                         }
3945                 }
3946
3947                 public IList<MemberSpec> Candidates {
3948                         get {
3949                                 return Methods;
3950                         }
3951                 }
3952
3953                 protected override TypeSpec DeclaringType {
3954                         get {
3955                                 return queried_type;
3956                         }
3957                 }
3958
3959                 public bool IsConditionallyExcluded {
3960                         get {
3961                                 return Methods == Excluded;
3962                         }
3963                 }
3964
3965                 public override bool IsInstance {
3966                         get {
3967                                 if (best_candidate != null)
3968                                         return !best_candidate.IsStatic;
3969
3970                                 return false;
3971                         }
3972                 }
3973
3974                 public override bool IsSideEffectFree {
3975                         get {
3976                                 return InstanceExpression == null || InstanceExpression.IsSideEffectFree;
3977                         }
3978                 }
3979
3980                 public override bool IsStatic {
3981                         get {
3982                                 if (best_candidate != null)
3983                                         return best_candidate.IsStatic;
3984
3985                                 return false;
3986                         }
3987                 }
3988
3989                 public override string KindName {
3990                         get { return "method"; }
3991                 }
3992
3993                 public override string Name {
3994                         get {
3995                                 if (best_candidate != null)
3996                                         return best_candidate.Name;
3997
3998                                 // TODO: throw ?
3999                                 return Methods.First ().Name;
4000                         }
4001                 }
4002
4003                 #endregion
4004
4005                 //
4006                 // When best candidate is already know this factory can be used
4007                 // to avoid expensive overload resolution to be called
4008                 //
4009                 // NOTE: InstanceExpression has to be set manually
4010                 //
4011                 public static MethodGroupExpr CreatePredefined (MethodSpec best, TypeSpec queriedType, Location loc)
4012                 {
4013                         return new MethodGroupExpr (best, queriedType, loc) {
4014                                 best_candidate = best,
4015                                 best_candidate_return = best.ReturnType
4016                         };
4017                 }
4018
4019                 public override string GetSignatureForError ()
4020                 {
4021                         if (best_candidate != null)
4022                                 return best_candidate.GetSignatureForError ();
4023
4024                         return Methods.First ().GetSignatureForError ();
4025                 }
4026
4027                 public override Expression CreateExpressionTree (ResolveContext ec)
4028                 {
4029                         if (best_candidate == null) {
4030                                 ec.Report.Error (1953, loc, "An expression tree cannot contain an expression with method group");
4031                                 return null;
4032                         }
4033
4034                         if (IsConditionallyExcluded)
4035                                 ec.Report.Error (765, loc,
4036                                         "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
4037
4038                         if (ConditionalAccess)
4039                                 Error_NullShortCircuitInsideExpressionTree (ec);
4040
4041                         return new TypeOfMethod (best_candidate, loc);
4042                 }
4043                 
4044                 protected override Expression DoResolve (ResolveContext ec)
4045                 {
4046                         this.eclass = ExprClass.MethodGroup;
4047
4048                         if (InstanceExpression != null) {
4049                                 InstanceExpression = InstanceExpression.Resolve (ec);
4050                                 if (InstanceExpression == null)
4051                                         return null;
4052                         }
4053
4054                         return this;
4055                 }
4056
4057                 public override void Emit (EmitContext ec)
4058                 {
4059                         throw new NotSupportedException ();
4060                 }
4061
4062                 public override void EmitPrepare (EmitContext ec)
4063                 {
4064                         InstanceExpression?.EmitPrepare (ec);
4065                 }
4066
4067                 public void EmitCall (EmitContext ec, Arguments arguments, bool statement)
4068                 {
4069                         var call = new CallEmitter ();
4070                         call.InstanceExpression = InstanceExpression;
4071                         call.ConditionalAccess = ConditionalAccess;
4072
4073                         if (statement)
4074                                 call.EmitStatement (ec, best_candidate, arguments, loc);
4075                         else
4076                                 call.Emit (ec, best_candidate, arguments, loc);
4077                 }
4078
4079                 public void EmitCall (EmitContext ec, Arguments arguments, TypeSpec conditionalAccessReceiver, bool statement)
4080                 {
4081                         var ca = ec.ConditionalAccess;
4082                         ec.ConditionalAccess = new ConditionalAccessContext (conditionalAccessReceiver, ec.DefineLabel ()) {
4083                                 Statement = statement
4084                         };
4085
4086                         EmitCall (ec, arguments, statement);
4087
4088                         ec.CloseConditionalAccess (!statement && best_candidate_return != conditionalAccessReceiver && conditionalAccessReceiver.IsNullableType ? conditionalAccessReceiver : null);
4089                         ec.ConditionalAccess = ca;
4090                 }
4091
4092                 public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
4093                 {
4094                         if (target != InternalType.ErrorType) {
4095                                 ec.Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method",
4096                                         Name, target.GetSignatureForError ());
4097                         }
4098                 }
4099
4100                 public bool HasAccessibleCandidate (ResolveContext rc)
4101                 {
4102                         foreach (var candidate in Candidates) {
4103                                 if (candidate.IsAccessible (rc))
4104                                         return true;
4105                         }
4106
4107                         return false;
4108                 }
4109
4110                 public static bool IsExtensionMethodArgument (Expression expr)
4111                 {
4112                         //
4113                         // LAMESPEC: No details about which expressions are not allowed
4114                         //
4115                         return !(expr is TypeExpr) && !(expr is BaseThis);
4116                 }
4117
4118                 /// <summary>
4119                 ///   Find the Applicable Function Members (7.4.2.1)
4120                 ///
4121                 ///   me: Method Group expression with the members to select.
4122                 ///       it might contain constructors or methods (or anything
4123                 ///       that maps to a method).
4124                 ///
4125                 ///   Arguments: ArrayList containing resolved Argument objects.
4126                 ///
4127                 ///   loc: The location if we want an error to be reported, or a Null
4128                 ///        location for "probing" purposes.
4129                 ///
4130                 ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
4131                 ///            that is the best match of me on Arguments.
4132                 ///
4133                 /// </summary>
4134                 public virtual MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments args, OverloadResolver.IErrorHandler cerrors, OverloadResolver.Restrictions restr)
4135                 {
4136                         // TODO: causes issues with probing mode, remove explicit Kind check
4137                         if (best_candidate != null && best_candidate.Kind == MemberKind.Destructor)
4138                                 return this;
4139
4140                         var r = new OverloadResolver (Methods, type_arguments, restr, loc);
4141                         if ((restr & OverloadResolver.Restrictions.NoBaseMembers) == 0) {
4142                                 r.BaseMembersProvider = this;
4143                                 r.InstanceQualifier = this;
4144                         }
4145
4146                         if (cerrors != null)
4147                                 r.CustomErrors = cerrors;
4148
4149                         // TODO: When in probing mode do IsApplicable only and when called again do VerifyArguments for full error reporting
4150                         best_candidate = r.ResolveMember<MethodSpec> (ec, ref args);
4151                         if (best_candidate == null) {
4152                                 if (!r.BestCandidateIsDynamic)
4153                                         return null;
4154
4155                                 if (simple_name != null && ec.IsStatic)
4156                                         InstanceExpression = ProbeIdenticalTypeName (ec, InstanceExpression, simple_name);
4157
4158                                 return this;
4159                         }
4160
4161                         // Overload resolver had to create a new method group, all checks bellow have already been executed
4162                         if (r.BestCandidateNewMethodGroup != null)
4163                                 return r.BestCandidateNewMethodGroup;
4164
4165                         if (best_candidate.Kind == MemberKind.Method && (restr & OverloadResolver.Restrictions.ProbingOnly) == 0) {
4166                                 if (InstanceExpression != null) {
4167                                         if (best_candidate.IsExtensionMethod && args[0].Expr == InstanceExpression) {
4168                                                 InstanceExpression = null;
4169                                         } else {
4170                                                 if (simple_name != null && best_candidate.IsStatic) {
4171                                                         InstanceExpression = ProbeIdenticalTypeName (ec, InstanceExpression, simple_name);
4172                                                 }
4173
4174                                                 InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup | ResolveFlags.Type);
4175                                         }
4176                                 }
4177
4178                                 ResolveInstanceExpression (ec, null);
4179                         }
4180
4181                         var base_override = CandidateToBaseOverride (ec, best_candidate);
4182                         if (base_override == best_candidate) {
4183                                 best_candidate_return = r.BestCandidateReturnType;
4184                         } else {
4185                                 best_candidate = base_override;
4186                                 best_candidate_return = best_candidate.ReturnType;
4187                         }
4188
4189                         if (best_candidate.IsGeneric && (restr & OverloadResolver.Restrictions.ProbingOnly) == 0 && TypeParameterSpec.HasAnyTypeParameterConstrained (best_candidate.GenericDefinition)) {
4190                                 ConstraintChecker cc = new ConstraintChecker (ec);
4191                                 cc.CheckAll (best_candidate.GetGenericMethodDefinition (), best_candidate.TypeArguments, best_candidate.Constraints, loc);
4192                         }
4193
4194                         //
4195                         // Additional check for possible imported base override method which
4196                         // could not be done during IsOverrideMethodBaseTypeAccessible
4197                         //
4198                         if (best_candidate.IsVirtual && (best_candidate.DeclaringType.Modifiers & Modifiers.PROTECTED) != 0 &&
4199                                 best_candidate.MemberDefinition.IsImported && !best_candidate.DeclaringType.IsAccessible (ec)) {
4200                                 ec.Report.SymbolRelatedToPreviousError (best_candidate);
4201                                 ErrorIsInaccesible (ec, best_candidate.GetSignatureForError (), loc);
4202                         }
4203
4204                         // Speed up the check by not doing it on disallowed targets
4205                         if (best_candidate_return.Kind == MemberKind.Void && best_candidate.IsConditionallyExcluded (ec))
4206                                 Methods = Excluded;
4207
4208                         return this;
4209                 }
4210
4211                 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
4212                 {
4213                         var fe = left as FieldExpr;
4214                         if (fe != null) {
4215                                 //
4216                                 // Using method-group on struct fields makes the struct assigned. I am not sure
4217                                 // why but that's what .net does
4218                                 //
4219                                 fe.Spec.MemberDefinition.SetIsAssigned ();
4220                         }
4221
4222                         simple_name = original;
4223                         return base.ResolveMemberAccess (ec, left, original);
4224                 }
4225
4226                 public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
4227                 {
4228                         if (!HasAccessibleCandidate (rc)) {
4229                                 ErrorIsInaccesible (rc, expr.GetSignatureForError (), loc);
4230                         }
4231
4232                         if (expr.HasTypeArguments) {
4233                                 rc.Report.Error (8084, expr.Location, "An argument to nameof operator cannot be method group with type arguments");
4234                         }
4235                 }
4236
4237                 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
4238                 {
4239                         type_arguments = ta;
4240                 }
4241
4242                 #region IBaseMembersProvider Members
4243
4244                 public virtual IList<MemberSpec> GetBaseMembers (TypeSpec type)
4245                 {
4246                         var baseType = type.BaseType;
4247                         
4248                         IList<MemberSpec> members = baseType == null ? null : MemberCache.FindMembers (baseType, Methods [0].Name, false);
4249
4250                         if (members == null && !type.IsInterface) {
4251                                 var tps = queried_type as TypeParameterSpec;
4252                                 if (tps != null)
4253                                         members = MemberCache.FindInterfaceMembers (tps, Methods [0].Name);
4254                         }
4255
4256                         return members;
4257                 }
4258
4259                 public IParametersMember GetOverrideMemberParameters (MemberSpec member)
4260                 {
4261                         if (queried_type == member.DeclaringType)
4262                                 return null;
4263
4264                         return MemberCache.FindMember (queried_type, new MemberFilter ((MethodSpec) member),
4265                                 BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly) as IParametersMember;
4266                 }
4267
4268                 //
4269                 // Extension methods lookup after ordinary methods candidates failed to apply
4270                 //
4271                 public virtual MethodGroupExpr LookupExtensionMethod (ResolveContext rc)
4272                 {
4273                         if (InstanceExpression == null || InstanceExpression.eclass == ExprClass.Type)
4274                                 return null;
4275
4276                         if (!IsExtensionMethodArgument (InstanceExpression))
4277                                 return null;
4278
4279                         int arity = type_arguments == null ? 0 : type_arguments.Count;
4280                         var methods = rc.LookupExtensionMethod (Methods[0].Name, arity);
4281                         if (methods == null)
4282                                 return null;
4283
4284                         var emg = new ExtensionMethodGroupExpr (methods, InstanceExpression, loc);
4285                         emg.SetTypeArguments (rc, type_arguments);
4286                         emg.ConditionalAccess = ConditionalAccess;
4287                         return emg;
4288                 }
4289
4290                 #endregion
4291         }
4292
4293         struct ConstructorInstanceQualifier : OverloadResolver.IInstanceQualifier
4294         {
4295                 public ConstructorInstanceQualifier (TypeSpec type)
4296                         : this ()
4297                 {
4298                         InstanceType = type;
4299                 }
4300
4301                 public TypeSpec InstanceType { get; private set; }
4302
4303                 public bool CheckProtectedMemberAccess (ResolveContext rc, MemberSpec member)
4304                 {
4305                         return MemberExpr.CheckProtectedMemberAccess (rc, member, InstanceType);
4306                 }
4307         }
4308
4309         public struct OverloadResolver
4310         {
4311                 [Flags]
4312                 public enum Restrictions
4313                 {
4314                         None = 0,
4315                         DelegateInvoke = 1,
4316                         ProbingOnly     = 1 << 1,
4317                         CovariantDelegate = 1 << 2,
4318                         NoBaseMembers = 1 << 3,
4319                         BaseMembersIncluded = 1 << 4,
4320                         GetEnumeratorLookup = 1 << 5
4321                 }
4322
4323                 public interface IBaseMembersProvider
4324                 {
4325                         IList<MemberSpec> GetBaseMembers (TypeSpec baseType);
4326                         IParametersMember GetOverrideMemberParameters (MemberSpec member);
4327                         MethodGroupExpr LookupExtensionMethod (ResolveContext rc);
4328                 }
4329
4330                 public interface IErrorHandler
4331                 {
4332                         bool AmbiguousCandidates (ResolveContext rc, MemberSpec best, MemberSpec ambiguous);
4333                         bool ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument a, int index);
4334                         bool NoArgumentMatch (ResolveContext rc, MemberSpec best);
4335                         bool TypeInferenceFailed (ResolveContext rc, MemberSpec best);
4336                 }
4337
4338                 public interface IInstanceQualifier
4339                 {
4340                         TypeSpec InstanceType { get; }
4341                         bool CheckProtectedMemberAccess (ResolveContext rc, MemberSpec member);
4342                 }
4343
4344                 sealed class NoBaseMembers : IBaseMembersProvider
4345                 {
4346                         public static readonly IBaseMembersProvider Instance = new NoBaseMembers ();
4347
4348                         public IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
4349                         {
4350                                 return null;
4351                         }
4352
4353                         public IParametersMember GetOverrideMemberParameters (MemberSpec member)
4354                         {
4355                                 return null;
4356                         }
4357
4358                         public MethodGroupExpr LookupExtensionMethod (ResolveContext rc)
4359                         {
4360                                 return null;
4361                         }
4362                 }
4363
4364                 struct AmbiguousCandidate
4365                 {
4366                         public readonly MemberSpec Member;
4367                         public readonly bool Expanded;
4368                         public readonly AParametersCollection Parameters;
4369
4370                         public AmbiguousCandidate (MemberSpec member, AParametersCollection parameters, bool expanded)
4371                         {
4372                                 Member = member;
4373                                 Parameters = parameters;
4374                                 Expanded = expanded;
4375                         }
4376                 }
4377
4378                 Location loc;
4379                 IList<MemberSpec> members;
4380                 TypeArguments type_arguments;
4381                 IBaseMembersProvider base_provider;
4382                 IErrorHandler custom_errors;
4383                 IInstanceQualifier instance_qualifier;
4384                 Restrictions restrictions;
4385                 MethodGroupExpr best_candidate_extension_group;
4386                 TypeSpec best_candidate_return_type;
4387
4388                 SessionReportPrinter lambda_conv_msgs;
4389
4390                 public OverloadResolver (IList<MemberSpec> members, Restrictions restrictions, Location loc)
4391                         : this (members, null, restrictions, loc)
4392                 {
4393                 }
4394
4395                 public OverloadResolver (IList<MemberSpec> members, TypeArguments targs, Restrictions restrictions, Location loc)
4396                         : this ()
4397                 {
4398                         if (members == null || members.Count == 0)
4399                                 throw new ArgumentException ("empty members set");
4400
4401                         this.members = members;
4402                         this.loc = loc;
4403                         type_arguments = targs;
4404                         this.restrictions = restrictions;
4405                         if (IsDelegateInvoke)
4406                                 this.restrictions |= Restrictions.NoBaseMembers;
4407
4408                         base_provider = NoBaseMembers.Instance;
4409                 }
4410
4411                 #region Properties
4412
4413                 public IBaseMembersProvider BaseMembersProvider {
4414                         get {
4415                                 return base_provider;
4416                         }
4417                         set {
4418                                 base_provider = value;
4419                         }
4420                 }
4421
4422                 public bool BestCandidateIsDynamic { get; set; }
4423
4424                 //
4425                 // Best candidate was found in newly created MethodGroupExpr, used by extension methods
4426                 //
4427                 public MethodGroupExpr BestCandidateNewMethodGroup {
4428                         get {
4429                                 return best_candidate_extension_group;
4430                         }
4431                 }
4432
4433                 //
4434                 // Return type can be different between best candidate and closest override
4435                 //
4436                 public TypeSpec BestCandidateReturnType {
4437                         get {
4438                                 return best_candidate_return_type;
4439                         }
4440                 }
4441
4442                 public IErrorHandler CustomErrors {
4443                         get {
4444                                 return custom_errors;
4445                         }
4446                         set {
4447                                 custom_errors = value;
4448                         }
4449                 }
4450
4451                 TypeSpec DelegateType {
4452                         get {
4453                                 if ((restrictions & Restrictions.DelegateInvoke) == 0)
4454                                         throw new InternalErrorException ("Not running in delegate mode", loc);
4455
4456                                 return members [0].DeclaringType;
4457                         }
4458                 }
4459
4460                 public IInstanceQualifier InstanceQualifier {
4461                         get {
4462                                 return instance_qualifier;
4463                         }
4464                         set {
4465                                 instance_qualifier = value;
4466                         }
4467                 }
4468
4469                 bool IsProbingOnly {
4470                         get {
4471                                 return (restrictions & Restrictions.ProbingOnly) != 0;
4472                         }
4473                 }
4474
4475                 bool IsDelegateInvoke {
4476                         get {
4477                                 return (restrictions & Restrictions.DelegateInvoke) != 0;
4478                         }
4479                 }
4480
4481                 #endregion
4482
4483                 //
4484                 //  7.4.3.3  Better conversion from expression
4485                 //  Returns :   1    if a->p is better,
4486                 //              2    if a->q is better,
4487                 //              0 if neither is better
4488                 //
4489                 static int BetterExpressionConversion (ResolveContext ec, Argument a, TypeSpec p, TypeSpec q)
4490                 {
4491                         TypeSpec argument_type = a.Type;
4492
4493                         //
4494                         // Exactly matching Expression phase
4495                         //
4496
4497                         //
4498                         // If argument is an anonymous function
4499                         //
4500                         if (argument_type == InternalType.AnonymousMethod && ec.Module.Compiler.Settings.Version > LanguageVersion.ISO_2) {
4501                                 //
4502                                 // p and q are delegate types or expression tree types
4503                                 //
4504                                 if (p.IsExpressionTreeType || q.IsExpressionTreeType) {
4505                                         if (q.MemberDefinition != p.MemberDefinition) {
4506                                                 return 0;
4507                                         }
4508
4509                                         //
4510                                         // Uwrap delegate from Expression<T>
4511                                         //
4512                                         q = TypeManager.GetTypeArguments (q) [0];
4513                                         p = TypeManager.GetTypeArguments (p) [0];
4514                                 }
4515
4516                                 var p_m = Delegate.GetInvokeMethod (p);
4517                                 var q_m = Delegate.GetInvokeMethod (q);
4518
4519                                 //
4520                                 // With identical parameter lists
4521                                 //
4522                                 if (!TypeSpecComparer.Equals (p_m.Parameters.Types, q_m.Parameters.Types))
4523                                         return 0;
4524
4525                                 p = p_m.ReturnType;
4526                                 var orig_q = q;
4527                                 q = q_m.ReturnType;
4528
4529                                 //
4530                                 // if p is void returning, and q has a return type Y, then C2 is the better conversion.
4531                                 //
4532                                 if (p.Kind == MemberKind.Void) {
4533                                         return q.Kind != MemberKind.Void ? 2 : 0;
4534                                 }
4535
4536                                 //
4537                                 // if p has a return type Y, and q is void returning, then C1 is the better conversion.
4538                                 //
4539                                 if (q.Kind == MemberKind.Void) {
4540                                         return p.Kind != MemberKind.Void ? 1 : 0;
4541                                 }
4542
4543                                 var am = (AnonymousMethodExpression)a.Expr;
4544
4545                                 //
4546                                 // When anonymous method is an asynchronous, and P has a return type Task<Y1>, and Q has a return type Task<Y2>
4547                                 // better conversion is performed between underlying types Y1 and Y2
4548                                 //
4549                                 if (p.IsGenericTask || q.IsGenericTask) {
4550                                         if (am.Block.IsAsync && p.IsGenericTask && q.IsGenericTask) {
4551                                                 q = q.TypeArguments [0];
4552                                                 p = p.TypeArguments [0];
4553                                         }
4554                                 }
4555
4556                                 if (q != p) {
4557                                         //
4558                                         // An inferred return type X exists for E in the context of the parameter list, and
4559                                         // an identity conversion exists from X to the return type of D
4560                                         //
4561                                         var inferred_type = am.InferReturnType (ec, null, orig_q);
4562                                         if (inferred_type != null) {
4563                                                 if (inferred_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
4564                                                         inferred_type = ec.BuiltinTypes.Object;
4565
4566                                                 if (inferred_type == p)
4567                                                         return 1;
4568
4569                                                 if (inferred_type == q)
4570                                                         return 2;
4571                                         }
4572                                 }
4573                         }
4574
4575                         if (argument_type == p)
4576                                 return 1;
4577
4578                         if (argument_type == q)
4579                                 return 2;
4580
4581                         return IsBetterConversionTarget (ec, p, q);
4582                 }
4583
4584                 static int IsBetterConversionTarget (ResolveContext rc, TypeSpec p, TypeSpec q)
4585                 {
4586                         if ((p.Kind == MemberKind.Delegate || p.IsExpressionTreeType) && (q.Kind == MemberKind.Delegate || q.IsExpressionTreeType)) {
4587
4588                                 if (p.Kind != MemberKind.Delegate) {
4589                                         p = TypeManager.GetTypeArguments (p) [0];
4590                                 }
4591
4592                                 if (q.Kind != MemberKind.Delegate) {
4593                                         q = TypeManager.GetTypeArguments (q) [0];
4594                                 }
4595
4596                                 var p_m = Delegate.GetInvokeMethod (p);
4597                                 var q_m = Delegate.GetInvokeMethod (q);
4598
4599                                 p = p_m.ReturnType;
4600                                 q = q_m.ReturnType;
4601
4602                                 //
4603                                 // if p is void returning, and q has a return type Y, then C2 is the better conversion.
4604                                 //
4605                                 if (p.Kind == MemberKind.Void) {
4606                                         return q.Kind != MemberKind.Void ? 2 : 0;
4607                                 }
4608
4609                                 //
4610                                 // if p has a return type Y, and q is void returning, then C1 is the better conversion.
4611                                 //
4612                                 if (q.Kind == MemberKind.Void) {
4613                                         return p.Kind != MemberKind.Void ? 1 : 0;
4614                                 }
4615
4616                                 return IsBetterConversionTarget (rc, p, q);
4617                         }
4618
4619                         if (p.IsGenericTask && q.IsGenericTask) {
4620                                 q = q.TypeArguments [0];
4621                                 p = p.TypeArguments [0];
4622                                 return IsBetterConversionTarget (rc, p, q);
4623                         }
4624
4625                         var p_orig = p;
4626                         if (p.IsNullableType) {
4627                                 p = Nullable.NullableInfo.GetUnderlyingType (p);
4628                                 if (!BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (p))
4629                                         return BetterTypeConversionImplicitConversion (rc, p_orig, q);
4630
4631                                 //
4632                                 // Spec expects implicit conversion check between p and q, q and p
4633                                 // to be done before nullable unwrapping but that's expensive operation.
4634                                 // 
4635                                 // Extra manual tweak is needed because BetterTypeConversion works on
4636                                 // unwrapped types
4637                                 //
4638                                 if (p == q)
4639                                         return 2;
4640                         }
4641
4642                         var q_orig = q;
4643                         if (q.IsNullableType) {
4644                                 q = Nullable.NullableInfo.GetUnderlyingType (q);
4645                                 if (!BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (q))
4646                                         return BetterTypeConversionImplicitConversion (rc, p_orig, q_orig);
4647
4648                                 if (q == p)
4649                                         return 1;
4650                         }
4651
4652                         return BetterTypeConversion (rc, p, q);
4653                 }
4654
4655                 //
4656                 // 7.4.3.4  Better conversion from type
4657                 //
4658                 public static int BetterTypeConversion (ResolveContext ec, TypeSpec p, TypeSpec q)
4659                 {
4660                         if (p == null || q == null)
4661                                 throw new InternalErrorException ("BetterTypeConversion got a null conversion");
4662
4663                         switch (p.BuiltinType) {
4664                         case BuiltinTypeSpec.Type.Int:
4665                                 if (q.BuiltinType == BuiltinTypeSpec.Type.UInt || q.BuiltinType == BuiltinTypeSpec.Type.ULong)
4666                                         return 1;
4667                                 break;
4668                         case BuiltinTypeSpec.Type.Long:
4669                                 if (q.BuiltinType == BuiltinTypeSpec.Type.ULong)
4670                                         return 1;
4671                                 break;
4672                         case BuiltinTypeSpec.Type.SByte:
4673                                 switch (q.BuiltinType) {
4674                                 case BuiltinTypeSpec.Type.Byte:
4675                                 case BuiltinTypeSpec.Type.UShort:
4676                                 case BuiltinTypeSpec.Type.UInt:
4677                                 case BuiltinTypeSpec.Type.ULong:
4678                                         return 1;
4679                                 }
4680                                 break;
4681                         case BuiltinTypeSpec.Type.Short:
4682                                 switch (q.BuiltinType) {
4683                                 case BuiltinTypeSpec.Type.UShort:
4684                                 case BuiltinTypeSpec.Type.UInt:
4685                                 case BuiltinTypeSpec.Type.ULong:
4686                                         return 1;
4687                                 }
4688                                 break;
4689                         case BuiltinTypeSpec.Type.Dynamic:
4690                                 // LAMESPEC: Dynamic conversions is not considered
4691                                 p = ec.Module.Compiler.BuiltinTypes.Object;
4692                                 break;
4693                         }
4694
4695                         switch (q.BuiltinType) {
4696                         case BuiltinTypeSpec.Type.Int:
4697                                 if (p.BuiltinType == BuiltinTypeSpec.Type.UInt || p.BuiltinType == BuiltinTypeSpec.Type.ULong)
4698                                         return 2;
4699                                 break;
4700                         case BuiltinTypeSpec.Type.Long:
4701                                 if (p.BuiltinType == BuiltinTypeSpec.Type.ULong)
4702                                         return 2;
4703                                 break;
4704                         case BuiltinTypeSpec.Type.SByte:
4705                                 switch (p.BuiltinType) {
4706                                 case BuiltinTypeSpec.Type.Byte:
4707                                 case BuiltinTypeSpec.Type.UShort:
4708                                 case BuiltinTypeSpec.Type.UInt:
4709                                 case BuiltinTypeSpec.Type.ULong:
4710                                         return 2;
4711                                 }
4712                                 break;
4713                         case BuiltinTypeSpec.Type.Short:
4714                                 switch (p.BuiltinType) {
4715                                 case BuiltinTypeSpec.Type.UShort:
4716                                 case BuiltinTypeSpec.Type.UInt:
4717                                 case BuiltinTypeSpec.Type.ULong:
4718                                         return 2;
4719                                 }
4720                                 break;
4721                         case BuiltinTypeSpec.Type.Dynamic:
4722                                 // LAMESPEC: Dynamic conversions is not considered
4723                                 q = ec.Module.Compiler.BuiltinTypes.Object;
4724                                 break;
4725                         }
4726
4727                         return BetterTypeConversionImplicitConversion (ec, p, q);
4728                 }
4729
4730                 static int BetterTypeConversionImplicitConversion (ResolveContext rc, TypeSpec p, TypeSpec q)
4731                 {
4732                         // TODO: this is expensive
4733                         Expression p_tmp = new EmptyExpression (p);
4734                         Expression q_tmp = new EmptyExpression (q);
4735
4736                         bool p_to_q = Convert.ImplicitConversionExists (rc, p_tmp, q);
4737                         bool q_to_p = Convert.ImplicitConversionExists (rc, q_tmp, p);
4738
4739                         if (p_to_q && !q_to_p)
4740                                 return 1;
4741
4742                         if (q_to_p && !p_to_q)
4743                                 return 2;
4744
4745                         return 0;
4746                 }
4747
4748                 /// <summary>
4749                 ///   Determines "Better function" between candidate
4750                 ///   and the current best match
4751                 /// </summary>
4752                 /// <remarks>
4753                 ///    Returns a boolean indicating :
4754                 ///     false if candidate ain't better
4755                 ///     true  if candidate is better than the current best match
4756                 /// </remarks>
4757                 bool BetterFunction (ResolveContext ec, Arguments args, MemberSpec candidate, AParametersCollection cparam, bool candidate_params,
4758                         MemberSpec best, AParametersCollection bparam, bool best_params)
4759                 {
4760                         AParametersCollection candidate_pd = ((IParametersMember) candidate).Parameters;
4761                         AParametersCollection best_pd = ((IParametersMember) best).Parameters;
4762
4763                         int candidate_better_count = 0;
4764                         int best_better_count = 0;
4765
4766                         bool are_equivalent = true;
4767                         int args_count = args == null ? 0 : args.Count;
4768                         int j = 0;
4769                         Argument a = null;
4770                         TypeSpec ct, bt;
4771                         for (int c_idx = 0, b_idx = 0; j < args_count; ++j, ++c_idx, ++b_idx) {
4772                                 a = args[j];
4773
4774                                 // Default arguments are ignored for better decision
4775                                 if (a.IsDefaultArgument)
4776                                         break;
4777
4778                                 //
4779                                 // When comparing named argument the parameter type index has to be looked up
4780                                 // in original parameter set (override version for virtual members)
4781                                 //
4782                                 NamedArgument na = a as NamedArgument;
4783                                 if (na != null) {
4784                                         int idx = cparam.GetParameterIndexByName (na.Name);
4785                                         ct = candidate_pd.Types[idx];
4786                                         if (candidate_params && candidate_pd.FixedParameters[idx].ModFlags == Parameter.Modifier.PARAMS)
4787                                                 ct = TypeManager.GetElementType (ct);
4788
4789                                         idx = bparam.GetParameterIndexByName (na.Name);
4790                                         bt = best_pd.Types[idx];
4791                                         if (best_params && best_pd.FixedParameters[idx].ModFlags == Parameter.Modifier.PARAMS)
4792                                                 bt = TypeManager.GetElementType (bt);
4793                                 } else {
4794                                         ct = candidate_pd.Types[c_idx];
4795                                         bt = best_pd.Types[b_idx];
4796
4797                                         if (candidate_params && candidate_pd.FixedParameters[c_idx].ModFlags == Parameter.Modifier.PARAMS) {
4798                                                 ct = TypeManager.GetElementType (ct);
4799                                                 --c_idx;
4800                                         }
4801
4802                                         if (best_params && best_pd.FixedParameters[b_idx].ModFlags == Parameter.Modifier.PARAMS) {
4803                                                 bt = TypeManager.GetElementType (bt);
4804                                                 --b_idx;
4805                                         }
4806                                 }
4807
4808                                 if (TypeSpecComparer.IsEqual (ct, bt))
4809                                         continue;
4810
4811                                 are_equivalent = false;
4812                                 int result = BetterExpressionConversion (ec, a, ct, bt);
4813
4814                                 // for each argument, the conversion to 'ct' should be no worse than 
4815                                 // the conversion to 'bt'.
4816                                 if (result == 2) {
4817                                         //
4818                                         // No optional parameters tie breaking rules for delegates overload resolution
4819                                         //
4820                                         if ((restrictions & Restrictions.CovariantDelegate) != 0)
4821                                                 return false;
4822
4823                                         ++best_better_count;
4824                                         continue;
4825                                 }
4826
4827                                 // for at least one argument, the conversion to 'ct' should be better than 
4828                                 // the conversion to 'bt'.
4829                                 if (result != 0)
4830                                         ++candidate_better_count;
4831                         }
4832
4833                         if (candidate_better_count != 0 && best_better_count == 0)
4834                                 return true;
4835
4836                         if (best_better_count > 0 && candidate_better_count == 0)
4837                                 return false;
4838
4839                         //
4840                         // LAMESPEC: Tie-breaking rules for not equivalent parameter types
4841                         //
4842                         if (!are_equivalent) {
4843                                 while (j < args_count && !args [j++].IsDefaultArgument) ;
4844
4845                                 //
4846                                 // A candidate with no default parameters is still better when there
4847                                 // is no better expression conversion and does not have more parameters
4848                                 //
4849                                 if (candidate_pd.Count < best_pd.Count) {
4850                                         if (candidate_params)
4851                                                 return false;
4852                                         
4853                                         if (!candidate_pd.FixedParameters [j - 1].HasDefaultValue)
4854                                                 return true;
4855
4856                                         if (best_pd.FixedParameters [j].HasDefaultValue)
4857                                                 return true;
4858                                         
4859                                 } else if (candidate_pd.Count == best_pd.Count) {
4860                                         if (candidate_params)
4861                                                 return false;
4862
4863                                         if (!candidate_pd.FixedParameters [j - 1].HasDefaultValue && best_pd.FixedParameters [j - 1].HasDefaultValue)
4864                                                 return true;
4865
4866                                         if (candidate_pd.FixedParameters [j - 1].HasDefaultValue && best_pd.HasParams)
4867                                                 return true;
4868                                 }
4869
4870                                 return false;
4871                         }
4872
4873                         //
4874                         // If candidate is applicable in its normal form and best has a params array and is applicable
4875                         // only in its expanded form, then candidate is better
4876                         //
4877                         if (candidate_params != best_params)
4878                                 return !candidate_params;
4879
4880                         //
4881                         // We have not reached end of parameters list due to params or used default parameters
4882                         //
4883                         bool defaults_ambiguity = false;
4884                         while (j < candidate_pd.Count && j < best_pd.Count) {
4885                                 var cand_param = candidate_pd.FixedParameters [j];
4886                                 var best_param = best_pd.FixedParameters [j];
4887
4888                                 if (cand_param.HasDefaultValue != best_param.HasDefaultValue && (!candidate_pd.HasParams || !best_pd.HasParams))
4889                                         return cand_param.HasDefaultValue;
4890
4891                                 defaults_ambiguity = true;
4892                                 if (candidate_pd.Count == best_pd.Count) {
4893                                         //
4894                                         // LAMESPEC:
4895                                         //
4896                                         // void Foo (int i = 0) is better than void Foo (params int[]) for Foo ()
4897                                         // void Foo (string[] s, string value = null) is better than Foo (string s, params string[]) for Foo (null) or Foo ()
4898                                         //
4899                                         if (cand_param.HasDefaultValue) {
4900                                                 ++j;
4901                                                 continue;
4902                                         }
4903
4904                                         break;
4905                                 }
4906
4907                                 //
4908                                 // Neither is better when not all arguments are provided
4909                                 //
4910                                 // void Foo (string s, int i = 0) <-> Foo (string s, int i = 0, int i2 = 0)
4911                                 // void Foo (string s, int i = 0) <-> Foo (string s, byte i = 0)
4912                                 // void Foo (string s, params int[]) <-> Foo (string s, params byte[])
4913                                 //
4914                                 ++j;
4915                         }
4916
4917                         if (candidate_pd.Count != best_pd.Count) {
4918                                 if (defaults_ambiguity && best_pd.Count - 1 == j)
4919                                         return best_pd.HasParams;
4920
4921                                 return candidate_pd.Count < best_pd.Count;
4922                         }
4923
4924                         //
4925                         // One is a non-generic method and second is a generic method, then non-generic is better
4926                         //
4927                         if (best.IsGeneric != candidate.IsGeneric)
4928                                 return best.IsGeneric;
4929
4930                         //
4931                         // Both methods have the same number of parameters, and the parameters have equal types
4932                         // Pick the "more specific" signature using rules over original (non-inflated) types
4933                         //
4934                         var candidate_def_pd = ((IParametersMember) candidate.MemberDefinition).Parameters;
4935                         var best_def_pd = ((IParametersMember) best.MemberDefinition).Parameters;
4936
4937                         bool specific_at_least_once = false;
4938                         for (j = 0; j < args_count; ++j) {
4939                                 NamedArgument na = args_count == 0 ? null : args [j] as NamedArgument;
4940                                 if (na != null) {
4941                                         ct = candidate_def_pd.Types[cparam.GetParameterIndexByName (na.Name)];
4942                                         bt = best_def_pd.Types[bparam.GetParameterIndexByName (na.Name)];
4943                                 } else {
4944                                         ct = candidate_def_pd.Types[j];
4945                                         bt = best_def_pd.Types[j];
4946                                 }
4947
4948                                 if (ct == bt)
4949                                         continue;
4950                                 TypeSpec specific = MoreSpecific (ct, bt);
4951                                 if (specific == bt)
4952                                         return false;
4953                                 if (specific == ct)
4954                                         specific_at_least_once = true;
4955                         }
4956
4957                         if (specific_at_least_once)
4958                                 return true;
4959
4960                         return false;
4961                 }
4962
4963                 static bool CheckInflatedArguments (MethodSpec ms)
4964                 {
4965                         if (!TypeParameterSpec.HasAnyTypeParameterTypeConstrained (ms.GenericDefinition))
4966                                 return true;
4967
4968                         // Setup constraint checker for probing only
4969                         ConstraintChecker cc = new ConstraintChecker (null);
4970
4971                         var mp = ms.Parameters.Types;
4972                         for (int i = 0; i < mp.Length; ++i) {
4973                                 var type = mp[i] as InflatedTypeSpec;
4974                                 if (type == null)
4975                                         continue;
4976
4977                                 var targs = type.TypeArguments;
4978                                 if (targs.Length == 0)
4979                                         continue;
4980
4981                                 // TODO: Checking inflated MVAR arguments should be enough
4982                                 if (!cc.CheckAll (type.GetDefinition (), targs, type.Constraints, Location.Null))
4983                                         return false;
4984                         }
4985
4986                         return true;
4987                 }
4988
4989                 public static void Error_ConstructorMismatch (ResolveContext rc, TypeSpec type, int argCount, Location loc)
4990                 {
4991                         rc.Report.Error (1729, loc,
4992                                 "The type `{0}' does not contain a constructor that takes `{1}' arguments",
4993                                 type.GetSignatureForError (), argCount.ToString ());
4994                 }
4995
4996                 //
4997                 // Determines if the candidate method is applicable to the given set of arguments
4998                 // There could be two different set of parameters for same candidate where one
4999                 // is the closest override for default values and named arguments checks and second
5000                 // one being the virtual base for the parameter types and modifiers.
5001                 //
5002                 // A return value rates candidate method compatibility,
5003                 // -1 = fatal error
5004                 // 0 = the best, int.MaxValue = the worst
5005                 //
5006                 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)
5007                 {
5008                         //
5009                         // Each step has allocated 10 values, it can overflow for
5010                         // more than 10 arguments but that's ok as it's used for
5011                         // better error reporting only
5012                         //
5013                         const int ArgumentCountMismatch         = 1000000000;
5014                         const int NamedArgumentsMismatch        = 100000000;
5015                         const int DefaultArgumentMismatch       = 10000000;
5016                         const int UnexpectedTypeArguments       = 1000000;
5017                         const int TypeArgumentsMismatch         = 100000;
5018                         const int InflatedTypesMismatch         = 10000;
5019
5020                         // Parameters of most-derived type used mainly for named and optional parameters
5021                         var pd = pm.Parameters;
5022
5023                         // Used for params modifier only, that's legacy of C# 1.0 which uses base type for
5024                         // params modifier instead of most-derived type
5025                         var cpd = ((IParametersMember) candidate).Parameters;
5026                         int param_count = pd.Count;
5027                         int optional_count = 0;
5028                         int score;
5029                         Arguments orig_args = arguments;
5030
5031                         if (arg_count != param_count) {
5032                                 //
5033                                 // No arguments expansion when doing exact match for delegates
5034                                 //
5035                                 if ((restrictions & Restrictions.CovariantDelegate) == 0) {
5036                                         for (int i = 0; i < pd.Count; ++i) {
5037                                                 if (pd.FixedParameters[i].HasDefaultValue) {
5038                                                         optional_count = pd.Count - i;
5039                                                         break;
5040                                                 }
5041                                         }
5042                                 }
5043
5044                                 if (optional_count != 0) {
5045                                         // Readjust expected number when params used
5046                                         if (cpd.HasParams) {
5047                                                 optional_count--;
5048                                                 if (arg_count < param_count)
5049                                                         param_count--;
5050                                         } else if (arg_count > param_count) {
5051                                                 int args_gap = System.Math.Abs (arg_count - param_count);
5052                                                 return ArgumentCountMismatch + args_gap;
5053                                         } else if (arg_count < param_count - optional_count) {
5054                                                 int args_gap = System.Math.Abs (param_count - optional_count - arg_count);
5055                                                 return ArgumentCountMismatch + args_gap;
5056                                         }
5057                                 } else if (arg_count != param_count) {
5058                                         int args_gap = System.Math.Abs (arg_count - param_count);
5059                                         if (!cpd.HasParams)
5060                                                 return ArgumentCountMismatch + args_gap;
5061                                         if (arg_count < param_count - 1)
5062                                                 return ArgumentCountMismatch + args_gap;
5063                                 }
5064
5065                                 // Resize to fit optional arguments
5066                                 if (optional_count != 0) {
5067                                         if (arguments == null) {
5068                                                 arguments = new Arguments (optional_count);
5069                                         } else {
5070                                                 // Have to create a new container, so the next run can do same
5071                                                 var resized = new Arguments (param_count);
5072                                                 resized.AddRange (arguments);
5073                                                 arguments = resized;
5074                                         }
5075
5076                                         for (int i = arg_count; i < param_count; ++i)
5077                                                 arguments.Add (null);
5078                                 }
5079                         }
5080
5081                         if (arg_count > 0) {
5082                                 //
5083                                 // Shuffle named arguments to the right positions if there are any
5084                                 //
5085                                 if (arguments[arg_count - 1] is NamedArgument) {
5086                                         arg_count = arguments.Count;
5087
5088                                         for (int i = 0; i < arg_count; ++i) {
5089                                                 bool arg_moved = false;
5090                                                 while (true) {
5091                                                         NamedArgument na = arguments[i] as NamedArgument;
5092                                                         if (na == null)
5093                                                                 break;
5094
5095                                                         int index = pd.GetParameterIndexByName (na.Name);
5096
5097                                                         // Named parameter not found
5098                                                         if (index < 0)
5099                                                                 return NamedArgumentsMismatch - i;
5100
5101                                                         // already reordered
5102                                                         if (index == i)
5103                                                                 break;
5104
5105                                                         Argument temp;
5106                                                         if (index >= param_count) {
5107                                                                 // When using parameters which should not be available to the user
5108                                                                 if ((cpd.FixedParameters[index].ModFlags & Parameter.Modifier.PARAMS) == 0)
5109                                                                         break;
5110
5111                                                                 arguments.Add (null);
5112                                                                 ++arg_count;
5113                                                                 temp = null;
5114                                                         } else {
5115                                                                 if (index == arg_count)
5116                                                                         return NamedArgumentsMismatch - i - 1;
5117
5118                                                                 temp = arguments [index];
5119
5120                                                                 // The slot has been taken by positional argument
5121                                                                 if (temp != null && !(temp is NamedArgument))
5122                                                                         return NamedArgumentsMismatch - i - 1;
5123                                                         }
5124
5125                                                         if (!arg_moved) {
5126                                                                 arguments = arguments.MarkOrderedArgument (na);
5127                                                                 arg_moved = true;
5128                                                         }
5129
5130                                                         if (arguments == orig_args) {
5131                                                                 arguments = new Arguments (orig_args.Count);
5132                                                                 arguments.AddRange (orig_args);
5133                                                         }
5134
5135                                                         arguments[index] = arguments[i];
5136                                                         arguments[i] = temp;
5137
5138                                                         if (temp == null)
5139                                                                 break;
5140                                                 }
5141                                         }
5142                                 } else {
5143                                         arg_count = arguments.Count;
5144                                 }
5145                         } else if (arguments != null) {
5146                                 arg_count = arguments.Count;
5147                         }
5148
5149                         //
5150                         // Don't do any expensive checks when the candidate cannot succeed
5151                         //
5152                         if (arg_count != param_count && !cpd.HasParams)
5153                                 return DefaultArgumentMismatch - System.Math.Abs (param_count - arg_count);
5154
5155                         var dep = candidate.GetMissingDependencies ();
5156                         if (dep != null) {
5157                                 ImportedTypeDefinition.Error_MissingDependency (ec, dep, loc);
5158                                 return -1;
5159                         }
5160
5161                         //
5162                         // 1. Handle generic method using type arguments when specified or type inference
5163                         //
5164                         TypeSpec[] ptypes;
5165                         var ms = candidate as MethodSpec;
5166                         if (ms != null && ms.IsGeneric) {
5167                                 if (type_arguments != null) {
5168                                         var g_args_count = ms.Arity;
5169                                         if (g_args_count != type_arguments.Count)
5170                                                 return TypeArgumentsMismatch - System.Math.Abs (type_arguments.Count - g_args_count);
5171
5172                                         if (type_arguments.Arguments != null)
5173                                                 ms = ms.MakeGenericMethod (ec, type_arguments.Arguments);
5174                                 } else {
5175                                         //
5176                                         // Deploy custom error reporting for infered anonymous expression or lambda methods. When
5177                                         // probing lambda methods keep all errors reported in separate set and once we are done and no best
5178                                         // candidate was found use the set to report more details about what was wrong with lambda body.
5179                                         // The general idea is to distinguish between code errors and errors caused by
5180                                         // trial-and-error type inference
5181                                         //
5182                                         if (lambda_conv_msgs == null) {
5183                                                 for (int i = 0; i < arg_count; i++) {
5184                                                         Argument a = arguments[i];
5185                                                         if (a == null)
5186                                                                 continue;
5187
5188                                                         var am = a.Expr as AnonymousMethodExpression;
5189                                                         if (am != null) {
5190                                                                 if (lambda_conv_msgs == null)
5191                                                                         lambda_conv_msgs = new SessionReportPrinter ();
5192
5193                                                                 am.TypeInferenceReportPrinter = lambda_conv_msgs;
5194                                                         }
5195                                                 }
5196                                         }
5197
5198                                         var ti = new TypeInference (arguments);
5199                                         TypeSpec[] i_args = ti.InferMethodArguments (ec, ms);
5200
5201                                         if (i_args == null)
5202                                                 return TypeArgumentsMismatch - ti.InferenceScore;
5203
5204                                         //
5205                                         // Clear any error messages when the result was success
5206                                         //
5207                                         if (lambda_conv_msgs != null)
5208                                                 lambda_conv_msgs.ClearSession ();
5209
5210                                         if (i_args.Length != 0) {
5211                                                 if (!errorMode) {
5212                                                         for (int i = 0; i < i_args.Length; ++i) {
5213                                                                 var ta = i_args [i];
5214                                                                 if (!ta.IsAccessible (ec))
5215                                                                         return TypeArgumentsMismatch - i;
5216                                                         }
5217                                                 }
5218
5219                                                 ms = ms.MakeGenericMethod (ec, i_args);
5220                                         }
5221                                 }
5222
5223                                 //
5224                                 // Type arguments constraints have to match for the method to be applicable
5225                                 //
5226                                 if (!CheckInflatedArguments (ms)) {
5227                                         candidate = ms;
5228                                         return InflatedTypesMismatch;
5229                                 }
5230
5231                                 //
5232                                 // We have a generic return type and at same time the method is override which
5233                                 // means we have to also inflate override return type in case the candidate is
5234                                 // best candidate and override return type is different to base return type.
5235                                 // 
5236                                 // virtual Foo<T, object> with override Foo<T, dynamic>
5237                                 //
5238                                 if (candidate != pm) {
5239                                         MethodSpec override_ms = (MethodSpec) pm;
5240                                         var inflator = new TypeParameterInflator (ec, ms.DeclaringType, override_ms.GenericDefinition.TypeParameters, ms.TypeArguments);
5241                                         returnType = inflator.Inflate (returnType);
5242                                 } else {
5243                                         returnType = ms.ReturnType;
5244                                 }
5245
5246                                 candidate = ms;
5247                                 pd = ms.Parameters;
5248                                 ptypes = pd.Types;
5249                         } else {
5250                                 if (type_arguments != null)
5251                                         return UnexpectedTypeArguments;
5252
5253                                 ptypes = cpd.Types;
5254                         }
5255
5256                         //
5257                         // 2. Each argument has to be implicitly convertible to method parameter
5258                         //
5259                         Parameter.Modifier p_mod = 0;
5260                         TypeSpec pt = null;
5261
5262                         for (int i = 0; i < arg_count; i++) {
5263                                 Argument a = arguments[i];
5264                                 if (a == null) {
5265                                         var fp = pd.FixedParameters[i];
5266                                         if (!fp.HasDefaultValue) {
5267                                                 arguments = orig_args;
5268                                                 return arg_count * 2 + 2;
5269                                         }
5270
5271                                         //
5272                                         // Get the default value expression, we can use the same expression
5273                                         // if the type matches
5274                                         //
5275                                         Expression e = fp.DefaultValue;
5276                                         if (e != null) {
5277                                                 e = ResolveDefaultValueArgument (ec, ptypes[i], e, loc);
5278                                                 if (e == null) {
5279                                                         // Restore for possible error reporting
5280                                                         for (int ii = i; ii < arg_count; ++ii)
5281                                                                 arguments.RemoveAt (i);
5282
5283                                                         return (arg_count - i) * 2 + 1;
5284                                                 }
5285                                         }
5286
5287                                         if ((fp.ModFlags & Parameter.Modifier.CallerMask) != 0) {
5288                                                 //
5289                                                 // LAMESPEC: Attributes can be mixed together with build-in priority
5290                                                 //
5291                                                 if ((fp.ModFlags & Parameter.Modifier.CallerLineNumber) != 0) {
5292                                                         e = new IntLiteral (ec.BuiltinTypes, loc.Row, loc);
5293                                                 } else if ((fp.ModFlags & Parameter.Modifier.CallerFilePath) != 0) {
5294                                                         e = new StringLiteral (ec.BuiltinTypes, loc.SourceFile.GetFullPathName (ec.Module.Compiler.Settings.PathMap), loc);
5295                                                 } else if (ec.MemberContext.CurrentMemberDefinition != null) {
5296                                                         e = new StringLiteral (ec.BuiltinTypes, ec.MemberContext.CurrentMemberDefinition.GetCallerMemberName (), loc);
5297                                                 }
5298                                         }
5299
5300                                         arguments[i] = new Argument (e, Argument.AType.Default);
5301                                         continue;
5302                                 }
5303
5304                                 if (p_mod != Parameter.Modifier.PARAMS) {
5305                                         p_mod = (pd.FixedParameters[i].ModFlags & ~Parameter.Modifier.PARAMS) | (cpd.FixedParameters[i].ModFlags & Parameter.Modifier.PARAMS);
5306                                         pt = ptypes [i];
5307                                 } else if (!params_expanded_form) {
5308                                         params_expanded_form = true;
5309                                         pt = ((ElementTypeSpec) pt).Element;
5310                                         i -= 2;
5311                                         continue;
5312                                 }
5313
5314                                 score = 1;
5315                                 if (!params_expanded_form) {
5316                                         if (a.IsExtensionType) {
5317                                                 if (ExtensionMethodGroupExpr.IsExtensionTypeCompatible (a.Type, pt)) {
5318                                                         score = 0;
5319                                                         continue;
5320                                                 }
5321                                         } else {
5322                                                 score = IsArgumentCompatible (ec, a, p_mod, pt);
5323
5324                                                 if (score < 0)
5325                                                         dynamicArgument = true;
5326                                         }
5327                                 }
5328
5329                                 //
5330                                 // It can be applicable in expanded form (when not doing exact match like for delegates)
5331                                 //
5332                                 if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && (restrictions & Restrictions.CovariantDelegate) == 0) {
5333                                         if (!params_expanded_form) {
5334                                                 pt = ((ElementTypeSpec) pt).Element;
5335                                         }
5336
5337                                         if (score > 0)
5338                                                 score = IsArgumentCompatible (ec, a, Parameter.Modifier.NONE, pt);
5339
5340                                         if (score < 0) {
5341                                                 params_expanded_form = true;
5342                                                 dynamicArgument = true;
5343                                         } else if (score == 0 || arg_count > pd.Count) {
5344                                                 params_expanded_form = true;
5345                                         }
5346                                 }
5347
5348                                 if (score > 0) {
5349                                         if (params_expanded_form)
5350                                                 ++score;
5351                                         return (arg_count - i) * 2 + score;
5352                                 }
5353                         }
5354
5355                         //
5356                         // Restore original arguments for dynamic binder to keep the intention of original source code
5357                         //
5358                         if (dynamicArgument)
5359                                 arguments = orig_args;
5360
5361                         return 0;
5362                 }
5363
5364                 public static Expression ResolveDefaultValueArgument (ResolveContext ec, TypeSpec ptype, Expression e, Location loc)
5365                 {
5366                         if (e is Constant && e.Type == ptype)
5367                                 return e;
5368
5369                         //
5370                         // LAMESPEC: No idea what the exact rules are for System.Reflection.Missing.Value instead of null
5371                         //
5372                         if (e == EmptyExpression.MissingValue && (ptype.BuiltinType == BuiltinTypeSpec.Type.Object || ptype.BuiltinType == BuiltinTypeSpec.Type.Dynamic)) {
5373                                 e = new MemberAccess (new MemberAccess (new MemberAccess (
5374                                         new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Reflection", loc), "Missing", loc), "Value", loc);
5375                         } else if (e is Constant) {
5376                                 //
5377                                 // Handles int to int? conversions, DefaultParameterValue check
5378                                 //
5379                                 e = Convert.ImplicitConversionStandard (ec, e, ptype, loc);
5380                                 if (e == null)
5381                                         return null;
5382                         } else {
5383                                 e = new DefaultValueExpression (new TypeExpression (ptype, loc), loc);
5384                         }
5385
5386                         return e.Resolve (ec);
5387                 }
5388
5389                 //
5390                 // Tests argument compatibility with the parameter
5391                 // The possible return values are
5392                 // 0 - success
5393                 // 1 - modifier mismatch
5394                 // 2 - type mismatch
5395                 // -1 - dynamic binding required
5396                 //
5397                 int IsArgumentCompatible (ResolveContext ec, Argument argument, Parameter.Modifier param_mod, TypeSpec parameter)
5398                 {
5399                         //
5400                         // Types have to be identical when ref or out modifer
5401                         // is used and argument is not of dynamic type
5402                         //
5403                         if (((argument.Modifier | param_mod) & Parameter.Modifier.RefOutMask) != 0) {
5404                                 var arg_type = argument.Type;
5405
5406                                 if ((argument.Modifier & Parameter.Modifier.RefOutMask) != (param_mod & Parameter.Modifier.RefOutMask)) {
5407                                         //
5408                                         // Using dynamic for ref/out parameter can still succeed at runtime
5409                                         //
5410                                         if (arg_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (argument.Modifier & Parameter.Modifier.RefOutMask) == 0 && (restrictions & Restrictions.CovariantDelegate) == 0)
5411                                                 return -1;
5412
5413                                         return 1;
5414                                 }
5415
5416                                 if (arg_type != parameter) {
5417                                         if (arg_type == InternalType.VarOutType)
5418                                                 return 0;
5419
5420                                         //
5421                                         // Do full equality check after quick path
5422                                         //
5423                                         if (!TypeSpecComparer.IsEqual (arg_type, parameter)) {
5424                                                 //
5425                                                 // Using dynamic for ref/out parameter can still succeed at runtime
5426                                                 //
5427                                                 if (arg_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (argument.Modifier & Parameter.Modifier.RefOutMask) == 0 && (restrictions & Restrictions.CovariantDelegate) == 0)
5428                                                         return -1;
5429
5430                                                 return 2;
5431                                         }
5432                                 }
5433
5434                         } else {
5435                                 if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (restrictions & Restrictions.CovariantDelegate) == 0)
5436                                         return -1;
5437
5438                                 //
5439                                 // Use implicit conversion in all modes to return same candidates when the expression
5440                                 // is used as argument or delegate conversion
5441                                 //
5442                                 if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) {
5443                                         return parameter.IsDelegate && argument.Expr is AnonymousMethodExpression ? 2 : 3;
5444                                 }
5445                         }
5446
5447                         return 0;
5448                 }
5449
5450                 static TypeSpec MoreSpecific (TypeSpec p, TypeSpec q)
5451                 {
5452                         if (p.IsGenericParameter != q.IsGenericParameter)
5453                                 return p.IsGenericParameter ? q : p;
5454
5455                         var ac_p = p as ArrayContainer;
5456                         if (ac_p != null) {
5457                                 var ac_q = q as ArrayContainer;
5458                                 if (ac_q == null)
5459                                         return null;
5460
5461                                 TypeSpec specific = MoreSpecific (ac_p.Element, ac_q.Element);
5462                                 if (specific == ac_p.Element)
5463                                         return p;
5464                                 if (specific == ac_q.Element)
5465                                         return q;
5466
5467                                 return null;
5468                         }
5469
5470                         if (p.IsGeneric && q.IsGeneric) {
5471                                 var pargs = p.TypeArguments;
5472                                 var qargs = q.TypeArguments;
5473
5474                                 bool p_specific_at_least_once = false;
5475                                 bool q_specific_at_least_once = false;
5476
5477                                 for (int i = 0; i < pargs.Length; i++) {
5478                                         TypeSpec specific = MoreSpecific (pargs [i], qargs [i]);
5479                                         if (specific == pargs [i])
5480                                                 p_specific_at_least_once = true;
5481                                         if (specific == qargs [i])
5482                                                 q_specific_at_least_once = true;
5483                                 }
5484
5485                                 if (p_specific_at_least_once && !q_specific_at_least_once)
5486                                         return p;
5487                                 if (!p_specific_at_least_once && q_specific_at_least_once)
5488                                         return q;
5489                         }
5490
5491                         return null;
5492                 }
5493
5494                 //
5495                 // Find the best method from candidate list
5496                 //
5497                 public T ResolveMember<T> (ResolveContext rc, ref Arguments args) where T : MemberSpec, IParametersMember
5498                 {
5499                         List<AmbiguousCandidate> ambiguous_candidates = null;
5500
5501                         MemberSpec best_candidate;
5502                         Arguments best_candidate_args = null;
5503                         bool best_candidate_params = false;
5504                         bool best_candidate_dynamic = false;
5505                         int best_candidate_rate;
5506                         IParametersMember best_parameter_member = null;
5507
5508                         int args_count = args != null ? args.Count : 0;
5509
5510                         Arguments candidate_args = args;
5511                         bool error_mode = false;
5512                         MemberSpec invocable_member = null;
5513                         int applicable_candidates = 0;
5514
5515                         while (true) {
5516                                 best_candidate = null;
5517                                 best_candidate_rate = int.MaxValue;
5518
5519                                 var type_members = members;
5520                                 do {
5521                                         for (int i = 0; i < type_members.Count; ++i) {
5522                                                 var member = type_members[i];
5523
5524                                                 //
5525                                                 // Methods in a base class are not candidates if any method in a derived
5526                                                 // class is applicable
5527                                                 //
5528                                                 if ((member.Modifiers & Modifiers.OVERRIDE) != 0)
5529                                                         continue;
5530
5531                                                 if (!error_mode) {
5532                                                         if (!member.IsAccessible (rc))
5533                                                                 continue;
5534
5535                                                         if (rc.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc))
5536                                                                 continue;
5537
5538                                                         if ((member.Modifiers & (Modifiers.PROTECTED | Modifiers.STATIC)) == Modifiers.PROTECTED &&
5539                                                                 instance_qualifier != null && !instance_qualifier.CheckProtectedMemberAccess (rc, member)) {
5540                                                                 continue;
5541                                                         }
5542                                                 }
5543
5544                                                 IParametersMember pm = member as IParametersMember;
5545                                                 if (pm == null) {
5546                                                         //
5547                                                         // Will use it later to report ambiguity between best method and invocable member
5548                                                         //
5549                                                         if (Invocation.IsMemberInvocable (member))
5550                                                                 invocable_member = member;
5551
5552                                                         continue;
5553                                                 }
5554
5555                                                 //
5556                                                 // Overload resolution is looking for base member but using parameter names
5557                                                 // and default values from the closest member. That means to do expensive lookup
5558                                                 // for the closest override for virtual or abstract members
5559                                                 //
5560                                                 if ((member.Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
5561                                                         var override_params = base_provider.GetOverrideMemberParameters (member);
5562                                                         if (override_params != null)
5563                                                                 pm = override_params;
5564                                                 }
5565
5566                                                 //
5567                                                 // Check if the member candidate is applicable
5568                                                 //
5569                                                 bool params_expanded_form = false;
5570                                                 bool dynamic_argument = false;
5571                                                 TypeSpec rt = pm.MemberType;
5572                                                 int candidate_rate = IsApplicable (rc, ref candidate_args, args_count, ref member, pm, ref params_expanded_form, ref dynamic_argument, ref rt, error_mode);
5573
5574                                                 if (lambda_conv_msgs != null)
5575                                                         lambda_conv_msgs.EndSession ();
5576
5577                                                 //
5578                                                 // How does it score compare to others
5579                                                 //
5580                                                 if (candidate_rate < best_candidate_rate) {
5581
5582                                                         // Fatal error (missing dependency), cannot continue
5583                                                         if (candidate_rate < 0)
5584                                                                 return null;
5585
5586                                                         applicable_candidates = 1;
5587                                                         if ((restrictions & Restrictions.GetEnumeratorLookup) != 0 && candidate_args.Count != 0) {
5588                                                                 // Only parameterless methods are considered
5589                                                         } else {
5590                                                                 best_candidate_rate = candidate_rate;
5591                                                                 best_candidate = member;
5592                                                                 best_candidate_args = candidate_args;
5593                                                                 best_candidate_params = params_expanded_form;
5594                                                                 best_candidate_dynamic = dynamic_argument;
5595                                                                 best_parameter_member = pm;
5596                                                                 best_candidate_return_type = rt;
5597                                                         }
5598                                                 } else if (candidate_rate == 0) {
5599                                                         //
5600                                                         // The member look is done per type for most operations but sometimes
5601                                                         // it's not possible like for binary operators overload because they
5602                                                         // are unioned between 2 sides
5603                                                         //
5604                                                         if ((restrictions & Restrictions.BaseMembersIncluded) != 0) {
5605                                                                 if (TypeSpec.IsBaseClass (best_candidate.DeclaringType, member.DeclaringType, true))
5606                                                                         continue;
5607                                                         }
5608
5609                                                         ++applicable_candidates;
5610                                                         bool is_better;
5611                                                         if (best_candidate.DeclaringType.IsInterface && member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) {
5612                                                                 //
5613                                                                 // We pack all interface members into top level type which makes the overload resolution
5614                                                                 // more complicated for interfaces. We compensate it by removing methods with same
5615                                                                 // signature when building the cache hence this path should not really be hit often
5616                                                                 //
5617                                                                 // Example:
5618                                                                 // interface IA { void Foo (int arg); }
5619                                                                 // interface IB : IA { void Foo (params int[] args); }
5620                                                                 //
5621                                                                 // IB::Foo is the best overload when calling IB.Foo (1)
5622                                                                 //
5623                                                                 is_better = true;
5624                                                                 if (ambiguous_candidates != null) {
5625                                                                         foreach (var amb_cand in ambiguous_candidates) {
5626                                                                                 if (member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) {
5627                                                                                         continue;
5628                                                                                 }
5629
5630                                                                                 is_better = false;
5631                                                                                 break;
5632                                                                         }
5633
5634                                                                         if (is_better)
5635                                                                                 ambiguous_candidates = null;
5636                                                                 }
5637                                                         } else {
5638                                                                 // Is the new candidate better
5639                                                                 is_better = BetterFunction (rc, candidate_args, member, pm.Parameters, params_expanded_form, best_candidate, best_parameter_member.Parameters, best_candidate_params);
5640                                                         }
5641
5642                                                         if (is_better) {
5643                                                                 best_candidate = member;
5644                                                                 best_candidate_args = candidate_args;
5645                                                                 best_candidate_params = params_expanded_form;
5646                                                                 best_candidate_dynamic = dynamic_argument;
5647                                                                 best_parameter_member = pm;
5648                                                                 best_candidate_return_type = rt;
5649                                                         } else {
5650                                                                 // It's not better but any other found later could be but we are not sure yet
5651                                                                 if (ambiguous_candidates == null)
5652                                                                         ambiguous_candidates = new List<AmbiguousCandidate> ();
5653
5654                                                                 ambiguous_candidates.Add (new AmbiguousCandidate (member, pm.Parameters, params_expanded_form));
5655                                                         }
5656                                                 }
5657
5658                                                 // Restore expanded arguments
5659                                                 candidate_args = args;
5660                                         }
5661                                 } while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType)) != null);
5662
5663                                 //
5664                                 // We've found exact match
5665                                 //
5666                                 if (best_candidate_rate == 0)
5667                                         break;
5668
5669                                 //
5670                                 // Try extension methods lookup when no ordinary method match was found and provider enables it
5671                                 //
5672                                 if (!error_mode) {
5673                                         var emg = base_provider.LookupExtensionMethod (rc);
5674                                         if (emg != null) {
5675                                                 emg = emg.OverloadResolve (rc, ref args, null, restrictions);
5676                                                 if (emg != null) {
5677                                                         best_candidate_extension_group = emg;
5678                                                         return (T) (MemberSpec) emg.BestCandidate;
5679                                                 }
5680                                         }
5681                                 }
5682
5683                                 // Don't run expensive error reporting mode for probing
5684                                 if (IsProbingOnly)
5685                                         return null;
5686
5687                                 if (error_mode)
5688                                         break;
5689
5690                                 if (lambda_conv_msgs != null && !lambda_conv_msgs.IsEmpty)
5691                                         break;
5692
5693                                 lambda_conv_msgs = null;
5694                                 error_mode = true;
5695                         }
5696
5697                         //
5698                         // No best member match found, report an error
5699                         //
5700                         if (best_candidate_rate != 0 || error_mode) {
5701                                 ReportOverloadError (rc, best_candidate, best_parameter_member, best_candidate_args, best_candidate_params);
5702                                 return null;
5703                         }
5704
5705                         if (best_candidate_dynamic) {
5706                                 if (args[0].IsExtensionType) {
5707                                         rc.Report.Error (1973, loc,
5708                                                 "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",
5709                                                 args [0].Type.GetSignatureForError (), best_candidate.Name, best_candidate.GetSignatureForError ());
5710                                 }
5711
5712                                 //
5713                                 // Check type constraints only when explicit type arguments are used
5714                                 //
5715                                 if (applicable_candidates == 1 && best_candidate.IsGeneric && type_arguments != null) {
5716                                         MethodSpec bc = best_candidate as MethodSpec;
5717                                         if (bc != null && TypeParameterSpec.HasAnyTypeParameterConstrained (bc.GenericDefinition)) {
5718                                                 ConstraintChecker cc = new ConstraintChecker (rc);
5719                                                 cc.CheckAll (bc.GetGenericMethodDefinition (), bc.TypeArguments, bc.Constraints, loc);
5720                                         }
5721                                 }
5722
5723                                 BestCandidateIsDynamic = true;
5724                                 return null;
5725                         }
5726
5727                         //
5728                         // These flags indicates we are running delegate probing conversion. No need to
5729                         // do more expensive checks
5730                         // 
5731                         if ((restrictions & (Restrictions.ProbingOnly | Restrictions.CovariantDelegate)) == (Restrictions.CovariantDelegate | Restrictions.ProbingOnly))
5732                                 return (T) best_candidate;
5733
5734                         if (ambiguous_candidates != null) {
5735                                 //
5736                                 // Now check that there are no ambiguities i.e the selected method
5737                                 // should be better than all the others
5738                                 //
5739                                 for (int ix = 0; ix < ambiguous_candidates.Count; ix++) {
5740                                         var candidate = ambiguous_candidates [ix];
5741
5742                                         if (!BetterFunction (rc, best_candidate_args, best_candidate, best_parameter_member.Parameters, best_candidate_params, candidate.Member, candidate.Parameters, candidate.Expanded)) {
5743                                                 var ambiguous = candidate.Member;
5744                                                 if (custom_errors == null || !custom_errors.AmbiguousCandidates (rc, best_candidate, ambiguous)) {
5745                                                         rc.Report.SymbolRelatedToPreviousError (best_candidate);
5746                                                         rc.Report.SymbolRelatedToPreviousError (ambiguous);
5747                                                         rc.Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'",
5748                                                                 best_candidate.GetSignatureForError (), ambiguous.GetSignatureForError ());
5749                                                 }
5750
5751                                                 return (T) best_candidate;
5752                                         }
5753                                 }
5754                         }
5755
5756                         if (invocable_member != null && !IsProbingOnly) {
5757                                 rc.Report.SymbolRelatedToPreviousError (best_candidate);
5758                                 rc.Report.SymbolRelatedToPreviousError (invocable_member);
5759                                 rc.Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and invocable non-method `{1}'. Using method group",
5760                                         best_candidate.GetSignatureForError (), invocable_member.GetSignatureForError ());
5761                         }
5762
5763                         //
5764                         // And now check if the arguments are all
5765                         // compatible, perform conversions if
5766                         // necessary etc. and return if everything is
5767                         // all right
5768                         //
5769                         if (!VerifyArguments (rc, ref best_candidate_args, best_candidate, best_parameter_member, best_candidate_params))
5770                                 return null;
5771
5772                         if (best_candidate == null)
5773                                 return null;
5774
5775                         //
5776                         // Don't run possibly expensive checks in probing mode
5777                         //
5778                         if (!IsProbingOnly && !rc.IsInProbingMode) {
5779                                 //
5780                                 // Check ObsoleteAttribute on the best method
5781                                 //
5782                                 best_candidate.CheckObsoleteness (rc, loc);
5783
5784                                 best_candidate.MemberDefinition.SetIsUsed ();
5785                         }
5786
5787                         args = best_candidate_args;
5788                         return (T) best_candidate;
5789                 }
5790
5791                 public MethodSpec ResolveOperator (ResolveContext rc, ref Arguments args)
5792                 {
5793                         return ResolveMember<MethodSpec> (rc, ref args);
5794                 }
5795
5796                 void ReportArgumentMismatch (ResolveContext ec, int idx, MemberSpec method,
5797                                                                                                         Argument a, AParametersCollection expected_par, TypeSpec paramType)
5798                 {
5799                         if (custom_errors != null && custom_errors.ArgumentMismatch (ec, method, a, idx))
5800                                 return;
5801
5802                         if (a.Type == InternalType.ErrorType)
5803                                 return;
5804
5805                         if (a is CollectionElementInitializer.ElementInitializerArgument) {
5806                                 ec.Report.SymbolRelatedToPreviousError (method);
5807                                 if ((expected_par.FixedParameters[idx].ModFlags & Parameter.Modifier.RefOutMask) != 0) {
5808                                         ec.Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have `ref' or `out' modifier",
5809                                                 TypeManager.CSharpSignature (method));
5810                                         return;
5811                                 }
5812                                 ec.Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments",
5813                                           TypeManager.CSharpSignature (method));
5814                         } else if (IsDelegateInvoke) {
5815                                 ec.Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments",
5816                                         DelegateType.GetSignatureForError ());
5817                         } else {
5818                                 ec.Report.SymbolRelatedToPreviousError (method);
5819                                 ec.Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments",
5820                                         method.GetSignatureForError ());
5821                         }
5822
5823                         Parameter.Modifier mod = idx >= expected_par.Count ? 0 : expected_par.FixedParameters[idx].ModFlags;
5824
5825                         string index = (idx + 1).ToString ();
5826                         if (((mod & Parameter.Modifier.RefOutMask) ^ (a.Modifier & Parameter.Modifier.RefOutMask)) != 0) {
5827                                 if ((mod & Parameter.Modifier.RefOutMask) == 0)
5828                                         ec.Report.Error (1615, a.Expr.Location, "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' modifier",
5829                                                 index, Parameter.GetModifierSignature (a.Modifier));
5830                                 else
5831                                         ec.Report.Error (1620, a.Expr.Location, "Argument `#{0}' is missing `{1}' modifier",
5832                                                 index, Parameter.GetModifierSignature (mod));
5833                         } else {
5834                                 string p1 = a.GetSignatureForError ();
5835                                 string p2 = paramType.GetSignatureForError ();
5836
5837                                 if (p1 == p2) {
5838                                         p1 = a.Type.GetSignatureForErrorIncludingAssemblyName ();
5839                                         p2 = paramType.GetSignatureForErrorIncludingAssemblyName ();
5840                                 }
5841
5842                                 if ((mod & Parameter.Modifier.RefOutMask) != 0) {
5843                                         p1 = Parameter.GetModifierSignature (a.Modifier) + " " + p1;
5844                                         p2 = Parameter.GetModifierSignature (a.Modifier) + " " + p2;
5845                                 }
5846
5847                                 ec.Report.Error (1503, a.Expr.Location,
5848                                         "Argument `#{0}' cannot convert `{1}' expression to type `{2}'", index, p1, p2);
5849                         }
5850                 }
5851
5852                 //
5853                 // We have failed to find exact match so we return error info about the closest match
5854                 //
5855                 void ReportOverloadError (ResolveContext rc, MemberSpec best_candidate, IParametersMember pm, Arguments args, bool params_expanded)
5856                 {
5857                         int ta_count = type_arguments == null ? 0 : type_arguments.Count;
5858                         int arg_count = args == null ? 0 : args.Count;
5859
5860                         if (ta_count != best_candidate.Arity && (ta_count > 0 || ((IParametersMember) best_candidate).Parameters.IsEmpty)) {
5861                                 var mg = new MethodGroupExpr (new [] { best_candidate }, best_candidate.DeclaringType, loc);
5862                                 mg.Error_TypeArgumentsCannotBeUsed (rc, best_candidate, loc);
5863                                 return;
5864                         }
5865
5866                         if (lambda_conv_msgs != null && lambda_conv_msgs.Merge (rc.Report.Printer)) {
5867                                 return;
5868                         }
5869
5870
5871                         if ((best_candidate.Modifiers & (Modifiers.PROTECTED | Modifiers.STATIC)) == Modifiers.PROTECTED &&
5872                                 InstanceQualifier != null && !InstanceQualifier.CheckProtectedMemberAccess (rc, best_candidate)) {
5873                                 MemberExpr.Error_ProtectedMemberAccess (rc, best_candidate, InstanceQualifier.InstanceType, loc);
5874                         }
5875
5876                         //
5877                         // For candidates which match on parameters count report more details about incorrect arguments
5878                         //
5879                         if (pm != null) {
5880                                 if (pm.Parameters.Count == arg_count || params_expanded || HasUnfilledParams (best_candidate, pm, args)) {
5881                                         // Reject any inaccessible member
5882                                         if (!best_candidate.IsAccessible (rc) || !best_candidate.DeclaringType.IsAccessible (rc)) {
5883                                                 rc.Report.SymbolRelatedToPreviousError (best_candidate);
5884                                                 Expression.ErrorIsInaccesible (rc, best_candidate.GetSignatureForError (), loc);
5885                                                 return;
5886                                         }
5887
5888                                         var ms = best_candidate as MethodSpec;
5889                                         if (ms != null && ms.IsGeneric) {
5890                                                 bool constr_ok = true;
5891                                                 if (ms.TypeArguments != null)
5892                                                         constr_ok = new ConstraintChecker (rc.MemberContext).CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc);
5893
5894                                                 if (ta_count == 0 && ms.TypeArguments == null) {
5895                                                         if (custom_errors != null && custom_errors.TypeInferenceFailed (rc, best_candidate))
5896                                                                 return;
5897
5898                                                         if (constr_ok) {
5899                                                                 rc.Report.Error (411, loc,
5900                                                                         "The type arguments for method `{0}' cannot be inferred from the usage. Try specifying the type arguments explicitly",
5901                                                                         ms.GetGenericMethodDefinition ().GetSignatureForError ());
5902                                                         }
5903
5904                                                         return;
5905                                                 }
5906                                         }
5907
5908                                         VerifyArguments (rc, ref args, best_candidate, pm, params_expanded);
5909                                         return;
5910                                 }
5911                         }
5912
5913                         //
5914                         // We failed to find any method with correct argument count, report best candidate
5915                         //
5916                         if (custom_errors != null && custom_errors.NoArgumentMatch (rc, best_candidate))
5917                                 return;
5918
5919                         if (best_candidate.Kind == MemberKind.Constructor) {
5920                                 rc.Report.SymbolRelatedToPreviousError (best_candidate);
5921                                 Error_ConstructorMismatch (rc, best_candidate.DeclaringType, arg_count, loc);
5922                         } else if (IsDelegateInvoke) {
5923                                 rc.Report.SymbolRelatedToPreviousError (DelegateType);
5924                                 rc.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",
5925                                         DelegateType.GetSignatureForError (), arg_count.ToString ());
5926                         } else {
5927                                 string name = best_candidate.Kind == MemberKind.Indexer ? "this" : best_candidate.Name;
5928                                 rc.Report.SymbolRelatedToPreviousError (best_candidate);
5929                                 rc.Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments",
5930                                         name, arg_count.ToString ());
5931                         }
5932                 }
5933
5934                 static bool HasUnfilledParams (MemberSpec best_candidate, IParametersMember pm, Arguments args)
5935                 {
5936                         var p = ((IParametersMember)best_candidate).Parameters;
5937                         if (!p.HasParams)
5938                                 return false;
5939
5940                         string name = null;
5941                         for (int i = p.Count - 1; i != 0; --i) {
5942                                 var fp = p.FixedParameters [i];
5943                                 if ((fp.ModFlags & Parameter.Modifier.PARAMS) == 0)
5944                                         continue;
5945
5946                                 name = fp.Name;
5947                                 break;
5948                         }
5949
5950                         if (args == null)
5951                                 return false;
5952
5953                         foreach (var arg in args) {
5954                                 var na = arg as NamedArgument;
5955                                 if (na == null)
5956                                         continue;
5957
5958                                 if (na.Name == name) {
5959                                         name = null;
5960                                         break;
5961                                 }
5962                         }
5963
5964                         if (name == null)
5965                                 return false;
5966
5967                         return args.Count + 1 == pm.Parameters.Count;
5968                 }
5969
5970                 bool VerifyArguments (ResolveContext ec, ref Arguments args, MemberSpec member, IParametersMember pm, bool chose_params_expanded)
5971                 {
5972                         var pd = pm.Parameters;
5973                         var cpd = ((IParametersMember) member).Parameters;
5974                         var ptypes = cpd.Types;
5975
5976                         Parameter.Modifier p_mod = 0;
5977                         TypeSpec pt = null;
5978                         int a_idx = 0, a_pos = 0;
5979                         Argument a = null;
5980                         ArrayInitializer params_initializers = null;
5981                         bool has_unsafe_arg = pm.MemberType.IsPointer;
5982                         int arg_count = args == null ? 0 : args.Count;
5983
5984                         for (; a_idx < arg_count; a_idx++, ++a_pos) {
5985                                 a = args[a_idx];
5986                                 if (a == null)
5987                                         continue;
5988
5989                                 if (p_mod != Parameter.Modifier.PARAMS) {
5990                                         p_mod = cpd.FixedParameters [a_idx].ModFlags;
5991                                         pt = ptypes[a_idx];
5992                                         has_unsafe_arg |= pt.IsPointer;
5993
5994                                         if (p_mod == Parameter.Modifier.PARAMS) {
5995                                                 if (chose_params_expanded) {
5996                                                         params_initializers = new ArrayInitializer (arg_count - a_idx, a.Expr.Location);
5997                                                         pt = TypeManager.GetElementType (pt);
5998                                                 }
5999                                         }
6000                                 }
6001
6002                                 //
6003                                 // Types have to be identical when ref or out modifer is used 
6004                                 //
6005                                 if (((a.Modifier | p_mod) & Parameter.Modifier.RefOutMask) != 0) {
6006                                         if ((a.Modifier & Parameter.Modifier.RefOutMask) != (p_mod & Parameter.Modifier.RefOutMask))
6007                                                 break;
6008
6009                                         var arg_type = a.Type;
6010                                         if (arg_type == pt)
6011                                                 continue;
6012
6013                                         if (arg_type == InternalType.VarOutType) {
6014                                                 //
6015                                                 // Set underlying variable type based on parameter type
6016                                                 //
6017                                                 ((DeclarationExpression)a.Expr).Variable.Type = pt;
6018                                                 continue;
6019                                         }
6020
6021                                         if (!TypeSpecComparer.IsEqual (arg_type, pt))
6022                                                 break;
6023                                 }
6024
6025                                 NamedArgument na = a as NamedArgument;
6026                                 if (na != null) {
6027                                         int name_index = pd.GetParameterIndexByName (na.Name);
6028                                         if (name_index < 0 || name_index >= pd.Count) {
6029                                                 if (IsDelegateInvoke) {
6030                                                         ec.Report.SymbolRelatedToPreviousError (DelegateType);
6031                                                         ec.Report.Error (1746, na.Location,
6032                                                                 "The delegate `{0}' does not contain a parameter named `{1}'",
6033                                                                 DelegateType.GetSignatureForError (), na.Name);
6034                                                 } else {
6035                                                         ec.Report.SymbolRelatedToPreviousError (member);
6036                                                         ec.Report.Error (1739, na.Location,
6037                                                                 "The best overloaded method match for `{0}' does not contain a parameter named `{1}'",
6038                                                                 TypeManager.CSharpSignature (member), na.Name);
6039                                                 }
6040                                         } else if (args[name_index] != a && args[name_index] != null) {
6041                                                 if (IsDelegateInvoke)
6042                                                         ec.Report.SymbolRelatedToPreviousError (DelegateType);
6043                                                 else
6044                                                         ec.Report.SymbolRelatedToPreviousError (member);
6045
6046                                                 ec.Report.Error (1744, na.Location,
6047                                                         "Named argument `{0}' cannot be used for a parameter which has positional argument specified",
6048                                                         na.Name);
6049                                         }
6050                                 }
6051                                 
6052                                 if (a.Expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
6053                                         continue;
6054
6055                                 if ((restrictions & Restrictions.CovariantDelegate) != 0 && !Delegate.IsTypeCovariant (ec, a.Expr.Type, pt)) {
6056                                         if (a.IsExtensionType) {
6057                                                 // TODO: Should report better message type, something similar to CS1928/1929 instead of
6058                                                 // CS1061 but that still better than confusing CS0123
6059                                                 var ma = new MemberAccess (a.Expr, member.Name, loc);
6060                                                 ma.Error_TypeDoesNotContainDefinition (ec, a.Expr.Type, ma.Name);
6061                                         } else {
6062                                                 custom_errors.NoArgumentMatch (ec, member);
6063                                         }
6064                                         return false;
6065                                 }
6066
6067                                 Expression conv;
6068                                 if (a.IsExtensionType) {
6069                                         if (a.Expr.Type == pt || TypeSpecComparer.IsEqual (a.Expr.Type, pt)) {
6070                                                 conv = a.Expr;
6071                                         } else {
6072                                                 conv = Convert.ImplicitReferenceConversion (a.Expr, pt, false);
6073                                                 if (conv == null)
6074                                                         conv = Convert.ImplicitBoxingConversion (a.Expr, a.Expr.Type, pt);
6075                                         }
6076                                 } else {
6077                                         conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc);
6078                                 }
6079
6080                                 if (conv == null)
6081                                         break;
6082
6083                                 //
6084                                 // Convert params arguments to an array initializer
6085                                 //
6086                                 if (params_initializers != null) {
6087                                         // we choose to use 'a.Expr' rather than 'conv' so that
6088                                         // we don't hide the kind of expression we have (esp. CompoundAssign.Helper)
6089                                         params_initializers.Add (a.Expr);
6090                                         args.RemoveAt (a_idx--);
6091                                         --arg_count;
6092                                         a.Expr = conv;
6093                                         continue;
6094                                 }
6095
6096                                 // Update the argument with the implicit conversion
6097                                 a.Expr = conv;
6098                         }
6099
6100                         if (a_idx != arg_count) {
6101                                 //
6102                                 // Convert all var out argument to error type for less confusing error reporting
6103                                 // when no matching overload is found
6104                                 //
6105                                 for (; a_idx < arg_count; a_idx++) {
6106                                         var arg = args [a_idx];
6107                                         if (arg == null)
6108                                                 continue;
6109
6110                                         if (arg.Type == InternalType.VarOutType) {
6111                                                 ((DeclarationExpression)arg.Expr).Variable.Type = InternalType.ErrorType;
6112                                         }
6113                                 }
6114
6115                                 ReportArgumentMismatch (ec, a_pos, member, a, pd, pt);
6116                                 return false;
6117                         }
6118
6119                         //
6120                         // Fill not provided arguments required by params modifier
6121                         //
6122                         if (params_initializers == null && arg_count + 1 == pd.Count) {
6123                                 if (args == null)
6124                                         args = new Arguments (1);
6125
6126                                 pt = ptypes[pd.Count - 1];
6127                                 pt = TypeManager.GetElementType (pt);
6128                                 has_unsafe_arg |= pt.IsPointer;
6129                                 params_initializers = new ArrayInitializer (0, loc);
6130                         }
6131
6132                         //
6133                         // Append an array argument with all params arguments
6134                         //
6135                         if (params_initializers != null) {
6136                                 args.Add (new Argument (
6137                                         new ArrayCreation (new TypeExpression (pt, loc), params_initializers, loc).Resolve (ec)));
6138                                 arg_count++;
6139                         }
6140
6141                         if (has_unsafe_arg) {
6142                                 if (ec.CurrentIterator != null) {
6143                                         Expression.UnsafeInsideIteratorError (ec, loc);
6144                                 } else if (!ec.IsUnsafe) {
6145                                         Expression.UnsafeError (ec, loc);
6146                                 }
6147                         }
6148
6149                         //
6150                         // We could infer inaccesible type arguments
6151                         //
6152                         if (type_arguments == null && member.IsGeneric) {
6153                                 var ms = (MethodSpec) member;
6154                                 foreach (var ta in ms.TypeArguments) {
6155                                         if (!ta.IsAccessible (ec)) {
6156                                                 ec.Report.SymbolRelatedToPreviousError (ta);
6157                                                 Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
6158                                                 break;
6159                                         }
6160                                 }
6161                         }
6162
6163                         return true;
6164                 }
6165         }
6166
6167         public class ConstantExpr : MemberExpr
6168         {
6169                 readonly ConstSpec constant;
6170
6171                 public ConstantExpr (ConstSpec constant, Location loc)
6172                 {
6173                         this.constant = constant;
6174                         this.loc = loc;
6175                 }
6176
6177                 public override string Name {
6178                         get { throw new NotImplementedException (); }
6179                 }
6180
6181                 public override string KindName {
6182                         get { return "constant"; }
6183                 }
6184
6185                 public override bool IsInstance {
6186                         get { return !IsStatic; }
6187                 }
6188
6189                 public override bool IsStatic {
6190                         get { return true; }
6191                 }
6192
6193                 protected override TypeSpec DeclaringType {
6194                         get { return constant.DeclaringType; }
6195                 }
6196
6197                 public override Expression CreateExpressionTree (ResolveContext ec)
6198                 {
6199                         throw new NotSupportedException ("ET");
6200                 }
6201
6202                 protected override Expression DoResolve (ResolveContext rc)
6203                 {
6204                         ResolveInstanceExpression (rc, null);
6205                         DoBestMemberChecks (rc, constant);
6206
6207                         if (rc.HasSet (ResolveContext.Options.NameOfScope)) {
6208                                 eclass = ExprClass.Value;
6209                                 type = constant.MemberType;
6210                                 return this;
6211                         }
6212
6213                         var c = constant.GetConstant (rc);
6214
6215                         // Creates reference expression to the constant value
6216                         return Constant.CreateConstantFromValue (constant.MemberType, c.GetValue (), loc);
6217                 }
6218
6219                 public override void Emit (EmitContext ec)
6220                 {
6221                         throw new NotSupportedException ();
6222                 }
6223
6224                 public override string GetSignatureForError ()
6225                 {
6226                         return constant.GetSignatureForError ();
6227                 }
6228
6229                 public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
6230                 {
6231                         constant.CheckObsoleteness (rc, expr.Location);
6232                 }
6233
6234                 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
6235                 {
6236                         Error_TypeArgumentsCannotBeUsed (ec, "constant", GetSignatureForError (), loc);
6237                 }
6238         }
6239
6240         //
6241         // Fully resolved expression that references a Field
6242         //
6243         public class FieldExpr : MemberExpr, IDynamicAssign, IMemoryLocation, IVariableReference
6244         {
6245                 protected FieldSpec spec;
6246                 VariableInfo variable_info;
6247                 
6248                 LocalTemporary temp;
6249                 bool prepared;
6250                 
6251                 protected FieldExpr (Location l)
6252                 {
6253                         loc = l;
6254                 }
6255
6256                 public FieldExpr (FieldSpec spec, Location loc)
6257                 {
6258                         this.spec = spec;
6259                         this.loc = loc;
6260
6261                         type = spec.MemberType;
6262                 }
6263                 
6264                 public FieldExpr (FieldBase fi, Location l)
6265                         : this (fi.Spec, l)
6266                 {
6267                 }
6268
6269                 #region Properties
6270
6271                 public override string Name {
6272                         get {
6273                                 return spec.Name;
6274                         }
6275                 }
6276
6277                 public bool IsHoisted {
6278                         get {
6279                                 IVariableReference hv = InstanceExpression as IVariableReference;
6280                                 return hv != null && hv.IsHoisted;
6281                         }
6282                 }
6283
6284                 public override bool IsInstance {
6285                         get {
6286                                 return !spec.IsStatic;
6287                         }
6288                 }
6289
6290                 public override bool IsStatic {
6291                         get {
6292                                 return spec.IsStatic;
6293                         }
6294                 }
6295
6296                 public override string KindName {
6297                         get { return "field"; }
6298                 }
6299
6300                 public FieldSpec Spec {
6301                         get {
6302                                 return spec;
6303                         }
6304                 }
6305
6306                 protected override TypeSpec DeclaringType {
6307                         get {
6308                                 return spec.DeclaringType;
6309                         }
6310                 }
6311
6312                 public VariableInfo VariableInfo {
6313                         get {
6314                                 return variable_info;
6315                         }
6316                 }
6317
6318 #endregion
6319
6320                 public override string GetSignatureForError ()
6321                 {
6322                         return spec.GetSignatureForError ();
6323                 }
6324
6325                 public bool IsMarshalByRefAccess (ResolveContext rc)
6326                 {
6327                         // Checks possible ldflda of field access expression
6328                         return !spec.IsStatic && TypeSpec.IsValueType (spec.MemberType) && !(InstanceExpression is This) &&
6329                                 rc.Module.PredefinedTypes.MarshalByRefObject.Define () &&
6330                                 TypeSpec.IsBaseClass (spec.DeclaringType, rc.Module.PredefinedTypes.MarshalByRefObject.TypeSpec, false);
6331                 }
6332
6333                 public void SetHasAddressTaken ()
6334                 {
6335                         IVariableReference vr = InstanceExpression as IVariableReference;
6336                         if (vr != null) {
6337                                 vr.SetHasAddressTaken ();
6338                         }
6339                 }
6340
6341                 protected override void CloneTo (CloneContext clonectx, Expression target)
6342                 {
6343                         var t = (FieldExpr) target;
6344
6345                         if (InstanceExpression != null)
6346                                 t.InstanceExpression = InstanceExpression.Clone (clonectx);
6347                 }
6348
6349                 public override Expression CreateExpressionTree (ResolveContext ec)
6350                 {
6351                         if (ConditionalAccess) {
6352                                 Error_NullShortCircuitInsideExpressionTree (ec);
6353                         }
6354
6355                         return CreateExpressionTree (ec, true);
6356                 }
6357
6358                 public Expression CreateExpressionTree (ResolveContext ec, bool convertInstance)
6359                 {
6360                         Arguments args;
6361                         Expression instance;
6362
6363                         if (InstanceExpression == null) {
6364                                 instance = new NullLiteral (loc);
6365                         } else if (convertInstance) {
6366                                 instance = InstanceExpression.CreateExpressionTree (ec);
6367                         } else {
6368                                 args = new Arguments (1);
6369                                 args.Add (new Argument (InstanceExpression));
6370                                 instance = CreateExpressionFactoryCall (ec, "Constant", args);
6371                         }
6372
6373                         args = Arguments.CreateForExpressionTree (ec, null,
6374                                 instance,
6375                                 CreateTypeOfExpression ());
6376
6377                         return CreateExpressionFactoryCall (ec, "Field", args);
6378                 }
6379
6380                 public Expression CreateTypeOfExpression ()
6381                 {
6382                         return new TypeOfField (spec, loc);
6383                 }
6384
6385                 protected override Expression DoResolve (ResolveContext ec)
6386                 {
6387                         spec.MemberDefinition.SetIsUsed ();
6388
6389                         return DoResolve (ec, null);
6390                 }
6391
6392                 Expression DoResolve (ResolveContext ec, Expression rhs)
6393                 {
6394                         bool lvalue_instance = rhs != null && IsInstance && spec.DeclaringType.IsStruct;
6395
6396                         if (rhs != this) {
6397                                 ResolveConditionalAccessReceiver (ec);
6398
6399                                 if (ResolveInstanceExpression (ec, rhs)) {
6400                                         // Resolve the field's instance expression while flow analysis is turned
6401                                         // off: when accessing a field "a.b", we must check whether the field
6402                                         // "a.b" is initialized, not whether the whole struct "a" is initialized.
6403
6404                                         if (lvalue_instance) {
6405                                                 bool out_access = rhs == EmptyExpression.OutAccess || rhs == EmptyExpression.LValueMemberOutAccess;
6406
6407                                                 Expression right_side =
6408                                                         out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
6409
6410                                                 InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
6411                                         } else {
6412                                                 InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
6413                                         }
6414
6415                                         if (InstanceExpression == null)
6416                                                 return null;
6417                                 }
6418
6419                                 DoBestMemberChecks (ec, spec);
6420
6421                                 if (conditional_access_receiver)
6422                                         ec.With (ResolveContext.Options.DontSetConditionalAccessReceiver, false);
6423                         }
6424
6425                         var fb = spec as FixedFieldSpec;
6426                         IVariableReference var = InstanceExpression as IVariableReference;
6427
6428                         if (fb != null) {
6429                                 IFixedExpression fe = InstanceExpression as IFixedExpression;
6430                                 if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) {
6431                                         ec.Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement");
6432                                 }
6433
6434                                 if (InstanceExpression.eclass != ExprClass.Variable) {
6435                                         ec.Report.SymbolRelatedToPreviousError (spec);
6436                                         ec.Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields",
6437                                                 TypeManager.GetFullNameSignature (spec));
6438                                 } else if (var != null && var.IsHoisted) {
6439                                         AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, var, loc);
6440                                 }
6441
6442                                 return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec);
6443                         }
6444
6445                         //
6446                         // Set flow-analysis variable info for struct member access. It will be check later
6447                         // for precise error reporting
6448                         //
6449                         if (var != null && var.VariableInfo != null && InstanceExpression.Type.IsStruct) {
6450                                 variable_info = var.VariableInfo.GetStructFieldInfo (Name);
6451                         }
6452
6453                         if (conditional_access_receiver)
6454                                 type = LiftMemberType (ec, type);
6455
6456                         if (ConditionalAccess && InstanceExpression != null && InstanceExpression.IsNull)
6457                                 return Constant.CreateConstantFromValue (type, null, loc);
6458
6459                         eclass = ExprClass.Variable;
6460                         return this;
6461                 }
6462
6463                 public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
6464                 {
6465                         spec.CheckObsoleteness (rc, expr.Location);
6466                 }
6467
6468                 public void SetFieldAssigned (FlowAnalysisContext fc)
6469                 {
6470                         if (!IsInstance)
6471                                 return;
6472
6473                         bool lvalue_instance = spec.DeclaringType.IsStruct;
6474                         if (lvalue_instance) {
6475                                 var var = InstanceExpression as IVariableReference;
6476                                 if (var != null && var.VariableInfo != null) {
6477                                         fc.SetStructFieldAssigned (var.VariableInfo, Name);
6478                                 }
6479                         }
6480
6481                         var fe = InstanceExpression as FieldExpr;
6482                         if (fe != null) {
6483                                 Expression instance;
6484
6485                                 do {
6486                                         instance = fe.InstanceExpression;
6487                                         var fe_instance = instance as FieldExpr;
6488                                         if ((fe_instance != null && !fe_instance.IsStatic) || instance is LocalVariableReference) {
6489                                                 if (TypeSpec.IsReferenceType (fe.Type) && instance.Type.IsStruct) {
6490                                                         var var = InstanceExpression as IVariableReference;
6491                                                         if (var != null && var.VariableInfo == null) {
6492                                                                 var var_inst = instance as IVariableReference;
6493                                                                 if (var_inst == null || (var_inst.VariableInfo != null && !fc.IsDefinitelyAssigned (var_inst.VariableInfo)))
6494                                                                         fc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
6495                                                         }
6496                                                 }
6497
6498                                                 if (fe_instance != null) {
6499                                                         fe = fe_instance;
6500                                                         continue;
6501                                                 }
6502                                         }
6503
6504                                         break;
6505                                 } while (true);
6506
6507                                 if (instance != null && TypeSpec.IsReferenceType (instance.Type))
6508                                         instance.FlowAnalysis (fc);
6509                         } else {
6510                                 if (TypeSpec.IsReferenceType (InstanceExpression.Type))
6511                                         InstanceExpression.FlowAnalysis (fc);
6512                         }
6513                 }
6514
6515                 Expression Error_AssignToReadonly (ResolveContext rc, Expression right_side)
6516                 {
6517                         // The return value is always null.  Returning a value simplifies calling code.
6518         
6519                         if (right_side == EmptyExpression.OutAccess) {
6520                                 if (IsStatic) {
6521                                         rc.Report.Error (199, loc, "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
6522                                                 GetSignatureForError ());
6523                                 } else {
6524                                         rc.Report.Error (192, loc, "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
6525                                                 GetSignatureForError ());
6526                                 }
6527
6528                                 return null;
6529                         }
6530
6531                         if (right_side == EmptyExpression.LValueMemberAccess) {
6532                                 // Already reported as CS1648/CS1650
6533                                 return null;
6534                         }
6535
6536                         if (right_side == EmptyExpression.LValueMemberOutAccess) {
6537                                 if (IsStatic) {
6538                                         rc.Report.Error (1651, loc, "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
6539                                                 GetSignatureForError ());
6540                                 } else {
6541                                         rc.Report.Error (1649, loc, "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)",
6542                                                 GetSignatureForError ());
6543                                 }
6544                                 return null;
6545                         }
6546
6547                         if (IsStatic) {
6548                                 rc.Report.Error (198, loc, "A static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
6549                                         GetSignatureForError ());
6550                         } else {
6551                                 rc.Report.Error (191, loc, "A readonly field `{0}' cannot be assigned to (except in a constructor or a variable initializer)",
6552                                         GetSignatureForError ());
6553                         }
6554
6555                         return null;
6556                 }
6557
6558                 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
6559                 {
6560                         if (HasConditionalAccess ())
6561                                 Error_NullPropagatingLValue (ec);
6562
6563                         if (spec is FixedFieldSpec) {
6564                                 // It could be much better error message but we want to be error compatible
6565                                 Error_ValueAssignment (ec, right_side);
6566                         }
6567
6568                         Expression e = DoResolve (ec, right_side);
6569
6570                         if (e == null)
6571                                 return null;
6572
6573                         spec.MemberDefinition.SetIsAssigned ();
6574
6575                         if ((right_side == EmptyExpression.UnaryAddress || right_side == EmptyExpression.OutAccess) &&
6576                                         (spec.Modifiers & Modifiers.VOLATILE) != 0) {
6577                                 ec.Report.Warning (420, 1, loc,
6578                                         "`{0}': A volatile field references will not be treated as volatile",
6579                                         spec.GetSignatureForError ());
6580                         }
6581
6582                         if (spec.IsReadOnly) {
6583                                 // InitOnly fields can only be assigned in constructors or initializers
6584                                 if (!ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.ConstructorScope))
6585                                         return Error_AssignToReadonly (ec, right_side);
6586
6587                                 if (ec.HasSet (ResolveContext.Options.ConstructorScope)) {
6588
6589                                         // InitOnly fields cannot be assigned-to in a different constructor from their declaring type
6590                                         if (ec.CurrentMemberDefinition.Parent.PartialContainer.Definition != spec.DeclaringType.GetDefinition ())
6591                                                 return Error_AssignToReadonly (ec, right_side);
6592                                         // static InitOnly fields cannot be assigned-to in an instance constructor
6593                                         if (IsStatic && !ec.IsStatic)
6594                                                 return Error_AssignToReadonly (ec, right_side);
6595                                         // instance constructors can't modify InitOnly fields of other instances of the same type
6596                                         if (!IsStatic && !(InstanceExpression is This))
6597                                                 return Error_AssignToReadonly (ec, right_side);
6598                                 }
6599                         }
6600
6601                         if (right_side == EmptyExpression.OutAccess && IsMarshalByRefAccess (ec)) {
6602                                 ec.Report.SymbolRelatedToPreviousError (spec.DeclaringType);
6603                                 ec.Report.Warning (197, 1, loc,
6604                                                 "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",
6605                                                 GetSignatureForError ());
6606                         }
6607
6608                         eclass = ExprClass.Variable;
6609                         return this;
6610                 }
6611
6612                 public override void FlowAnalysis (FlowAnalysisContext fc)
6613                 {
6614                         var var = InstanceExpression as IVariableReference;
6615                         if (var != null) {
6616                                 var vi = var.VariableInfo;
6617                                 if (vi != null && !fc.IsStructFieldDefinitelyAssigned (vi, Name)) {
6618                                         fc.Report.Error (170, loc, "Use of possibly unassigned field `{0}'", Name);
6619                                         return;
6620                                 }
6621
6622                                 if (TypeSpec.IsValueType (InstanceExpression.Type)) {
6623                                         var le = SkipLeftValueTypeAccess (InstanceExpression);
6624                                         if (le != null)
6625                                                 le.FlowAnalysis (fc);
6626
6627                                         return;
6628                                 }
6629                         }
6630
6631                         var da = conditional_access_receiver ? fc.BranchDefiniteAssignment () : null;
6632
6633                         base.FlowAnalysis (fc);
6634
6635                         if (conditional_access_receiver)
6636                                 fc.DefiniteAssignment = da;
6637                 }
6638
6639                 static Expression SkipLeftValueTypeAccess (Expression expr)
6640                 {
6641                         if (!TypeSpec.IsValueType (expr.Type))
6642                                 return expr;
6643
6644                         if (expr is VariableReference)
6645                                 return null;
6646
6647                         var fe = expr as FieldExpr;
6648                         if (fe == null)
6649                                 return expr;
6650
6651                         if (fe.InstanceExpression == null)
6652                                 return expr;
6653
6654                         return SkipLeftValueTypeAccess (fe.InstanceExpression);
6655                 }
6656
6657                 public override int GetHashCode ()
6658                 {
6659                         return spec.GetHashCode ();
6660                 }
6661                 
6662                 public bool IsFixed {
6663                         get {
6664                                 //
6665                                 // A variable of the form V.I is fixed when V is a fixed variable of a struct type
6666                                 //
6667                                 IVariableReference variable = InstanceExpression as IVariableReference;
6668                                 if (variable != null)
6669                                         return InstanceExpression.Type.IsStruct && variable.IsFixed;
6670
6671                                 IFixedExpression fe = InstanceExpression as IFixedExpression;
6672                                 return fe != null && fe.IsFixed;
6673                         }
6674                 }
6675
6676                 public override bool Equals (object obj)
6677                 {
6678                         FieldExpr fe = obj as FieldExpr;
6679                         if (fe == null)
6680                                 return false;
6681
6682                         if (spec != fe.spec)
6683                                 return false;
6684
6685                         if (InstanceExpression == null || fe.InstanceExpression == null)
6686                                 return true;
6687
6688                         return InstanceExpression.Equals (fe.InstanceExpression);
6689                 }
6690                 
6691                 public void Emit (EmitContext ec, bool leave_copy)
6692                 {
6693                         bool is_volatile = (spec.Modifiers & Modifiers.VOLATILE) != 0;
6694
6695                         if (IsStatic){
6696                                 if (is_volatile)
6697                                         ec.Emit (OpCodes.Volatile);
6698
6699                                 ec.Emit (OpCodes.Ldsfld, spec);
6700                         } else {
6701                                 var ca = ec.ConditionalAccess;
6702
6703                                 if (!prepared) {
6704                                         if (conditional_access_receiver)
6705                                                 ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ());
6706
6707                                         EmitInstance (ec, false);
6708                                 }
6709
6710                                 // Optimization for build-in types
6711                                 if (type.IsStruct && type == ec.CurrentType && InstanceExpression.Type == type) {
6712                                         ec.EmitLoadFromPtr (type);
6713                                 } else {
6714                                         var ff = spec as FixedFieldSpec;
6715                                         if (ff != null) {
6716                                                 ec.Emit (OpCodes.Ldflda, spec);
6717                                                 ec.Emit (OpCodes.Ldflda, ff.Element);
6718                                         } else {
6719                                                 if (is_volatile)
6720                                                         ec.Emit (OpCodes.Volatile);
6721
6722                                                 ec.Emit (OpCodes.Ldfld, spec);
6723                                         }
6724                                 }
6725
6726                                 if (conditional_access_receiver) {
6727                                         ec.CloseConditionalAccess (type.IsNullableType && type != spec.MemberType ? type : null);
6728                                         ec.ConditionalAccess = ca;
6729                                 }
6730                         }
6731
6732                         if (leave_copy) {
6733                                 ec.Emit (OpCodes.Dup);
6734                                 if (!IsStatic) {
6735                                         temp = new LocalTemporary (this.Type);
6736                                         temp.Store (ec);
6737                                 }
6738                         }
6739                 }
6740
6741                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
6742                 {
6743                         bool has_await_source = ec.HasSet (BuilderContext.Options.AsyncBody) && source.ContainsEmitWithAwait ();
6744                         if (isCompound && !(source is DynamicExpressionStatement) && !has_await_source) {
6745                                 prepared = true;
6746                         }
6747
6748                         if (IsInstance) {
6749                                 if (ConditionalAccess)
6750                                         throw new NotImplementedException ("null operator assignment");
6751
6752                                 if (has_await_source)
6753                                         source = source.EmitToField (ec);
6754
6755                                 EmitInstance (ec, prepared);
6756                         }
6757
6758                         source.Emit (ec);
6759
6760                         if (leave_copy || ec.NotifyEvaluatorOnStore) {
6761                                 ec.Emit (OpCodes.Dup);
6762                                 if (!IsStatic) {
6763                                         temp = new LocalTemporary (this.Type);
6764                                         temp.Store (ec);
6765                                 }
6766                         }
6767
6768                         if ((spec.Modifiers & Modifiers.VOLATILE) != 0)
6769                                 ec.Emit (OpCodes.Volatile);
6770                                         
6771                         spec.MemberDefinition.SetIsAssigned ();
6772
6773                         if (IsStatic)
6774                                 ec.Emit (OpCodes.Stsfld, spec);
6775                         else
6776                                 ec.Emit (OpCodes.Stfld, spec);
6777
6778                         if (ec.NotifyEvaluatorOnStore) {
6779                                 if (!IsStatic)
6780                                         throw new NotImplementedException ("instance field write");
6781
6782                                 if (leave_copy)
6783                                         ec.Emit (OpCodes.Dup);
6784
6785                                 ec.Module.Evaluator.EmitValueChangedCallback (ec, Name, type, loc);
6786                         }
6787                         
6788                         if (temp != null) {
6789                                 temp.Emit (ec);
6790                                 temp.Release (ec);
6791                                 temp = null;
6792                         }
6793                 }
6794
6795                 //
6796                 // Emits store to field with prepared values on stack
6797                 //
6798                 public void EmitAssignFromStack (EmitContext ec)
6799                 {
6800                         if (IsStatic) {
6801                                 ec.Emit (OpCodes.Stsfld, spec);
6802                         } else {
6803                                 ec.Emit (OpCodes.Stfld, spec);
6804                         }
6805                 }
6806
6807                 public override void Emit (EmitContext ec)
6808                 {
6809                         Emit (ec, false);
6810                 }
6811
6812                 public override void EmitSideEffect (EmitContext ec)
6813                 {
6814                         bool is_volatile = (spec.Modifiers & Modifiers.VOLATILE) != 0;
6815
6816                         if (is_volatile) // || is_marshal_by_ref ())
6817                                 base.EmitSideEffect (ec);
6818                 }
6819
6820                 public virtual void AddressOf (EmitContext ec, AddressOp mode)
6821                 {
6822                         if ((mode & AddressOp.Store) != 0)
6823                                 spec.MemberDefinition.SetIsAssigned ();
6824                         if ((mode & AddressOp.Load) != 0)
6825                                 spec.MemberDefinition.SetIsUsed ();
6826
6827                         //
6828                         // Handle initonly fields specially: make a copy and then
6829                         // get the address of the copy.
6830                         //
6831                         bool need_copy;
6832                         if (spec.IsReadOnly){
6833                                 need_copy = true;
6834                                 if (ec.HasSet (EmitContext.Options.ConstructorScope) && spec.DeclaringType == ec.CurrentType) {
6835                                         if (IsStatic){
6836                                                 if (ec.IsStatic)
6837                                                         need_copy = false;
6838                                         } else
6839                                                 need_copy = false;
6840                                 }
6841                         } else
6842                                 need_copy = false;
6843                         
6844                         if (need_copy) {
6845                                 Emit (ec);
6846                                 var temp = ec.GetTemporaryLocal (type);
6847                                 ec.Emit (OpCodes.Stloc, temp);
6848                                 ec.Emit (OpCodes.Ldloca, temp);
6849                                 return;
6850                         }
6851
6852
6853                         if (IsStatic){
6854                                 ec.Emit (OpCodes.Ldsflda, spec);
6855                         } else {
6856                                 if (!prepared)
6857                                         EmitInstance (ec, false);
6858                                 ec.Emit (OpCodes.Ldflda, spec);
6859                         }
6860                 }
6861
6862                 public SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source)
6863                 {
6864                         return MakeExpression (ctx);
6865                 }
6866
6867                 public override SLE.Expression MakeExpression (BuilderContext ctx)
6868                 {
6869 #if STATIC
6870                         return base.MakeExpression (ctx);
6871 #else
6872                         return SLE.Expression.Field (
6873                                 IsStatic ? null : InstanceExpression.MakeExpression (ctx),
6874                                 spec.GetMetaInfo ());
6875 #endif
6876                 }
6877
6878                 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
6879                 {
6880                         Error_TypeArgumentsCannotBeUsed (ec, "field", GetSignatureForError (), loc);
6881                 }
6882         }
6883
6884         
6885         //
6886         // Expression that evaluates to a Property.
6887         //
6888         // This is not an LValue because we need to re-write the expression. We
6889         // can not take data from the stack and store it.
6890         //
6891         sealed class PropertyExpr : PropertyOrIndexerExpr<PropertySpec>
6892         {
6893                 Arguments arguments;
6894                 FieldExpr backing_field;
6895
6896                 public PropertyExpr (PropertySpec spec, Location l)
6897                         : base (l)
6898                 {
6899                         best_candidate = spec;
6900                         type = spec.MemberType;
6901                 }
6902
6903                 #region Properties
6904
6905                 protected override Arguments Arguments {
6906                         get {
6907                                 return arguments;
6908                         }
6909                         set {
6910                                 arguments = value;
6911                         }
6912                 }
6913
6914                 protected override TypeSpec DeclaringType {
6915                         get {
6916                                 return best_candidate.DeclaringType;
6917                         }
6918                 }
6919
6920                 public override string Name {
6921                         get {
6922                                 return best_candidate.Name;
6923                         }
6924                 }
6925
6926                 public bool IsAutoPropertyAccess {
6927                         get {
6928                                 var prop = best_candidate.MemberDefinition as Property;
6929                                 return prop != null && prop.BackingField != null;
6930                         }
6931                 }
6932
6933                 public override bool IsInstance {
6934                         get {
6935                                 return !IsStatic;
6936                         }
6937                 }
6938
6939                 public override bool IsStatic {
6940                         get {
6941                                 return best_candidate.IsStatic;
6942                         }
6943                 }
6944
6945                 public override string KindName {
6946                         get { return "property"; }
6947                 }
6948
6949                 public PropertySpec PropertyInfo {
6950                         get {
6951                                 return best_candidate;
6952                         }
6953                 }
6954
6955                 #endregion
6956
6957                 public override MethodGroupExpr CanReduceLambda (AnonymousMethodBody body)
6958                 {
6959                         if (best_candidate == null || !(best_candidate.IsStatic || InstanceExpression is This))
6960                                 return null;
6961
6962                         var args_count = arguments == null ? 0 : arguments.Count;
6963                         if (args_count != body.Parameters.Count && args_count == 0)
6964                                 return null;
6965
6966                         var mg = MethodGroupExpr.CreatePredefined (best_candidate.Get, DeclaringType, loc);
6967                         mg.InstanceExpression = InstanceExpression;
6968
6969                         return mg;
6970                 }
6971
6972                 public static PropertyExpr CreatePredefined (PropertySpec spec, Location loc)
6973                 {
6974                         return new PropertyExpr (spec, loc) {
6975                                 Getter = spec.Get,
6976                                 Setter = spec.Set
6977                         };
6978                 }
6979
6980                 public override Expression CreateExpressionTree (ResolveContext ec)
6981                 {
6982                         if (ConditionalAccess) {
6983                                 Error_NullShortCircuitInsideExpressionTree (ec);
6984                         }
6985
6986                         Arguments args;
6987                         if (IsSingleDimensionalArrayLength ()) {
6988                                 args = new Arguments (1);
6989                                 args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
6990                                 return CreateExpressionFactoryCall (ec, "ArrayLength", args);
6991                         }
6992
6993                         args = new Arguments (2);
6994                         if (InstanceExpression == null)
6995                                 args.Add (new Argument (new NullLiteral (loc)));
6996                         else
6997                                 args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
6998                         args.Add (new Argument (new TypeOfMethod (Getter, loc)));
6999                         return CreateExpressionFactoryCall (ec, "Property", args);
7000                 }
7001
7002                 public Expression CreateSetterTypeOfExpression (ResolveContext rc)
7003                 {
7004                         DoResolveLValue (rc, null);
7005                         return new TypeOfMethod (Setter, loc);
7006                 }
7007
7008                 public override string GetSignatureForError ()
7009                 {
7010                         return best_candidate.GetSignatureForError ();
7011                 }
7012
7013                 public override SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source)
7014                 {
7015 #if STATIC
7016                         return base.MakeExpression (ctx);
7017 #else
7018                         return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) Setter.GetMetaInfo ());
7019 #endif
7020                 }
7021
7022                 public override SLE.Expression MakeExpression (BuilderContext ctx)
7023                 {
7024 #if STATIC
7025                         return base.MakeExpression (ctx);
7026 #else
7027                         return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) Getter.GetMetaInfo ());
7028 #endif
7029                 }
7030
7031                 void Error_PropertyNotValid (ResolveContext ec)
7032                 {
7033                         ec.Report.SymbolRelatedToPreviousError (best_candidate);
7034                         ec.Report.Error (1546, loc, "Property or event `{0}' is not supported by the C# language",
7035                                 GetSignatureForError ());
7036                 }
7037
7038                 bool IsSingleDimensionalArrayLength ()
7039                 {
7040                         if (best_candidate.DeclaringType.BuiltinType != BuiltinTypeSpec.Type.Array || !best_candidate.HasGet || Name != "Length")
7041                                 return false;
7042
7043                         ArrayContainer ac = InstanceExpression.Type as ArrayContainer;
7044                         return ac != null && ac.Rank == 1;
7045                 }
7046
7047                 public override void Emit (EmitContext ec, bool leave_copy)
7048                 {
7049                         //
7050                         // Special case: length of single dimension array property is turned into ldlen
7051                         //
7052                         if (IsSingleDimensionalArrayLength ()) {
7053                                 if (conditional_access_receiver) {
7054                                         ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ());
7055                                 }
7056
7057                                 EmitInstance (ec, false);
7058
7059                                 ec.Emit (OpCodes.Ldlen);
7060                                 ec.Emit (OpCodes.Conv_I4);
7061
7062                                 if (conditional_access_receiver) {
7063                                         ec.CloseConditionalAccess (type);
7064                                 }
7065
7066                                 return;
7067                         }
7068
7069                         base.Emit (ec, leave_copy);
7070                 }
7071
7072                 public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
7073                 {
7074                         if (backing_field != null) {
7075                                 backing_field.EmitAssign (ec, source, leave_copy, false);
7076                                 return;
7077                         }
7078
7079                         Arguments args;
7080                         LocalTemporary await_source_arg = null;
7081
7082                         if (isCompound && !(source is DynamicExpressionStatement)) {
7083                                 emitting_compound_assignment = true;
7084                                 source.Emit (ec);
7085
7086                                 if (has_await_arguments) {
7087                                         await_source_arg = new LocalTemporary (Type);
7088                                         await_source_arg.Store (ec);
7089
7090                                         args = new Arguments (1);
7091                                         args.Add (new Argument (await_source_arg));
7092
7093                                         if (leave_copy) {
7094                                                 temp = await_source_arg;
7095                                         }
7096
7097                                         has_await_arguments = false;
7098                                 } else {
7099                                         args = null;
7100
7101                                         if (leave_copy) {
7102                                                 ec.Emit (OpCodes.Dup);
7103                                                 temp = new LocalTemporary (this.Type);
7104                                                 temp.Store (ec);
7105                                         }
7106                                 }
7107                         } else {
7108                                 args = arguments ?? new Arguments (1);
7109
7110                                 if (leave_copy) {
7111                                         source.Emit (ec);
7112                                         temp = new LocalTemporary (this.Type);
7113                                         temp.Store (ec);
7114                                         args.Add (new Argument (temp));
7115                                 } else {
7116                                         args.Add (new Argument (source));
7117                                 }
7118                         }
7119
7120                         emitting_compound_assignment = false;
7121
7122                         var call = new CallEmitter ();
7123                         call.InstanceExpression = InstanceExpression;
7124                         if (args == null)
7125                                 call.InstanceExpressionOnStack = true;
7126
7127                         if (ConditionalAccess) {
7128                                 call.ConditionalAccess = true;
7129                         }
7130
7131                         if (leave_copy)
7132                                 call.Emit (ec, Setter, args, loc);
7133                         else
7134                                 call.EmitStatement (ec, Setter, args, loc);
7135
7136                         if (temp != null) {
7137                                 temp.Emit (ec);
7138                                 temp.Release (ec);
7139                         }
7140
7141                         if (await_source_arg != null) {
7142                                 await_source_arg.Release (ec);
7143                         }
7144                 }
7145
7146                 public override void FlowAnalysis (FlowAnalysisContext fc)
7147                 {
7148                         var prop = best_candidate.MemberDefinition as Property;
7149                         if (prop != null && prop.BackingField != null) {
7150                                 var var = InstanceExpression as IVariableReference;
7151                                 if (var != null) {
7152                                         var vi = var.VariableInfo;
7153                                         if (vi != null && !fc.IsStructFieldDefinitelyAssigned (vi, prop.BackingField.Name)) {
7154                                                 fc.Report.Error (8079, loc, "Use of possibly unassigned auto-implemented property `{0}'", Name);
7155                                                 return;
7156                                         }
7157
7158                                         if (TypeSpec.IsValueType (InstanceExpression.Type) && InstanceExpression is VariableReference)
7159                                                 return;
7160                                 }
7161                         }
7162
7163                         var da = conditional_access_receiver ? fc.BranchDefiniteAssignment () : null;
7164
7165                         base.FlowAnalysis (fc);
7166
7167                         if (conditional_access_receiver)
7168                                 fc.DefiniteAssignment = da;
7169                 }
7170
7171                 protected override Expression OverloadResolve (ResolveContext rc, Expression right_side)
7172                 {
7173                         eclass = ExprClass.PropertyAccess;
7174
7175                         if (best_candidate.IsNotCSharpCompatible) {
7176                                 Error_PropertyNotValid (rc);
7177                         }
7178
7179                         ResolveInstanceExpression (rc, right_side);
7180
7181                         if ((best_candidate.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0 && best_candidate.DeclaringType != InstanceExpression.Type) {
7182                                 var filter = new MemberFilter (best_candidate.Name, 0, MemberKind.Property, null, null);
7183                                 var p = MemberCache.FindMember (InstanceExpression.Type, filter, BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly) as PropertySpec;
7184                                 if (p != null) {
7185                                         type = p.MemberType;
7186                                 }
7187                         }
7188
7189                         DoBestMemberChecks (rc, best_candidate);
7190
7191                         // Handling of com-imported properties with any number of default property parameters
7192                         if (best_candidate.HasGet && !best_candidate.Get.Parameters.IsEmpty) {
7193                                 var p = best_candidate.Get.Parameters;
7194                                 arguments = new Arguments (p.Count);
7195                                 for (int i = 0; i < p.Count; ++i) {
7196                                         arguments.Add (new Argument (OverloadResolver.ResolveDefaultValueArgument (rc, p.Types [i], p.FixedParameters [i].DefaultValue, loc)));
7197                                 }
7198                         } else if (best_candidate.HasSet && best_candidate.Set.Parameters.Count > 1) {
7199                                 var p = best_candidate.Set.Parameters;
7200                                 arguments = new Arguments (p.Count - 1);
7201                                 for (int i = 0; i < p.Count - 1; ++i) {
7202                                         arguments.Add (new Argument (OverloadResolver.ResolveDefaultValueArgument (rc, p.Types [i], p.FixedParameters [i].DefaultValue, loc)));
7203                                 }
7204                         }
7205
7206                         return this;
7207                 }
7208
7209                 protected override bool ResolveAutopropertyAssignment (ResolveContext rc, Expression rhs)
7210                 {
7211                         if (!rc.HasSet (ResolveContext.Options.ConstructorScope))
7212                                 return false;
7213
7214                         var prop = best_candidate.MemberDefinition as Property;
7215                         if (prop == null || prop.Parent.PartialContainer != rc.CurrentMemberDefinition.Parent.PartialContainer) {
7216                                 var ps = MemberCache.FindMember (rc.CurrentType, MemberFilter.Property (best_candidate.Name, best_candidate.MemberType), BindingRestriction.DeclaredOnly) as PropertySpec;
7217                                 if (ps == null)
7218                                         return false;
7219
7220                                 prop = (Property)ps.MemberDefinition;
7221                         }
7222
7223                         var spec = prop.BackingField;
7224                         if (spec == null)
7225                                 return false;
7226
7227                         if (rc.IsStatic != spec.IsStatic)
7228                                 return false;
7229
7230                         if (!spec.IsStatic && (!(InstanceExpression is This) || InstanceExpression is BaseThis))
7231                                 return false;
7232
7233                         backing_field = new FieldExpr (prop.BackingField, loc);
7234                         backing_field.ResolveLValue (rc, rhs);
7235                         return true;
7236                 }
7237
7238                 public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
7239                 {
7240                         if (!best_candidate.IsAccessible (rc))
7241                                 ErrorIsInaccesible (rc, best_candidate.GetSignatureForError (), expr.Location);
7242
7243                         best_candidate.CheckObsoleteness (rc, expr.Location);
7244                 }
7245
7246                 public void SetBackingFieldAssigned (FlowAnalysisContext fc)
7247                 {
7248                         if (backing_field != null) {
7249                                 backing_field.SetFieldAssigned (fc);
7250                                 return;
7251                         }
7252
7253                         if (!IsAutoPropertyAccess)
7254                                 return;
7255
7256                         var prop = best_candidate.MemberDefinition as Property;
7257                         if (prop != null && prop.BackingField != null) {
7258                                 bool lvalue_instance = best_candidate.DeclaringType.IsStruct;
7259                                 if (lvalue_instance) {
7260                                         var var = InstanceExpression as IVariableReference;
7261                                         if (var != null && var.VariableInfo != null) {
7262                                                 fc.SetStructFieldAssigned (var.VariableInfo, prop.BackingField.Name);
7263                                         }
7264                                 }
7265                         }
7266                 }
7267
7268                 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
7269                 {
7270                         Error_TypeArgumentsCannotBeUsed (ec, "property", GetSignatureForError (), loc);
7271                 }
7272         }
7273
7274         abstract class PropertyOrIndexerExpr<T> : MemberExpr, IDynamicAssign where T : PropertySpec
7275         {
7276                 // getter and setter can be different for base calls
7277                 MethodSpec getter, setter;
7278                 protected T best_candidate;
7279
7280                 protected LocalTemporary temp;
7281                 protected bool emitting_compound_assignment;
7282                 protected bool has_await_arguments;
7283
7284                 protected PropertyOrIndexerExpr (Location l)
7285                 {
7286                         loc = l;
7287                 }
7288
7289                 #region Properties
7290
7291                 protected abstract Arguments Arguments { get; set; }
7292
7293                 public MethodSpec Getter {
7294                         get {
7295                                 return getter;
7296                         }
7297                         set {
7298                                 getter = value;
7299                         }
7300                 }
7301
7302                 public MethodSpec Setter {
7303                         get {
7304                                 return setter;
7305                         }
7306                         set {
7307                                 setter = value;
7308                         }
7309                 }
7310
7311                 #endregion
7312
7313                 protected override Expression DoResolve (ResolveContext ec)
7314                 {
7315                         if (eclass == ExprClass.Unresolved) {
7316                                 ResolveConditionalAccessReceiver (ec);
7317
7318                                 var expr = OverloadResolve (ec, null);
7319                                 if (expr == null)
7320                                         return null;
7321
7322                                 if (expr != this) {
7323                                         using (ec.With (ResolveContext.Options.DontSetConditionalAccessReceiver, conditional_access_receiver))
7324                                                 return expr.Resolve (ec);
7325                                 }
7326
7327                                 if (conditional_access_receiver) {
7328                                         type = LiftMemberType (ec, type);
7329                                 }
7330                         }
7331
7332                         if (!ResolveGetter (ec))
7333                                 return null;
7334
7335                         return this;
7336                 }
7337
7338                 public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
7339                 {
7340                         if (HasConditionalAccess ())
7341                                 Error_NullPropagatingLValue (rc);
7342
7343                         if (right_side == EmptyExpression.OutAccess) {
7344                                 // TODO: best_candidate can be null at this point
7345                                 INamedBlockVariable variable = null;
7346                                 if (best_candidate != null && rc.CurrentBlock.ParametersBlock.TopBlock.GetLocalName (best_candidate.Name, rc.CurrentBlock, ref variable) && variable is Linq.RangeVariable) {
7347                                         rc.Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter",
7348                                                 best_candidate.Name);
7349                                 } else {
7350                                         right_side.DoResolveLValue (rc, this);
7351                                 }
7352                                 return null;
7353                         }
7354
7355                         if (eclass == ExprClass.Unresolved) {
7356                                 var expr = OverloadResolve (rc, right_side);
7357                                 if (expr == null)
7358                                         return null;
7359
7360                                 if (expr != this)
7361                                         return expr.ResolveLValue (rc, right_side);
7362                         } else {
7363                                 ResolveInstanceExpression (rc, right_side);
7364                         }
7365
7366                         if (!best_candidate.HasSet) {
7367                                 if (ResolveAutopropertyAssignment (rc, right_side))
7368                                         return this;
7369
7370                                 rc.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read-only)",
7371                                         GetSignatureForError ());
7372                                 return null;
7373                         }
7374
7375                         if (!best_candidate.Set.IsAccessible (rc) || !best_candidate.Set.DeclaringType.IsAccessible (rc)) {
7376                                 if (best_candidate.HasDifferentAccessibility) {
7377                                         rc.Report.SymbolRelatedToPreviousError (best_candidate.Set);
7378                                         rc.Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
7379                                                 GetSignatureForError ());
7380                                 } else {
7381                                         rc.Report.SymbolRelatedToPreviousError (best_candidate.Set);
7382                                         ErrorIsInaccesible (rc, best_candidate.GetSignatureForError (), loc);
7383                                 }
7384                         }
7385
7386                         if (best_candidate.HasDifferentAccessibility)
7387                                 CheckProtectedMemberAccess (rc, best_candidate.Set);
7388
7389                         setter = CandidateToBaseOverride (rc, best_candidate.Set);
7390                         return this;
7391                 }
7392
7393                 void EmitConditionalAccess (EmitContext ec, ref CallEmitter call, MethodSpec method, Arguments arguments)
7394                 {
7395                         var ca = ec.ConditionalAccess;
7396                         ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ());
7397
7398                         call.Emit (ec, method, arguments, loc);
7399
7400                         ec.CloseConditionalAccess (method.ReturnType != type && type.IsNullableType ? type : null);
7401                         ec.ConditionalAccess = ca;
7402                 }
7403
7404                 //
7405                 // Implements the IAssignMethod interface for assignments
7406                 //
7407                 public virtual void Emit (EmitContext ec, bool leave_copy)
7408                 {
7409                         var call = new CallEmitter ();
7410                         call.ConditionalAccess = ConditionalAccess;
7411                         call.InstanceExpression = InstanceExpression;
7412                         if (has_await_arguments)
7413                                 call.HasAwaitArguments = true;
7414                         else
7415                                 call.DuplicateArguments = emitting_compound_assignment;
7416
7417                         if (conditional_access_receiver)
7418                                 EmitConditionalAccess (ec, ref call, Getter, Arguments);
7419                         else
7420                                 call.Emit (ec, Getter, Arguments, loc);
7421
7422                         if (call.HasAwaitArguments) {
7423                                 InstanceExpression = call.InstanceExpression;
7424                                 Arguments = call.EmittedArguments;
7425                                 has_await_arguments = true;
7426                         }
7427
7428                         if (leave_copy) {
7429                                 ec.Emit (OpCodes.Dup);
7430                                 temp = new LocalTemporary (Type);
7431                                 temp.Store (ec);
7432                         }
7433                 }
7434
7435                 public abstract void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound);
7436
7437                 public override void Emit (EmitContext ec)
7438                 {
7439                         Emit (ec, false);
7440                 }
7441
7442                 protected override FieldExpr EmitToFieldSource (EmitContext ec)
7443                 {
7444                         has_await_arguments = true;
7445                         Emit (ec, false);
7446                         return null;
7447                 }
7448
7449                 public abstract SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source);
7450
7451                 protected abstract Expression OverloadResolve (ResolveContext rc, Expression right_side);
7452
7453                 bool ResolveGetter (ResolveContext rc)
7454                 {
7455                         if (!best_candidate.HasGet) {
7456                                 if (InstanceExpression != EmptyExpression.Null) {
7457                                         rc.Report.SymbolRelatedToPreviousError (best_candidate);
7458                                         rc.Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
7459                                                 best_candidate.GetSignatureForError ());
7460                                         return false;
7461                                 }
7462                         } else if (!best_candidate.Get.IsAccessible (rc) || !best_candidate.Get.DeclaringType.IsAccessible (rc)) {
7463                                 if (best_candidate.HasDifferentAccessibility) {
7464                                         rc.Report.SymbolRelatedToPreviousError (best_candidate.Get);
7465                                         rc.Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
7466                                                 TypeManager.CSharpSignature (best_candidate));
7467                                 } else {
7468                                         rc.Report.SymbolRelatedToPreviousError (best_candidate.Get);
7469                                         ErrorIsInaccesible (rc, best_candidate.Get.GetSignatureForError (), loc);
7470                                 }
7471                         }
7472
7473                         if (best_candidate.HasDifferentAccessibility) {
7474                                 CheckProtectedMemberAccess (rc, best_candidate.Get);
7475                         }
7476
7477                         getter = CandidateToBaseOverride (rc, best_candidate.Get);
7478                         return true;
7479                 }
7480
7481                 protected virtual bool ResolveAutopropertyAssignment (ResolveContext rc, Expression rhs)
7482                 {
7483                         return false;
7484                 }
7485         }
7486
7487         /// <summary>
7488         ///   Fully resolved expression that evaluates to an Event
7489         /// </summary>
7490         public class EventExpr : MemberExpr, IAssignMethod
7491         {
7492                 readonly EventSpec spec;
7493                 MethodSpec op;
7494
7495                 public EventExpr (EventSpec spec, Location loc)
7496                 {
7497                         this.spec = spec;
7498                         this.loc = loc;
7499                 }
7500
7501                 #region Properties
7502
7503                 protected override TypeSpec DeclaringType {
7504                         get {
7505                                 return spec.DeclaringType;
7506                         }
7507                 }
7508
7509                 public override string Name {
7510                         get {
7511                                 return spec.Name;
7512                         }
7513                 }
7514
7515                 public override bool IsInstance {
7516                         get {
7517                                 return !spec.IsStatic;
7518                         }
7519                 }
7520
7521                 public override bool IsStatic {
7522                         get {
7523                                 return spec.IsStatic;
7524                         }
7525                 }
7526
7527                 public override string KindName {
7528                         get { return "event"; }
7529                 }
7530
7531                 public MethodSpec Operator {
7532                         get {
7533                                 return op;
7534                         }
7535                 }
7536
7537                 #endregion
7538
7539                 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
7540                 {
7541                         //
7542                         // If the event is local to this class and we are not lhs of +=/-= we transform ourselves into a FieldExpr
7543                         //
7544                         if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) {
7545                                 if (spec.BackingField != null &&
7546                                         (spec.DeclaringType == ec.CurrentType || TypeManager.IsNestedChildOf (ec.CurrentType, spec.DeclaringType.MemberDefinition))) {
7547
7548                                         spec.MemberDefinition.SetIsUsed ();
7549
7550                                         spec.CheckObsoleteness (ec, loc);
7551
7552                                         if ((spec.Modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
7553                                                 Error_AssignmentEventOnly (ec);
7554
7555                                         FieldExpr ml = new FieldExpr (spec.BackingField, loc);
7556
7557                                         InstanceExpression = null;
7558
7559                                         return ml.ResolveMemberAccess (ec, left, original);
7560                                 }
7561                         }
7562
7563                         return base.ResolveMemberAccess (ec, left, original);
7564                 }
7565
7566                 public override Expression CreateExpressionTree (ResolveContext ec)
7567                 {
7568                         throw new NotSupportedException ("ET");
7569                 }
7570
7571                 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
7572                 {
7573                         if (right_side == EmptyExpression.EventAddition) {
7574                                 op = spec.AccessorAdd;
7575                         } else if (right_side == EmptyExpression.EventSubtraction) {
7576                                 op = spec.AccessorRemove;
7577                         }
7578
7579                         if (op == null) {
7580                                 Error_AssignmentEventOnly (ec);
7581                                 return null;
7582                         }
7583
7584                         if (HasConditionalAccess ())
7585                                 Error_NullPropagatingLValue (ec);
7586
7587                         op = CandidateToBaseOverride (ec, op);
7588                         return this;
7589                 }
7590
7591                 protected override Expression DoResolve (ResolveContext ec)
7592                 {
7593                         eclass = ExprClass.EventAccess;
7594                         type = spec.MemberType;
7595
7596                         ResolveInstanceExpression (ec, null);
7597
7598                         if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) {
7599                                 Error_AssignmentEventOnly (ec);
7600                         }
7601
7602                         DoBestMemberChecks (ec, spec);
7603                         return this;
7604                 }               
7605
7606                 public override void Emit (EmitContext ec)
7607                 {
7608                         throw new NotSupportedException ();
7609                         //Error_CannotAssign ();
7610                 }
7611
7612                 #region IAssignMethod Members
7613
7614                 public void Emit (EmitContext ec, bool leave_copy)
7615                 {
7616                         throw new NotImplementedException ();
7617                 }
7618
7619                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
7620                 {
7621                         if (leave_copy || !isCompound)
7622                                 throw new NotImplementedException ("EventExpr::EmitAssign");
7623
7624                         Arguments args = new Arguments (1);
7625                         args.Add (new Argument (source));
7626
7627                         // TODO: Wrong, needs receiver
7628 //                      if (NullShortCircuit) {
7629 //                              ec.ConditionalAccess = new ConditionalAccessContext (type, ec.DefineLabel ());
7630 //                      }
7631
7632                         var call = new CallEmitter ();
7633                         call.InstanceExpression = InstanceExpression;
7634                         call.ConditionalAccess = ConditionalAccess;
7635                         call.EmitStatement (ec, op, args, loc);
7636
7637 //                      if (NullShortCircuit)
7638 //                              ec.CloseConditionalAccess (null);
7639                 }
7640
7641                 #endregion
7642
7643                 void Error_AssignmentEventOnly (ResolveContext ec)
7644                 {
7645                         if (spec.DeclaringType == ec.CurrentType || TypeManager.IsNestedChildOf (ec.CurrentType, spec.DeclaringType.MemberDefinition)) {
7646                                 ec.Report.Error (79, loc,
7647                                         "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator",
7648                                         GetSignatureForError ());
7649                         } else {
7650                                 ec.Report.Error (70, loc,
7651                                         "The event `{0}' can only appear on the left hand side of += or -= when used outside of the type `{1}'",
7652                                         GetSignatureForError (), spec.DeclaringType.GetSignatureForError ());
7653                         }
7654                 }
7655
7656                 protected override void Error_CannotCallAbstractBase (ResolveContext rc, string name)
7657                 {
7658                         name = name.Substring (0, name.LastIndexOf ('.'));
7659                         base.Error_CannotCallAbstractBase (rc, name);
7660                 }
7661
7662                 public override string GetSignatureForError ()
7663                 {
7664                         return TypeManager.CSharpSignature (spec);
7665                 }
7666
7667                 public override void ResolveNameOf (ResolveContext rc, ATypeNameExpression expr)
7668                 {
7669                         spec.CheckObsoleteness (rc, expr.Location);
7670                 }
7671
7672                 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
7673                 {
7674                         Error_TypeArgumentsCannotBeUsed (ec, "event", GetSignatureForError (), loc);
7675                 }
7676         }
7677
7678         public class TemporaryVariableReference : VariableReference
7679         {
7680                 public class Declarator : Statement
7681                 {
7682                         TemporaryVariableReference variable;
7683
7684                         public Declarator (TemporaryVariableReference variable)
7685                         {
7686                                 this.variable = variable;
7687                                 loc = variable.loc;
7688                         }
7689
7690                         protected override void DoEmit (EmitContext ec)
7691                         {
7692                                 variable.li.CreateBuilder (ec);
7693                         }
7694
7695                         public override void Emit (EmitContext ec)
7696                         {
7697                                 // Don't create sequence point
7698                                 DoEmit (ec);
7699                         }
7700
7701                         protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
7702                         {
7703                                 return false;
7704                         }
7705
7706                         protected override void CloneTo (CloneContext clonectx, Statement target)
7707                         {
7708                                 // Nothing
7709                         }
7710                 }
7711
7712                 LocalVariable li;
7713
7714                 public TemporaryVariableReference (LocalVariable li, Location loc)
7715                 {
7716                         this.li = li;
7717                         this.type = li.Type;
7718                         this.loc = loc;
7719                 }
7720
7721                 public override bool IsLockedByStatement {
7722                         get {
7723                                 return false;
7724                         }
7725                         set {
7726                         }
7727                 }
7728
7729                 public LocalVariable LocalInfo {
7730                     get {
7731                         return li;
7732                     }
7733                 }
7734
7735                 public static TemporaryVariableReference Create (TypeSpec type, Block block, Location loc, bool writeToSymbolFile = false)
7736                 {
7737                         var li = LocalVariable.CreateCompilerGenerated (type, block, loc, writeToSymbolFile);
7738                         return new TemporaryVariableReference (li, loc);
7739                 }
7740
7741                 protected override Expression DoResolve (ResolveContext ec)
7742                 {
7743                         eclass = ExprClass.Variable;
7744
7745                         //
7746                         // Don't capture temporary variables except when using
7747                         // state machine redirection and block yields
7748                         //
7749                         if (ec.CurrentAnonymousMethod is StateMachineInitializer &&
7750                                 (ec.CurrentBlock.Explicit.HasYield || ec.CurrentBlock.Explicit.HasAwait) &&
7751                                 ec.IsVariableCapturingRequired) {
7752                                 AnonymousMethodStorey storey = li.Block.Explicit.CreateAnonymousMethodStorey (ec);
7753                                 storey.CaptureLocalVariable (ec, li);
7754                         }
7755
7756                         return this;
7757                 }
7758
7759                 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
7760                 {
7761                         return Resolve (ec);
7762                 }
7763                 
7764                 public override void Emit (EmitContext ec)
7765                 {
7766                         li.CreateBuilder (ec);
7767
7768                         Emit (ec, false);
7769                 }
7770
7771                 public void EmitAssign (EmitContext ec, Expression source)
7772                 {
7773                         li.CreateBuilder (ec);
7774
7775                         EmitAssign (ec, source, false, false);
7776                 }
7777
7778                 public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
7779                 {
7780                         return li.HoistedVariant;
7781                 }
7782
7783                 public override bool IsFixed {
7784                         get { return true; }
7785                 }
7786
7787                 public override bool IsRef {
7788                         get { return false; }
7789                 }
7790
7791                 public override string Name {
7792                         get { throw new NotImplementedException (); }
7793                 }
7794
7795                 public override void SetHasAddressTaken ()
7796                 {
7797                         throw new NotImplementedException ();
7798                 }
7799
7800                 protected override ILocalVariable Variable {
7801                         get { return li; }
7802                 }
7803
7804                 public override VariableInfo VariableInfo {
7805                         get { return null; }
7806                 }
7807         }
7808
7809         /// 
7810         /// Handles `var' contextual keyword; var becomes a keyword only
7811         /// if no type called var exists in a variable scope
7812         /// 
7813         class VarExpr : SimpleName
7814         {
7815                 public VarExpr (Location loc)
7816                         : base ("var", loc)
7817                 {
7818                 }
7819
7820                 public bool InferType (ResolveContext ec, Expression rhs)
7821                 {
7822                         if (type != null)
7823                                 throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
7824                         
7825                         type = rhs.Type;
7826
7827                         if (type.Kind == MemberKind.Void || InternalType.HasNoType (type) || (rhs is TupleLiteral && TupleLiteral.ContainsNoTypeElement (type))) {
7828                                 ec.Report.Error (815, loc,
7829                                         "An implicitly typed local variable declaration cannot be initialized with `{0}'",
7830                                         type.GetSignatureForError ());
7831                                 type = InternalType.ErrorType;
7832                                 return false;
7833                         }
7834
7835                         eclass = ExprClass.Variable;
7836                         return true;
7837                 }
7838
7839                 protected override void Error_TypeOrNamespaceNotFound (IMemberContext ec)
7840                 {
7841                         if (ec.Module.Compiler.Settings.Version < LanguageVersion.V_3)
7842                                 base.Error_TypeOrNamespaceNotFound (ec);
7843                         else
7844                                 ec.Module.Compiler.Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration");
7845                 }
7846         }
7847 }