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