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