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