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