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