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