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