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