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