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