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