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