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