Added tests for Task.WhenAll w/ empty list
[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                         var cand = candidates;
3298                         arguments.Insert (0, new Argument (ExtensionExpression, Argument.AType.ExtensionType));
3299                         var res = base.OverloadResolve (ec, ref arguments, ehandler ?? this, restr);
3300                         
3301                         // Restore candidates in case we are running in probing mode 
3302                         candidates = cand;
3303
3304                         // Store resolved argument and restore original arguments
3305                         if (res == null) {
3306                                 // Clean-up modified arguments for error reporting
3307                                 arguments.RemoveAt (0);
3308                                 return null;
3309                         }
3310
3311                         var me = ExtensionExpression as MemberExpr;
3312                         if (me != null) {
3313                                 me.ResolveInstanceExpression (ec, null);
3314                                 var fe = me as FieldExpr;
3315                                 if (fe != null)
3316                                         fe.Spec.MemberDefinition.SetIsUsed ();
3317                         }
3318
3319                         InstanceExpression = null;
3320                         return this;
3321                 }
3322
3323                 #region IErrorHandler Members
3324
3325                 bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext rc, MemberSpec best, MemberSpec ambiguous)
3326                 {
3327                         return false;
3328                 }
3329
3330                 bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index)
3331                 {
3332                         rc.Report.SymbolRelatedToPreviousError (best);
3333                         rc.Report.Error (1928, loc,
3334                                 "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' has some invalid arguments",
3335                                 queried_type.GetSignatureForError (), Name, best.GetSignatureForError ());
3336
3337                         if (index == 0) {
3338                                 rc.Report.Error (1929, loc,
3339                                         "Extension method instance type `{0}' cannot be converted to `{1}'",
3340                                         arg.Type.GetSignatureForError (), ((MethodSpec)best).Parameters.ExtensionMethodType.GetSignatureForError ());
3341                         }
3342
3343                         return true;
3344                 }
3345
3346                 bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best)
3347                 {
3348                         return false;
3349                 }
3350
3351                 bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best)
3352                 {
3353                         return false;
3354                 }
3355
3356                 #endregion
3357         }
3358
3359         /// <summary>
3360         ///   MethodGroupExpr represents a group of method candidates which
3361         ///   can be resolved to the best method overload
3362         /// </summary>
3363         public class MethodGroupExpr : MemberExpr, OverloadResolver.IBaseMembersProvider
3364         {
3365                 protected IList<MemberSpec> Methods;
3366                 MethodSpec best_candidate;
3367                 TypeSpec best_candidate_return;
3368                 protected TypeArguments type_arguments;
3369
3370                 SimpleName simple_name;
3371                 protected TypeSpec queried_type;
3372
3373                 public MethodGroupExpr (IList<MemberSpec> mi, TypeSpec type, Location loc)
3374                 {
3375                         Methods = mi;
3376                         this.loc = loc;
3377                         this.type = InternalType.MethodGroup;
3378
3379                         eclass = ExprClass.MethodGroup;
3380                         queried_type = type;
3381                 }
3382
3383                 public MethodGroupExpr (MethodSpec m, TypeSpec type, Location loc)
3384                         : this (new MemberSpec[] { m }, type, loc)
3385                 {
3386                 }
3387
3388                 #region Properties
3389
3390                 public MethodSpec BestCandidate {
3391                         get {
3392                                 return best_candidate;
3393                         }
3394                 }
3395
3396                 public TypeSpec BestCandidateReturnType {
3397                         get {
3398                                 return best_candidate_return;
3399                         }
3400                 }
3401
3402                 public IList<MemberSpec> Candidates {
3403                         get {
3404                                 return Methods;
3405                         }
3406                 }
3407
3408                 protected override TypeSpec DeclaringType {
3409                         get {
3410                                 return queried_type;
3411                         }
3412                 }
3413
3414                 public override bool IsInstance {
3415                         get {
3416                                 if (best_candidate != null)
3417                                         return !best_candidate.IsStatic;
3418
3419                                 return false;
3420                         }
3421                 }
3422
3423                 public override bool IsStatic {
3424                         get {
3425                                 if (best_candidate != null)
3426                                         return best_candidate.IsStatic;
3427
3428                                 return false;
3429                         }
3430                 }
3431
3432                 public override string KindName {
3433                         get { return "method"; }
3434                 }
3435
3436                 public override string Name {
3437                         get {
3438                                 if (best_candidate != null)
3439                                         return best_candidate.Name;
3440
3441                                 // TODO: throw ?
3442                                 return Methods.First ().Name;
3443                         }
3444                 }
3445
3446                 #endregion
3447
3448                 //
3449                 // When best candidate is already know this factory can be used
3450                 // to avoid expensive overload resolution to be called
3451                 //
3452                 // NOTE: InstanceExpression has to be set manually
3453                 //
3454                 public static MethodGroupExpr CreatePredefined (MethodSpec best, TypeSpec queriedType, Location loc)
3455                 {
3456                         return new MethodGroupExpr (best, queriedType, loc) {
3457                                 best_candidate = best,
3458                                 best_candidate_return = best.ReturnType
3459                         };
3460                 }
3461
3462                 public override string GetSignatureForError ()
3463                 {
3464                         if (best_candidate != null)
3465                                 return best_candidate.GetSignatureForError ();
3466
3467                         return Methods.First ().GetSignatureForError ();
3468                 }
3469
3470                 public override Expression CreateExpressionTree (ResolveContext ec)
3471                 {
3472                         if (best_candidate == null) {
3473                                 ec.Report.Error (1953, loc, "An expression tree cannot contain an expression with method group");
3474                                 return null;
3475                         }
3476
3477                         if (best_candidate.IsConditionallyExcluded (ec, loc))
3478                                 ec.Report.Error (765, loc,
3479                                         "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
3480                         
3481                         return new TypeOfMethod (best_candidate, loc);
3482                 }
3483                 
3484                 protected override Expression DoResolve (ResolveContext ec)
3485                 {
3486                         this.eclass = ExprClass.MethodGroup;
3487
3488                         if (InstanceExpression != null) {
3489                                 InstanceExpression = InstanceExpression.Resolve (ec);
3490                                 if (InstanceExpression == null)
3491                                         return null;
3492                         }
3493
3494                         return this;
3495                 }
3496
3497                 public override void Emit (EmitContext ec)
3498                 {
3499                         throw new NotSupportedException ();
3500                 }
3501                 
3502                 public void EmitCall (EmitContext ec, Arguments arguments)
3503                 {
3504                         var call = new CallEmitter ();
3505                         call.InstanceExpression = InstanceExpression;
3506                         call.Emit (ec, best_candidate, arguments, loc);                 
3507                 }
3508
3509                 public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
3510                 {
3511                         ec.Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method",
3512                                 Name, target.GetSignatureForError ());
3513                 }
3514
3515                 public static bool IsExtensionMethodArgument (Expression expr)
3516                 {
3517                         //
3518                         // LAMESPEC: No details about which expressions are not allowed
3519                         //
3520                         return !(expr is TypeExpr) && !(expr is BaseThis);
3521                 }
3522
3523                 /// <summary>
3524                 ///   Find the Applicable Function Members (7.4.2.1)
3525                 ///
3526                 ///   me: Method Group expression with the members to select.
3527                 ///       it might contain constructors or methods (or anything
3528                 ///       that maps to a method).
3529                 ///
3530                 ///   Arguments: ArrayList containing resolved Argument objects.
3531                 ///
3532                 ///   loc: The location if we want an error to be reported, or a Null
3533                 ///        location for "probing" purposes.
3534                 ///
3535                 ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
3536                 ///            that is the best match of me on Arguments.
3537                 ///
3538                 /// </summary>
3539                 public virtual MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments args, OverloadResolver.IErrorHandler cerrors, OverloadResolver.Restrictions restr)
3540                 {
3541                         // TODO: causes issues with probing mode, remove explicit Kind check
3542                         if (best_candidate != null && best_candidate.Kind == MemberKind.Destructor)
3543                                 return this;
3544
3545                         var r = new OverloadResolver (Methods, type_arguments, restr, loc);
3546                         if ((restr & OverloadResolver.Restrictions.NoBaseMembers) == 0) {
3547                                 r.BaseMembersProvider = this;
3548                                 r.InstanceQualifier = this;
3549                         }
3550
3551                         if (cerrors != null)
3552                                 r.CustomErrors = cerrors;
3553
3554                         // TODO: When in probing mode do IsApplicable only and when called again do VerifyArguments for full error reporting
3555                         best_candidate = r.ResolveMember<MethodSpec> (ec, ref args);
3556                         if (best_candidate == null)
3557                                 return r.BestCandidateIsDynamic ? this : null;
3558
3559                         // Overload resolver had to create a new method group, all checks bellow have already been executed
3560                         if (r.BestCandidateNewMethodGroup != null)
3561                                 return r.BestCandidateNewMethodGroup;
3562
3563                         if (best_candidate.Kind == MemberKind.Method && (restr & OverloadResolver.Restrictions.ProbingOnly) == 0) {
3564                                 if (InstanceExpression != null) {
3565                                         if (best_candidate.IsExtensionMethod && args[0].Expr == InstanceExpression) {
3566                                                 InstanceExpression = null;
3567                                         } else {
3568                                                 if (best_candidate.IsStatic && simple_name != null) {
3569                                                         InstanceExpression = ProbeIdenticalTypeName (ec, InstanceExpression, simple_name);
3570                                                 }
3571
3572                                                 InstanceExpression.Resolve (ec);
3573                                         }
3574                                 }
3575
3576                                 ResolveInstanceExpression (ec, null);
3577                         }
3578
3579                         var base_override = CandidateToBaseOverride (ec, best_candidate);
3580                         if (base_override == best_candidate) {
3581                                 best_candidate_return = r.BestCandidateReturnType;
3582                         } else {
3583                                 best_candidate = base_override;
3584                                 best_candidate_return = best_candidate.ReturnType;
3585                         }
3586
3587                         if (best_candidate.IsGeneric && (restr & OverloadResolver.Restrictions.ProbingOnly) == 0 && TypeParameterSpec.HasAnyTypeParameterConstrained (best_candidate.GenericDefinition)) {
3588                                 ConstraintChecker cc = new ConstraintChecker (ec);
3589                                 cc.CheckAll (best_candidate.GetGenericMethodDefinition (), best_candidate.TypeArguments, best_candidate.Constraints, loc);
3590                         }
3591
3592                         //
3593                         // Additional check for possible imported base override method which
3594                         // could not be done during IsOverrideMethodBaseTypeAccessible
3595                         //
3596                         if (best_candidate.IsVirtual && (best_candidate.DeclaringType.Modifiers & Modifiers.PROTECTED) != 0 &&
3597                                 best_candidate.MemberDefinition.IsImported && !best_candidate.DeclaringType.IsAccessible (ec)) {
3598                                 ec.Report.SymbolRelatedToPreviousError (best_candidate);
3599                                 ErrorIsInaccesible (ec, best_candidate.GetSignatureForError (), loc);
3600                         }
3601
3602                         return this;
3603                 }
3604
3605                 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
3606                 {
3607                         var fe = left as FieldExpr;
3608                         if (fe != null) {
3609                                 //
3610                                 // Using method-group on struct fields makes the struct assigned. I am not sure
3611                                 // why but that's what .net does
3612                                 //
3613                                 fe.Spec.MemberDefinition.SetIsAssigned ();
3614                         }
3615
3616                         simple_name = original;
3617                         return base.ResolveMemberAccess (ec, left, original);
3618                 }
3619
3620                 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
3621                 {
3622                         type_arguments = ta;
3623                 }
3624
3625                 #region IBaseMembersProvider Members
3626
3627                 public virtual IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
3628                 {
3629                         return baseType == null ? null : MemberCache.FindMembers (baseType, Methods [0].Name, false);
3630                 }
3631
3632                 public IParametersMember GetOverrideMemberParameters (MemberSpec member)
3633                 {
3634                         if (queried_type == member.DeclaringType)
3635                                 return null;
3636
3637                         return MemberCache.FindMember (queried_type, new MemberFilter ((MethodSpec) member),
3638                                 BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly) as IParametersMember;
3639                 }
3640
3641                 //
3642                 // Extension methods lookup after ordinary methods candidates failed to apply
3643                 //
3644                 public virtual MethodGroupExpr LookupExtensionMethod (ResolveContext rc)
3645                 {
3646                         if (InstanceExpression == null)
3647                                 return null;
3648
3649                         InstanceExpression = InstanceExpression.Resolve (rc);
3650                         if (!IsExtensionMethodArgument (InstanceExpression))
3651                                 return null;
3652
3653                         int arity = type_arguments == null ? 0 : type_arguments.Count;
3654                         var methods = rc.LookupExtensionMethod (InstanceExpression.Type, Methods[0].Name, arity);
3655                         if (methods == null)
3656                                 return null;
3657
3658                         var emg = new ExtensionMethodGroupExpr (methods, InstanceExpression, loc);
3659                         emg.SetTypeArguments (rc, type_arguments);
3660                         return emg;
3661                 }
3662
3663                 #endregion
3664         }
3665
3666         struct ConstructorInstanceQualifier : OverloadResolver.IInstanceQualifier
3667         {
3668                 public ConstructorInstanceQualifier (TypeSpec type)
3669                         : this ()
3670                 {
3671                         InstanceType = type;
3672                 }
3673
3674                 public TypeSpec InstanceType { get; private set; }
3675
3676                 public bool CheckProtectedMemberAccess (ResolveContext rc, MemberSpec member)
3677                 {
3678                         return MemberExpr.CheckProtectedMemberAccess (rc, member, InstanceType);
3679                 }
3680         }
3681
3682         public struct OverloadResolver
3683         {
3684                 [Flags]
3685                 public enum Restrictions
3686                 {
3687                         None = 0,
3688                         DelegateInvoke = 1,
3689                         ProbingOnly     = 1 << 1,
3690                         CovariantDelegate = 1 << 2,
3691                         NoBaseMembers = 1 << 3,
3692                         BaseMembersIncluded = 1 << 4
3693                 }
3694
3695                 public interface IBaseMembersProvider
3696                 {
3697                         IList<MemberSpec> GetBaseMembers (TypeSpec baseType);
3698                         IParametersMember GetOverrideMemberParameters (MemberSpec member);
3699                         MethodGroupExpr LookupExtensionMethod (ResolveContext rc);
3700                 }
3701
3702                 public interface IErrorHandler
3703                 {
3704                         bool AmbiguousCandidates (ResolveContext rc, MemberSpec best, MemberSpec ambiguous);
3705                         bool ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument a, int index);
3706                         bool NoArgumentMatch (ResolveContext rc, MemberSpec best);
3707                         bool TypeInferenceFailed (ResolveContext rc, MemberSpec best);
3708                 }
3709
3710                 public interface IInstanceQualifier
3711                 {
3712                         TypeSpec InstanceType { get; }
3713                         bool CheckProtectedMemberAccess (ResolveContext rc, MemberSpec member);
3714                 }
3715
3716                 sealed class NoBaseMembers : IBaseMembersProvider
3717                 {
3718                         public static readonly IBaseMembersProvider Instance = new NoBaseMembers ();
3719
3720                         public IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
3721                         {
3722                                 return null;
3723                         }
3724
3725                         public IParametersMember GetOverrideMemberParameters (MemberSpec member)
3726                         {
3727                                 return null;
3728                         }
3729
3730                         public MethodGroupExpr LookupExtensionMethod (ResolveContext rc)
3731                         {
3732                                 return null;
3733                         }
3734                 }
3735
3736                 struct AmbiguousCandidate
3737                 {
3738                         public readonly MemberSpec Member;
3739                         public readonly bool Expanded;
3740                         public readonly AParametersCollection Parameters;
3741
3742                         public AmbiguousCandidate (MemberSpec member, AParametersCollection parameters, bool expanded)
3743                         {
3744                                 Member = member;
3745                                 Parameters = parameters;
3746                                 Expanded = expanded;
3747                         }
3748                 }
3749
3750                 Location loc;
3751                 IList<MemberSpec> members;
3752                 TypeArguments type_arguments;
3753                 IBaseMembersProvider base_provider;
3754                 IErrorHandler custom_errors;
3755                 IInstanceQualifier instance_qualifier;
3756                 Restrictions restrictions;
3757                 MethodGroupExpr best_candidate_extension_group;
3758                 TypeSpec best_candidate_return_type;
3759
3760                 SessionReportPrinter lambda_conv_msgs;
3761
3762                 public OverloadResolver (IList<MemberSpec> members, Restrictions restrictions, Location loc)
3763                         : this (members, null, restrictions, loc)
3764                 {
3765                 }
3766
3767                 public OverloadResolver (IList<MemberSpec> members, TypeArguments targs, Restrictions restrictions, Location loc)
3768                         : this ()
3769                 {
3770                         if (members == null || members.Count == 0)
3771                                 throw new ArgumentException ("empty members set");
3772
3773                         this.members = members;
3774                         this.loc = loc;
3775                         type_arguments = targs;
3776                         this.restrictions = restrictions;
3777                         if (IsDelegateInvoke)
3778                                 this.restrictions |= Restrictions.NoBaseMembers;
3779
3780                         base_provider = NoBaseMembers.Instance;
3781                 }
3782
3783                 #region Properties
3784
3785                 public IBaseMembersProvider BaseMembersProvider {
3786                         get {
3787                                 return base_provider;
3788                         }
3789                         set {
3790                                 base_provider = value;
3791                         }
3792                 }
3793
3794                 public bool BestCandidateIsDynamic { get; set; }
3795
3796                 //
3797                 // Best candidate was found in newly created MethodGroupExpr, used by extension methods
3798                 //
3799                 public MethodGroupExpr BestCandidateNewMethodGroup {
3800                         get {
3801                                 return best_candidate_extension_group;
3802                         }
3803                 }
3804
3805                 //
3806                 // Return type can be different between best candidate and closest override
3807                 //
3808                 public TypeSpec BestCandidateReturnType {
3809                         get {
3810                                 return best_candidate_return_type;
3811                         }
3812                 }
3813
3814                 public IErrorHandler CustomErrors {
3815                         get {
3816                                 return custom_errors;
3817                         }
3818                         set {
3819                                 custom_errors = value;
3820                         }
3821                 }
3822
3823                 TypeSpec DelegateType {
3824                         get {
3825                                 if ((restrictions & Restrictions.DelegateInvoke) == 0)
3826                                         throw new InternalErrorException ("Not running in delegate mode", loc);
3827
3828                                 return members [0].DeclaringType;
3829                         }
3830                 }
3831
3832                 public IInstanceQualifier InstanceQualifier {
3833                         get {
3834                                 return instance_qualifier;
3835                         }
3836                         set {
3837                                 instance_qualifier = value;
3838                         }
3839                 }
3840
3841                 bool IsProbingOnly {
3842                         get {
3843                                 return (restrictions & Restrictions.ProbingOnly) != 0;
3844                         }
3845                 }
3846
3847                 bool IsDelegateInvoke {
3848                         get {
3849                                 return (restrictions & Restrictions.DelegateInvoke) != 0;
3850                         }
3851                 }
3852
3853                 #endregion
3854
3855                 //
3856                 //  7.4.3.3  Better conversion from expression
3857                 //  Returns :   1    if a->p is better,
3858                 //              2    if a->q is better,
3859                 //              0 if neither is better
3860                 //
3861                 static int BetterExpressionConversion (ResolveContext ec, Argument a, TypeSpec p, TypeSpec q)
3862                 {
3863                         TypeSpec argument_type = a.Type;
3864
3865                         //
3866                         // If argument is an anonymous function
3867                         //
3868                         if (argument_type == InternalType.AnonymousMethod && ec.Module.Compiler.Settings.Version > LanguageVersion.ISO_2) {
3869                                 //
3870                                 // p and q are delegate types or expression tree types
3871                                 //
3872                                 if (p.IsExpressionTreeType || q.IsExpressionTreeType) {
3873                                         if (q.MemberDefinition != p.MemberDefinition) {
3874                                                 return 0;
3875                                         }
3876
3877                                         //
3878                                         // Uwrap delegate from Expression<T>
3879                                         //
3880                                         q = TypeManager.GetTypeArguments (q)[0];
3881                                         p = TypeManager.GetTypeArguments (p)[0];
3882                                 }
3883
3884                                 var p_m = Delegate.GetInvokeMethod (p);
3885                                 var q_m = Delegate.GetInvokeMethod (q);
3886
3887                                 //
3888                                 // With identical parameter lists
3889                                 //
3890                                 if (!TypeSpecComparer.Equals (p_m.Parameters.Types, q_m.Parameters.Types))
3891                                         return 0;
3892
3893                                 var orig_p = p;
3894                                 p = p_m.ReturnType;
3895                                 var orig_q = q;
3896                                 q = q_m.ReturnType;
3897
3898                                 //
3899                                 // if p is void returning, and q has a return type Y, then C2 is the better conversion.
3900                                 //
3901                                 if (p.Kind == MemberKind.Void) {
3902                                         return q.Kind != MemberKind.Void ? 2 : 0;
3903                                 }
3904
3905                                 //
3906                                 // if p has a return type Y, and q is void returning, then C1 is the better conversion.
3907                                 //
3908                                 if (q.Kind == MemberKind.Void) {
3909                                         return p.Kind != MemberKind.Void ? 1: 0;
3910                                 }
3911
3912                                 var am = (AnonymousMethodExpression) a.Expr;
3913
3914                                 //
3915                                 // When anonymous method is an asynchronous, and P has a return type Task<Y1>, and Q has a return type Task<Y2>
3916                                 // better conversion is performed between underlying types Y1 and Y2
3917                                 //
3918                                 if (p.IsGenericTask || q.IsGenericTask) {
3919                                         if (am.Block.IsAsync && p.IsGenericTask && q.IsGenericTask) {
3920                                                 q = q.TypeArguments[0];
3921                                                 p = p.TypeArguments[0];
3922                                         }
3923                                 } else if (q != p) {
3924                                         //
3925                                         // LAMESPEC: Lambda expression returning dynamic type has identity (better) conversion to delegate returning object type
3926                                         //
3927                                         if (q.BuiltinType == BuiltinTypeSpec.Type.Object) {
3928                                                 var am_rt = am.InferReturnType (ec, null, orig_q);
3929                                                 if (am_rt != null && am_rt.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
3930                                                         return 2;
3931                                         } else if (p.BuiltinType == BuiltinTypeSpec.Type.Object) {
3932                                                 var am_rt = am.InferReturnType (ec, null, orig_p);
3933                                                 if (am_rt != null && am_rt.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
3934                                                         return 1;
3935                                         }
3936                                 }
3937
3938                                 //
3939                                 // The parameters are identicial and return type is not void, use better type conversion
3940                                 // on return type to determine better one
3941                                 //
3942                         } else {
3943                                 if (argument_type == p)
3944                                         return 1;
3945
3946                                 if (argument_type == q)
3947                                         return 2;
3948                         }
3949
3950                         return BetterTypeConversion (ec, p, q);
3951                 }
3952
3953                 //
3954                 // 7.4.3.4  Better conversion from type
3955                 //
3956                 public static int BetterTypeConversion (ResolveContext ec, TypeSpec p, TypeSpec q)
3957                 {
3958                         if (p == null || q == null)
3959                                 throw new InternalErrorException ("BetterTypeConversion got a null conversion");
3960
3961                         switch (p.BuiltinType) {
3962                         case BuiltinTypeSpec.Type.Int:
3963                                 if (q.BuiltinType == BuiltinTypeSpec.Type.UInt || q.BuiltinType == BuiltinTypeSpec.Type.ULong)
3964                                         return 1;
3965                                 break;
3966                         case BuiltinTypeSpec.Type.Long:
3967                                 if (q.BuiltinType == BuiltinTypeSpec.Type.ULong)
3968                                         return 1;
3969                                 break;
3970                         case BuiltinTypeSpec.Type.SByte:
3971                                 switch (q.BuiltinType) {
3972                                 case BuiltinTypeSpec.Type.Byte:
3973                                 case BuiltinTypeSpec.Type.UShort:
3974                                 case BuiltinTypeSpec.Type.UInt:
3975                                 case BuiltinTypeSpec.Type.ULong:
3976                                         return 1;
3977                                 }
3978                                 break;
3979                         case BuiltinTypeSpec.Type.Short:
3980                                 switch (q.BuiltinType) {
3981                                 case BuiltinTypeSpec.Type.UShort:
3982                                 case BuiltinTypeSpec.Type.UInt:
3983                                 case BuiltinTypeSpec.Type.ULong:
3984                                         return 1;
3985                                 }
3986                                 break;
3987                         case BuiltinTypeSpec.Type.Dynamic:
3988                                 // Dynamic is never better
3989                                 return 2;
3990                         }
3991
3992                         switch (q.BuiltinType) {
3993                         case BuiltinTypeSpec.Type.Int:
3994                                 if (p.BuiltinType == BuiltinTypeSpec.Type.UInt || p.BuiltinType == BuiltinTypeSpec.Type.ULong)
3995                                         return 2;
3996                                 break;
3997                         case BuiltinTypeSpec.Type.Long:
3998                                 if (p.BuiltinType == BuiltinTypeSpec.Type.ULong)
3999                                         return 2;
4000                                 break;
4001                         case BuiltinTypeSpec.Type.SByte:
4002                                 switch (p.BuiltinType) {
4003                                 case BuiltinTypeSpec.Type.Byte:
4004                                 case BuiltinTypeSpec.Type.UShort:
4005                                 case BuiltinTypeSpec.Type.UInt:
4006                                 case BuiltinTypeSpec.Type.ULong:
4007                                         return 2;
4008                                 }
4009                                 break;
4010                         case BuiltinTypeSpec.Type.Short:
4011                                 switch (p.BuiltinType) {
4012                                 case BuiltinTypeSpec.Type.UShort:
4013                                 case BuiltinTypeSpec.Type.UInt:
4014                                 case BuiltinTypeSpec.Type.ULong:
4015                                         return 2;
4016                                 }
4017                                 break;
4018                         case BuiltinTypeSpec.Type.Dynamic:
4019                                 // Dynamic is never better
4020                                 return 1;
4021                         }
4022
4023                         // FIXME: handle lifted operators
4024
4025                         // TODO: this is expensive
4026                         Expression p_tmp = new EmptyExpression (p);
4027                         Expression q_tmp = new EmptyExpression (q);
4028
4029                         bool p_to_q = Convert.ImplicitConversionExists (ec, p_tmp, q);
4030                         bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p);
4031
4032                         if (p_to_q && !q_to_p)
4033                                 return 1;
4034
4035                         if (q_to_p && !p_to_q)
4036                                 return 2;
4037
4038                         return 0;
4039                 }
4040
4041                 /// <summary>
4042                 ///   Determines "Better function" between candidate
4043                 ///   and the current best match
4044                 /// </summary>
4045                 /// <remarks>
4046                 ///    Returns a boolean indicating :
4047                 ///     false if candidate ain't better
4048                 ///     true  if candidate is better than the current best match
4049                 /// </remarks>
4050                 static bool BetterFunction (ResolveContext ec, Arguments args, MemberSpec candidate, AParametersCollection cparam, bool candidate_params,
4051                         MemberSpec best, AParametersCollection bparam, bool best_params)
4052                 {
4053                         AParametersCollection candidate_pd = ((IParametersMember) candidate).Parameters;
4054                         AParametersCollection best_pd = ((IParametersMember) best).Parameters;
4055
4056                         bool better_at_least_one = false;
4057                         bool same = true;
4058                         int args_count = args == null ? 0 : args.Count;
4059                         int j = 0;
4060                         Argument a = null;
4061                         TypeSpec ct, bt;
4062                         for (int c_idx = 0, b_idx = 0; j < args_count; ++j, ++c_idx, ++b_idx) {
4063                                 a = args[j];
4064
4065                                 // Default arguments are ignored for better decision
4066                                 if (a.IsDefaultArgument)
4067                                         break;
4068
4069                                 //
4070                                 // When comparing named argument the parameter type index has to be looked up
4071                                 // in original parameter set (override version for virtual members)
4072                                 //
4073                                 NamedArgument na = a as NamedArgument;
4074                                 if (na != null) {
4075                                         int idx = cparam.GetParameterIndexByName (na.Name);
4076                                         ct = candidate_pd.Types[idx];
4077                                         if (candidate_params && candidate_pd.FixedParameters[idx].ModFlags == Parameter.Modifier.PARAMS)
4078                                                 ct = TypeManager.GetElementType (ct);
4079
4080                                         idx = bparam.GetParameterIndexByName (na.Name);
4081                                         bt = best_pd.Types[idx];
4082                                         if (best_params && best_pd.FixedParameters[idx].ModFlags == Parameter.Modifier.PARAMS)
4083                                                 bt = TypeManager.GetElementType (bt);
4084                                 } else {
4085                                         ct = candidate_pd.Types[c_idx];
4086                                         bt = best_pd.Types[b_idx];
4087
4088                                         if (candidate_params && candidate_pd.FixedParameters[c_idx].ModFlags == Parameter.Modifier.PARAMS) {
4089                                                 ct = TypeManager.GetElementType (ct);
4090                                                 --c_idx;
4091                                         }
4092
4093                                         if (best_params && best_pd.FixedParameters[b_idx].ModFlags == Parameter.Modifier.PARAMS) {
4094                                                 bt = TypeManager.GetElementType (bt);
4095                                                 --b_idx;
4096                                         }
4097                                 }
4098
4099                                 if (TypeSpecComparer.IsEqual (ct, bt))
4100                                         continue;
4101
4102                                 same = false;
4103                                 int result = BetterExpressionConversion (ec, a, ct, bt);
4104
4105                                 // for each argument, the conversion to 'ct' should be no worse than 
4106                                 // the conversion to 'bt'.
4107                                 if (result == 2)
4108                                         return false;
4109
4110                                 // for at least one argument, the conversion to 'ct' should be better than 
4111                                 // the conversion to 'bt'.
4112                                 if (result != 0)
4113                                         better_at_least_one = true;
4114                         }
4115
4116                         if (better_at_least_one)
4117                                 return true;
4118
4119                         //
4120                         // This handles the case
4121                         //
4122                         //   Add (float f1, float f2, float f3);
4123                         //   Add (params decimal [] foo);
4124                         //
4125                         // The call Add (3, 4, 5) should be ambiguous.  Without this check, the
4126                         // first candidate would've chosen as better.
4127                         //
4128                         if (!same && !a.IsDefaultArgument)
4129                                 return false;
4130
4131                         //
4132                         // The two methods have equal non-optional parameter types, apply tie-breaking rules
4133                         //
4134
4135                         //
4136                         // This handles the following cases:
4137                         //
4138                         //  Foo (int i) is better than Foo (int i, long l = 0)
4139                         //  Foo (params int[] args) is better than Foo (int i = 0, params int[] args)
4140                         //  Foo (string s, params string[] args) is better than Foo (params string[] args)
4141                         //
4142                         // Prefer non-optional version
4143                         //
4144                         // LAMESPEC: Specification claims this should be done at last but the opposite is true
4145                         //
4146                         if (candidate_params == best_params && candidate_pd.Count != best_pd.Count) {
4147                                 if (j < candidate_pd.Count && candidate_pd.FixedParameters[j].HasDefaultValue)
4148                                         return false;
4149
4150                                 if (j < best_pd.Count && best_pd.FixedParameters[j].HasDefaultValue)
4151                                         return true;
4152
4153                                 return candidate_pd.Count >= best_pd.Count;
4154                         }
4155
4156                         //
4157                         // One is a non-generic method and second is a generic method, then non-generic is better
4158                         //
4159                         if (best.IsGeneric != candidate.IsGeneric)
4160                                 return best.IsGeneric;
4161
4162                         //
4163                         // This handles the following cases:
4164                         //
4165                         //   Trim () is better than Trim (params char[] chars)
4166                         //   Concat (string s1, string s2, string s3) is better than
4167                         //     Concat (string s1, params string [] srest)
4168                         //   Foo (int, params int [] rest) is better than Foo (params int [] rest)
4169                         //
4170                         // Prefer non-expanded version
4171                         //
4172                         if (candidate_params != best_params)
4173                                 return best_params;
4174
4175                         int candidate_param_count = candidate_pd.Count;
4176                         int best_param_count = best_pd.Count;
4177
4178                         if (candidate_param_count != best_param_count)
4179                                 // can only happen if (candidate_params && best_params)
4180                                 return candidate_param_count > best_param_count && best_pd.HasParams;
4181
4182                         //
4183                         // Both methods have the same number of parameters, and the parameters have equal types
4184                         // Pick the "more specific" signature using rules over original (non-inflated) types
4185                         //
4186                         var candidate_def_pd = ((IParametersMember) candidate.MemberDefinition).Parameters;
4187                         var best_def_pd = ((IParametersMember) best.MemberDefinition).Parameters;
4188
4189                         bool specific_at_least_once = false;
4190                         for (j = 0; j < args_count; ++j) {
4191                                 NamedArgument na = args_count == 0 ? null : args [j] as NamedArgument;
4192                                 if (na != null) {
4193                                         ct = candidate_def_pd.Types[cparam.GetParameterIndexByName (na.Name)];
4194                                         bt = best_def_pd.Types[bparam.GetParameterIndexByName (na.Name)];
4195                                 } else {
4196                                         ct = candidate_def_pd.Types[j];
4197                                         bt = best_def_pd.Types[j];
4198                                 }
4199
4200                                 if (ct == bt)
4201                                         continue;
4202                                 TypeSpec specific = MoreSpecific (ct, bt);
4203                                 if (specific == bt)
4204                                         return false;
4205                                 if (specific == ct)
4206                                         specific_at_least_once = true;
4207                         }
4208
4209                         if (specific_at_least_once)
4210                                 return true;
4211
4212                         return false;
4213                 }
4214
4215                 static bool CheckInflatedArguments (MethodSpec ms)
4216                 {
4217                         if (!TypeParameterSpec.HasAnyTypeParameterTypeConstrained (ms.GenericDefinition))
4218                                 return true;
4219
4220                         // Setup constraint checker for probing only
4221                         ConstraintChecker cc = new ConstraintChecker (null);
4222
4223                         var mp = ms.Parameters.Types;
4224                         for (int i = 0; i < mp.Length; ++i) {
4225                                 var type = mp[i] as InflatedTypeSpec;
4226                                 if (type == null)
4227                                         continue;
4228
4229                                 var targs = type.TypeArguments;
4230                                 if (targs.Length == 0)
4231                                         continue;
4232
4233                                 // TODO: Checking inflated MVAR arguments should be enough
4234                                 if (!cc.CheckAll (type.GetDefinition (), targs, type.Constraints, Location.Null))
4235                                         return false;
4236                         }
4237
4238                         return true;
4239                 }
4240
4241                 public static void Error_ConstructorMismatch (ResolveContext rc, TypeSpec type, int argCount, Location loc)
4242                 {
4243                         rc.Report.Error (1729, loc,
4244                                 "The type `{0}' does not contain a constructor that takes `{1}' arguments",
4245                                 type.GetSignatureForError (), argCount.ToString ());
4246                 }
4247
4248                 //
4249                 // Determines if the candidate method is applicable to the given set of arguments
4250                 // There could be two different set of parameters for same candidate where one
4251                 // is the closest override for default values and named arguments checks and second
4252                 // one being the virtual base for the parameter types and modifiers.
4253                 //
4254                 // A return value rates candidate method compatibility,
4255                 // 0 = the best, int.MaxValue = the worst
4256                 // -1 = fatal error
4257                 //
4258                 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)
4259                 {
4260                         // Parameters of most-derived type used mainly for named and optional parameters
4261                         var pd = pm.Parameters;
4262
4263                         // Used for params modifier only, that's legacy of C# 1.0 which uses base type for
4264                         // params modifier instead of most-derived type
4265                         var cpd = ((IParametersMember) candidate).Parameters;
4266                         int param_count = pd.Count;
4267                         int optional_count = 0;
4268                         int score;
4269                         Arguments orig_args = arguments;
4270
4271                         if (arg_count != param_count) {
4272                                 //
4273                                 // No arguments expansion when doing exact match for delegates
4274                                 //
4275                                 if ((restrictions & Restrictions.CovariantDelegate) == 0) {
4276                                         for (int i = 0; i < pd.Count; ++i) {
4277                                                 if (pd.FixedParameters[i].HasDefaultValue) {
4278                                                         optional_count = pd.Count - i;
4279                                                         break;
4280                                                 }
4281                                         }
4282                                 }
4283
4284                                 if (optional_count != 0) {
4285                                         // Readjust expected number when params used
4286                                         if (cpd.HasParams) {
4287                                                 optional_count--;
4288                                                 if (arg_count < param_count)
4289                                                         param_count--;
4290                                         } else if (arg_count > param_count) {
4291                                                 int args_gap = System.Math.Abs (arg_count - param_count);
4292                                                 return int.MaxValue - 10000 + args_gap;
4293                                         } else if (arg_count < param_count - optional_count) {
4294                                                 int args_gap = System.Math.Abs (param_count - optional_count - arg_count);
4295                                                 return int.MaxValue - 10000 + args_gap;
4296                                         }
4297                                 } else if (arg_count != param_count) {
4298                                         int args_gap = System.Math.Abs (arg_count - param_count);
4299                                         if (!cpd.HasParams)
4300                                                 return int.MaxValue - 10000 + args_gap;
4301                                         if (arg_count < param_count - 1)
4302                                                 return int.MaxValue - 10000 + args_gap;
4303                                 }
4304
4305                                 // Resize to fit optional arguments
4306                                 if (optional_count != 0) {
4307                                         if (arguments == null) {
4308                                                 arguments = new Arguments (optional_count);
4309                                         } else {
4310                                                 // Have to create a new container, so the next run can do same
4311                                                 var resized = new Arguments (param_count);
4312                                                 resized.AddRange (arguments);
4313                                                 arguments = resized;
4314                                         }
4315
4316                                         for (int i = arg_count; i < param_count; ++i)
4317                                                 arguments.Add (null);
4318                                 }
4319                         }
4320
4321                         if (arg_count > 0) {
4322                                 //
4323                                 // Shuffle named arguments to the right positions if there are any
4324                                 //
4325                                 if (arguments[arg_count - 1] is NamedArgument) {
4326                                         arg_count = arguments.Count;
4327
4328                                         for (int i = 0; i < arg_count; ++i) {
4329                                                 bool arg_moved = false;
4330                                                 while (true) {
4331                                                         NamedArgument na = arguments[i] as NamedArgument;
4332                                                         if (na == null)
4333                                                                 break;
4334
4335                                                         int index = pd.GetParameterIndexByName (na.Name);
4336
4337                                                         // Named parameter not found
4338                                                         if (index < 0)
4339                                                                 return (i + 1) * 3;
4340
4341                                                         // already reordered
4342                                                         if (index == i)
4343                                                                 break;
4344
4345                                                         Argument temp;
4346                                                         if (index >= param_count) {
4347                                                                 // When using parameters which should not be available to the user
4348                                                                 if ((cpd.FixedParameters[index].ModFlags & Parameter.Modifier.PARAMS) == 0)
4349                                                                         break;
4350
4351                                                                 arguments.Add (null);
4352                                                                 ++arg_count;
4353                                                                 temp = null;
4354                                                         } else {
4355                                                                 temp = arguments[index];
4356
4357                                                                 // The slot has been taken by positional argument
4358                                                                 if (temp != null && !(temp is NamedArgument))
4359                                                                         break;
4360                                                         }
4361
4362                                                         if (!arg_moved) {
4363                                                                 arguments = arguments.MarkOrderedArgument (na);
4364                                                                 arg_moved = true;
4365                                                         }
4366
4367                                                         arguments[index] = arguments[i];
4368                                                         arguments[i] = temp;
4369
4370                                                         if (temp == null)
4371                                                                 break;
4372                                                 }
4373                                         }
4374                                 } else {
4375                                         arg_count = arguments.Count;
4376                                 }
4377                         } else if (arguments != null) {
4378                                 arg_count = arguments.Count;
4379                         }
4380
4381                         //
4382                         // Don't do any expensive checks when the candidate cannot succeed
4383                         //
4384                         if (arg_count != param_count && !cpd.HasParams)
4385                                 return (param_count - arg_count) * 2 + 1;
4386
4387                         var dep = candidate.GetMissingDependencies ();
4388                         if (dep != null) {
4389                                 ImportedTypeDefinition.Error_MissingDependency (ec, dep, loc);
4390                                 return -1;
4391                         }
4392
4393                         //
4394                         // 1. Handle generic method using type arguments when specified or type inference
4395                         //
4396                         TypeSpec[] ptypes;
4397                         var ms = candidate as MethodSpec;
4398                         if (ms != null && ms.IsGeneric) {
4399                                 if (type_arguments != null) {
4400                                         var g_args_count = ms.Arity;
4401                                         if (g_args_count != type_arguments.Count)
4402                                                 return int.MaxValue - 20000 + System.Math.Abs (type_arguments.Count - g_args_count);
4403
4404                                         ms = ms.MakeGenericMethod (ec, type_arguments.Arguments);
4405                                 } else {
4406                                         //
4407                                         // Deploy custom error reporting for infered anonymous expression or lambda methods. When
4408                                         // probing lambda methods keep all errors reported in separate set and once we are done and no best
4409                                         // candidate was found use the set to report more details about what was wrong with lambda body.
4410                                         // The general idea is to distinguish between code errors and errors caused by
4411                                         // trial-and-error type inference
4412                                         //
4413                                         if (lambda_conv_msgs == null) {
4414                                                 for (int i = 0; i < arg_count; i++) {
4415                                                         Argument a = arguments[i];
4416                                                         if (a == null)
4417                                                                 continue;
4418
4419                                                         var am = a.Expr as AnonymousMethodExpression;
4420                                                         if (am != null) {
4421                                                                 if (lambda_conv_msgs == null)
4422                                                                         lambda_conv_msgs = new SessionReportPrinter ();
4423
4424                                                                 am.TypeInferenceReportPrinter = lambda_conv_msgs;
4425                                                         }
4426                                                 }
4427                                         }
4428
4429                                         var ti = new TypeInference (arguments);
4430                                         TypeSpec[] i_args = ti.InferMethodArguments (ec, ms);
4431
4432                                         if (i_args == null)
4433                                                 return ti.InferenceScore - 20000;
4434
4435                                         //
4436                                         // Clear any error messages when the result was success
4437                                         //
4438                                         if (lambda_conv_msgs != null)
4439                                                 lambda_conv_msgs.ClearSession ();
4440
4441                                         if (i_args.Length != 0) {
4442                                                 ms = ms.MakeGenericMethod (ec, i_args);
4443                                         }
4444                                 }
4445
4446                                 //
4447                                 // Type arguments constraints have to match for the method to be applicable
4448                                 //
4449                                 if (!CheckInflatedArguments (ms)) {
4450                                         candidate = ms;
4451                                         return int.MaxValue - 25000;
4452                                 }
4453
4454                                 //
4455                                 // We have a generic return type and at same time the method is override which
4456                                 // means we have to also inflate override return type in case the candidate is
4457                                 // best candidate and override return type is different to base return type.
4458                                 // 
4459                                 // virtual Foo<T, object> with override Foo<T, dynamic>
4460                                 //
4461                                 if (candidate != pm) {
4462                                         MethodSpec override_ms = (MethodSpec) pm;
4463                                         var inflator = new TypeParameterInflator (ec, ms.DeclaringType, override_ms.GenericDefinition.TypeParameters, ms.TypeArguments);
4464                                         returnType = inflator.Inflate (returnType);
4465                                 } else {
4466                                         returnType = ms.ReturnType;
4467                                 }
4468
4469                                 candidate = ms;
4470                                 pd = ms.Parameters;
4471                                 ptypes = pd.Types;
4472                         } else {
4473                                 if (type_arguments != null)
4474                                         return int.MaxValue - 15000;
4475
4476                                 ptypes = cpd.Types;
4477                         }
4478
4479                         //
4480                         // 2. Each argument has to be implicitly convertible to method parameter
4481                         //
4482                         Parameter.Modifier p_mod = 0;
4483                         TypeSpec pt = null;
4484
4485                         for (int i = 0; i < arg_count; i++) {
4486                                 Argument a = arguments[i];
4487                                 if (a == null) {
4488                                         var fp = pd.FixedParameters[i];
4489                                         if (!fp.HasDefaultValue) {
4490                                                 arguments = orig_args;
4491                                                 return arg_count * 2 + 2;
4492                                         }
4493
4494                                         //
4495                                         // Get the default value expression, we can use the same expression
4496                                         // if the type matches
4497                                         //
4498                                         Expression e = fp.DefaultValue;
4499                                         if (e != null) {
4500                                                 e = ResolveDefaultValueArgument (ec, ptypes[i], e, loc);
4501                                                 if (e == null) {
4502                                                         // Restore for possible error reporting
4503                                                         for (int ii = i; ii < arg_count; ++ii)
4504                                                                 arguments.RemoveAt (i);
4505
4506                                                         return (arg_count - i) * 2 + 1;
4507                                                 }
4508                                         }
4509
4510                                         if ((fp.ModFlags & Parameter.Modifier.CallerMask) != 0) {
4511                                                 //
4512                                                 // LAMESPEC: Attributes can be mixed together with build-in priority
4513                                                 //
4514                                                 if ((fp.ModFlags & Parameter.Modifier.CallerLineNumber) != 0) {
4515                                                         e = new IntLiteral (ec.BuiltinTypes, loc.Row, loc);
4516                                                 } else if ((fp.ModFlags & Parameter.Modifier.CallerFilePath) != 0) {
4517                                                         e = new StringLiteral (ec.BuiltinTypes, loc.NameFullPath, loc);
4518                                                 } else if (ec.MemberContext.CurrentMemberDefinition != null) {
4519                                                         e = new StringLiteral (ec.BuiltinTypes, ec.MemberContext.CurrentMemberDefinition.GetCallerMemberName (), loc);
4520                                                 }
4521                                         }
4522
4523                                         arguments[i] = new Argument (e, Argument.AType.Default);
4524                                         continue;
4525                                 }
4526
4527                                 if (p_mod != Parameter.Modifier.PARAMS) {
4528                                         p_mod = (pd.FixedParameters[i].ModFlags & ~Parameter.Modifier.PARAMS) | (cpd.FixedParameters[i].ModFlags & Parameter.Modifier.PARAMS);
4529                                         pt = ptypes [i];
4530                                 } else if (!params_expanded_form) {
4531                                         params_expanded_form = true;
4532                                         pt = ((ElementTypeSpec) pt).Element;
4533                                         i -= 2;
4534                                         continue;
4535                                 }
4536
4537                                 score = 1;
4538                                 if (!params_expanded_form) {
4539                                         if (a.ArgType == Argument.AType.ExtensionType) {
4540                                                 //
4541                                                 // Indentity, implicit reference or boxing conversion must exist for the extension parameter
4542                                                 //
4543                                                 // LAMESPEC: or implicit type parameter conversion
4544                                                 //
4545                                                 var at = a.Type;
4546                                                 if (at == pt || TypeSpecComparer.IsEqual (at, pt) ||
4547                                                         Convert.ImplicitReferenceConversionExists (at, pt, false) ||
4548                                                         Convert.ImplicitBoxingConversion (null, at, pt) != null) {
4549                                                         score = 0;
4550                                                         continue;
4551                                                 }
4552                                         } else {
4553                                                 score = IsArgumentCompatible (ec, a, p_mod, pt);
4554
4555                                                 if (score < 0)
4556                                                         dynamicArgument = true;
4557                                         }
4558                                 }
4559
4560                                 //
4561                                 // It can be applicable in expanded form (when not doing exact match like for delegates)
4562                                 //
4563                                 if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && (restrictions & Restrictions.CovariantDelegate) == 0) {
4564                                         if (!params_expanded_form) {
4565                                                 pt = ((ElementTypeSpec) pt).Element;
4566                                         }
4567
4568                                         if (score > 0)
4569                                                 score = IsArgumentCompatible (ec, a, Parameter.Modifier.NONE, pt);
4570
4571                                         if (score < 0) {
4572                                                 params_expanded_form = true;
4573                                                 dynamicArgument = true;
4574                                         } else if (score == 0 || arg_count > pd.Count) {
4575                                                 params_expanded_form = true;
4576                                         }
4577                                 }
4578
4579                                 if (score > 0) {
4580                                         if (params_expanded_form)
4581                                                 ++score;
4582                                         return (arg_count - i) * 2 + score;
4583                                 }
4584                         }
4585
4586                         //
4587                         // When params parameter has no argument it will be provided later if the method is the best candidate
4588                         //
4589                         if (arg_count + 1 == pd.Count && (cpd.FixedParameters [arg_count].ModFlags & Parameter.Modifier.PARAMS) != 0)
4590                                 params_expanded_form = true;
4591
4592                         //
4593                         // Restore original arguments for dynamic binder to keep the intention of original source code
4594                         //
4595                         if (dynamicArgument)
4596                                 arguments = orig_args;
4597
4598                         return 0;
4599                 }
4600
4601                 public static Expression ResolveDefaultValueArgument (ResolveContext ec, TypeSpec ptype, Expression e, Location loc)
4602                 {
4603                         if (e is Constant && e.Type == ptype)
4604                                 return e;
4605
4606                         //
4607                         // LAMESPEC: No idea what the exact rules are for System.Reflection.Missing.Value instead of null
4608                         //
4609                         if (e == EmptyExpression.MissingValue && ptype.BuiltinType == BuiltinTypeSpec.Type.Object || ptype.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
4610                                 e = new MemberAccess (new MemberAccess (new MemberAccess (
4611                                         new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Reflection", loc), "Missing", loc), "Value", loc);
4612                         } else if (e is Constant) {
4613                                 //
4614                                 // Handles int to int? conversions, DefaultParameterValue check
4615                                 //
4616                                 e = Convert.ImplicitConversionStandard (ec, e, ptype, loc);
4617                                 if (e == null)
4618                                         return null;
4619                         } else {
4620                                 e = new DefaultValueExpression (new TypeExpression (ptype, loc), loc);
4621                         }
4622
4623                         return e.Resolve (ec);
4624                 }
4625
4626                 //
4627                 // Tests argument compatibility with the parameter
4628                 // The possible return values are
4629                 // 0 - success
4630                 // 1 - modifier mismatch
4631                 // 2 - type mismatch
4632                 // -1 - dynamic binding required
4633                 //
4634                 int IsArgumentCompatible (ResolveContext ec, Argument argument, Parameter.Modifier param_mod, TypeSpec parameter)
4635                 {
4636                         //
4637                         // Types have to be identical when ref or out modifer
4638                         // is used and argument is not of dynamic type
4639                         //
4640                         if (((argument.Modifier | param_mod) & Parameter.Modifier.RefOutMask) != 0) {
4641                                 if (argument.Type != parameter) {
4642                                         //
4643                                         // Do full equality check after quick path
4644                                         //
4645                                         if (!TypeSpecComparer.IsEqual (argument.Type, parameter)) {
4646                                                 //
4647                                                 // Using dynamic for ref/out parameter can still succeed at runtime
4648                                                 //
4649                                                 if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (argument.Modifier & Parameter.Modifier.RefOutMask) == 0 && (restrictions & Restrictions.CovariantDelegate) == 0)
4650                                                         return -1;
4651
4652                                                 return 2;
4653                                         }
4654                                 }
4655
4656                                 if ((argument.Modifier & Parameter.Modifier.RefOutMask) != (param_mod & Parameter.Modifier.RefOutMask)) {
4657                                         //
4658                                         // Using dynamic for ref/out parameter can still succeed at runtime
4659                                         //
4660                                         if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (argument.Modifier & Parameter.Modifier.RefOutMask) == 0 && (restrictions & Restrictions.CovariantDelegate) == 0)
4661                                                 return -1;
4662
4663                                         return 1;
4664                                 }
4665
4666                         } else {
4667                                 if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (restrictions & Restrictions.CovariantDelegate) == 0)
4668                                         return -1;
4669
4670                                 //
4671                                 // Use implicit conversion in all modes to return same candidates when the expression
4672                                 // is used as argument or delegate conversion
4673                                 //
4674                                 if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) {
4675                                         return 2;
4676                                 }
4677                         }
4678
4679                         return 0;
4680                 }
4681
4682                 static TypeSpec MoreSpecific (TypeSpec p, TypeSpec q)
4683                 {
4684                         if (TypeManager.IsGenericParameter (p) && !TypeManager.IsGenericParameter (q))
4685                                 return q;
4686                         if (!TypeManager.IsGenericParameter (p) && TypeManager.IsGenericParameter (q))
4687                                 return p;
4688
4689                         var ac_p = p as ArrayContainer;
4690                         if (ac_p != null) {
4691                                 var ac_q = q as ArrayContainer;
4692                                 if (ac_q == null)
4693                                         return null;
4694
4695                                 TypeSpec specific = MoreSpecific (ac_p.Element, ac_q.Element);
4696                                 if (specific == ac_p.Element)
4697                                         return p;
4698                                 if (specific == ac_q.Element)
4699                                         return q;
4700                         } else if (p.IsGeneric && q.IsGeneric) {
4701                                 var pargs = TypeManager.GetTypeArguments (p);
4702                                 var qargs = TypeManager.GetTypeArguments (q);
4703
4704                                 bool p_specific_at_least_once = false;
4705                                 bool q_specific_at_least_once = false;
4706
4707                                 for (int i = 0; i < pargs.Length; i++) {
4708                                         TypeSpec specific = MoreSpecific (pargs[i], qargs[i]);
4709                                         if (specific == pargs[i])
4710                                                 p_specific_at_least_once = true;
4711                                         if (specific == qargs[i])
4712                                                 q_specific_at_least_once = true;
4713                                 }
4714
4715                                 if (p_specific_at_least_once && !q_specific_at_least_once)
4716                                         return p;
4717                                 if (!p_specific_at_least_once && q_specific_at_least_once)
4718                                         return q;
4719                         }
4720
4721                         return null;
4722                 }
4723
4724                 //
4725                 // Find the best method from candidate list
4726                 //
4727                 public T ResolveMember<T> (ResolveContext rc, ref Arguments args) where T : MemberSpec, IParametersMember
4728                 {
4729                         List<AmbiguousCandidate> ambiguous_candidates = null;
4730
4731                         MemberSpec best_candidate;
4732                         Arguments best_candidate_args = null;
4733                         bool best_candidate_params = false;
4734                         bool best_candidate_dynamic = false;
4735                         int best_candidate_rate;
4736                         IParametersMember best_parameter_member = null;
4737
4738                         int args_count = args != null ? args.Count : 0;
4739
4740                         Arguments candidate_args = args;
4741                         bool error_mode = false;
4742                         MemberSpec invocable_member = null;
4743
4744                         while (true) {
4745                                 best_candidate = null;
4746                                 best_candidate_rate = int.MaxValue;
4747
4748                                 var type_members = members;
4749                                 do {
4750                                         for (int i = 0; i < type_members.Count; ++i) {
4751                                                 var member = type_members[i];
4752
4753                                                 //
4754                                                 // Methods in a base class are not candidates if any method in a derived
4755                                                 // class is applicable
4756                                                 //
4757                                                 if ((member.Modifiers & Modifiers.OVERRIDE) != 0)
4758                                                         continue;
4759
4760                                                 if (!error_mode) {
4761                                                         if (!member.IsAccessible (rc))
4762                                                                 continue;
4763
4764                                                         if (rc.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc))
4765                                                                 continue;
4766
4767                                                         if ((member.Modifiers & (Modifiers.PROTECTED | Modifiers.STATIC)) == Modifiers.PROTECTED &&
4768                                                                 instance_qualifier != null && !instance_qualifier.CheckProtectedMemberAccess (rc, member)) {
4769                                                                 continue;
4770                                                         }
4771                                                 }
4772
4773                                                 IParametersMember pm = member as IParametersMember;
4774                                                 if (pm == null) {
4775                                                         //
4776                                                         // Will use it later to report ambiguity between best method and invocable member
4777                                                         //
4778                                                         if (Invocation.IsMemberInvocable (member))
4779                                                                 invocable_member = member;
4780
4781                                                         continue;
4782                                                 }
4783
4784                                                 //
4785                                                 // Overload resolution is looking for base member but using parameter names
4786                                                 // and default values from the closest member. That means to do expensive lookup
4787                                                 // for the closest override for virtual or abstract members
4788                                                 //
4789                                                 if ((member.Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
4790                                                         var override_params = base_provider.GetOverrideMemberParameters (member);
4791                                                         if (override_params != null)
4792                                                                 pm = override_params;
4793                                                 }
4794
4795                                                 //
4796                                                 // Check if the member candidate is applicable
4797                                                 //
4798                                                 bool params_expanded_form = false;
4799                                                 bool dynamic_argument = false;
4800                                                 TypeSpec rt = pm.MemberType;
4801                                                 int candidate_rate = IsApplicable (rc, ref candidate_args, args_count, ref member, pm, ref params_expanded_form, ref dynamic_argument, ref rt);
4802
4803                                                 if (lambda_conv_msgs != null)
4804                                                         lambda_conv_msgs.EndSession ();
4805
4806                                                 //
4807                                                 // How does it score compare to others
4808                                                 //
4809                                                 if (candidate_rate < best_candidate_rate) {
4810
4811                                                         // Fatal error (missing dependency), cannot continue
4812                                                         if (candidate_rate < 0)
4813                                                                 return null;
4814
4815                                                         best_candidate_rate = candidate_rate;
4816                                                         best_candidate = member;
4817                                                         best_candidate_args = candidate_args;
4818                                                         best_candidate_params = params_expanded_form;
4819                                                         best_candidate_dynamic = dynamic_argument;
4820                                                         best_parameter_member = pm;
4821                                                         best_candidate_return_type = rt;
4822                                                 } else if (candidate_rate == 0) {
4823                                                         //
4824                                                         // The member look is done per type for most operations but sometimes
4825                                                         // it's not possible like for binary operators overload because they
4826                                                         // are unioned between 2 sides
4827                                                         //
4828                                                         if ((restrictions & Restrictions.BaseMembersIncluded) != 0) {
4829                                                                 if (TypeSpec.IsBaseClass (best_candidate.DeclaringType, member.DeclaringType, true))
4830                                                                         continue;
4831                                                         }
4832
4833                                                         bool is_better;
4834                                                         if (best_candidate.DeclaringType.IsInterface && member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) {
4835                                                                 //
4836                                                                 // We pack all interface members into top level type which makes the overload resolution
4837                                                                 // more complicated for interfaces. We compensate it by removing methods with same
4838                                                                 // signature when building the cache hence this path should not really be hit often
4839                                                                 //
4840                                                                 // Example:
4841                                                                 // interface IA { void Foo (int arg); }
4842                                                                 // interface IB : IA { void Foo (params int[] args); }
4843                                                                 //
4844                                                                 // IB::Foo is the best overload when calling IB.Foo (1)
4845                                                                 //
4846                                                                 is_better = true;
4847                                                                 if (ambiguous_candidates != null) {
4848                                                                         foreach (var amb_cand in ambiguous_candidates) {
4849                                                                                 if (member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) {
4850                                                                                         continue;
4851                                                                                 }
4852
4853                                                                                 is_better = false;
4854                                                                                 break;
4855                                                                         }
4856
4857                                                                         if (is_better)
4858                                                                                 ambiguous_candidates = null;
4859                                                                 }
4860                                                         } else {
4861                                                                 // Is the new candidate better
4862                                                                 is_better = BetterFunction (rc, candidate_args, member, pm.Parameters, params_expanded_form, best_candidate, best_parameter_member.Parameters, best_candidate_params);
4863                                                         }
4864
4865                                                         if (is_better) {
4866                                                                 best_candidate = member;
4867                                                                 best_candidate_args = candidate_args;
4868                                                                 best_candidate_params = params_expanded_form;
4869                                                                 best_candidate_dynamic = dynamic_argument;
4870                                                                 best_parameter_member = pm;
4871                                                                 best_candidate_return_type = rt;
4872                                                         } else {
4873                                                                 // It's not better but any other found later could be but we are not sure yet
4874                                                                 if (ambiguous_candidates == null)
4875                                                                         ambiguous_candidates = new List<AmbiguousCandidate> ();
4876
4877                                                                 ambiguous_candidates.Add (new AmbiguousCandidate (member, pm.Parameters, params_expanded_form));
4878                                                         }
4879                                                 }
4880
4881                                                 // Restore expanded arguments
4882                                                 if (candidate_args != args)
4883                                                         candidate_args = args;
4884                                         }
4885                                 } while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType.BaseType)) != null);
4886
4887                                 //
4888                                 // We've found exact match
4889                                 //
4890                                 if (best_candidate_rate == 0)
4891                                         break;
4892
4893                                 //
4894                                 // Try extension methods lookup when no ordinary method match was found and provider enables it
4895                                 //
4896                                 if (!error_mode) {
4897                                         var emg = base_provider.LookupExtensionMethod (rc);
4898                                         if (emg != null) {
4899                                                 emg = emg.OverloadResolve (rc, ref args, null, restrictions);
4900                                                 if (emg != null) {
4901                                                         best_candidate_extension_group = emg;
4902                                                         return (T) (MemberSpec) emg.BestCandidate;
4903                                                 }
4904                                         }
4905                                 }
4906
4907                                 // Don't run expensive error reporting mode for probing
4908                                 if (IsProbingOnly)
4909                                         return null;
4910
4911                                 if (error_mode)
4912                                         break;
4913
4914                                 if (lambda_conv_msgs != null && !lambda_conv_msgs.IsEmpty)
4915                                         break;
4916
4917                                 lambda_conv_msgs = null;
4918                                 error_mode = true;
4919                         }
4920
4921                         //
4922                         // No best member match found, report an error
4923                         //
4924                         if (best_candidate_rate != 0 || error_mode) {
4925                                 ReportOverloadError (rc, best_candidate, best_parameter_member, best_candidate_args, best_candidate_params);
4926                                 return null;
4927                         }
4928
4929                         if (best_candidate_dynamic) {
4930                                 if (args[0].ArgType == Argument.AType.ExtensionType) {
4931                                         rc.Report.Error (1973, loc,
4932                                                 "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",
4933                                                 args [0].Type.GetSignatureForError (), best_candidate.Name, best_candidate.GetSignatureForError ());
4934                                 }
4935
4936                                 //
4937                                 // Check type constraints only when explicit type arguments are used
4938                                 //
4939                                 if (best_candidate.IsGeneric && type_arguments != null) {
4940                                         MethodSpec bc = best_candidate as MethodSpec;
4941                                         if (bc != null && TypeParameterSpec.HasAnyTypeParameterConstrained (bc.GenericDefinition)) {
4942                                                 ConstraintChecker cc = new ConstraintChecker (rc);
4943                                                 cc.CheckAll (bc.GetGenericMethodDefinition (), bc.TypeArguments, bc.Constraints, loc);
4944                                         }
4945                                 }
4946
4947                                 BestCandidateIsDynamic = true;
4948                                 return null;
4949                         }
4950
4951                         //
4952                         // These flags indicates we are running delegate probing conversion. No need to
4953                         // do more expensive checks
4954                         // 
4955                         if ((restrictions & (Restrictions.ProbingOnly | Restrictions.CovariantDelegate)) == (Restrictions.CovariantDelegate | Restrictions.ProbingOnly))
4956                                 return (T) best_candidate;
4957
4958                         if (ambiguous_candidates != null) {
4959                                 //
4960                                 // Now check that there are no ambiguities i.e the selected method
4961                                 // should be better than all the others
4962                                 //
4963                                 for (int ix = 0; ix < ambiguous_candidates.Count; ix++) {
4964                                         var candidate = ambiguous_candidates [ix];
4965
4966                                         if (!BetterFunction (rc, best_candidate_args, best_candidate, best_parameter_member.Parameters, best_candidate_params, candidate.Member, candidate.Parameters, candidate.Expanded)) {
4967                                                 var ambiguous = candidate.Member;
4968                                                 if (custom_errors == null || !custom_errors.AmbiguousCandidates (rc, best_candidate, ambiguous)) {
4969                                                         rc.Report.SymbolRelatedToPreviousError (best_candidate);
4970                                                         rc.Report.SymbolRelatedToPreviousError (ambiguous);
4971                                                         rc.Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'",
4972                                                                 best_candidate.GetSignatureForError (), ambiguous.GetSignatureForError ());
4973                                                 }
4974
4975                                                 return (T) best_candidate;
4976                                         }
4977                                 }
4978                         }
4979
4980                         if (invocable_member != null && !IsProbingOnly) {
4981                                 rc.Report.SymbolRelatedToPreviousError (best_candidate);
4982                                 rc.Report.SymbolRelatedToPreviousError (invocable_member);
4983                                 rc.Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and invocable non-method `{1}'. Using method group",
4984                                         best_candidate.GetSignatureForError (), invocable_member.GetSignatureForError ());
4985                         }
4986
4987                         //
4988                         // And now check if the arguments are all
4989                         // compatible, perform conversions if
4990                         // necessary etc. and return if everything is
4991                         // all right
4992                         //
4993                         if (!VerifyArguments (rc, ref best_candidate_args, best_candidate, best_parameter_member, best_candidate_params))
4994                                 return null;
4995
4996                         if (best_candidate == null)
4997                                 return null;
4998
4999                         //
5000                         // Don't run possibly expensive checks in probing mode
5001                         //
5002                         if (!IsProbingOnly && !rc.IsInProbingMode) {
5003                                 //
5004                                 // Check ObsoleteAttribute on the best method
5005                                 //
5006                                 ObsoleteAttribute oa = best_candidate.GetAttributeObsolete ();
5007                                 if (oa != null && !rc.IsObsolete)
5008                                         AttributeTester.Report_ObsoleteMessage (oa, best_candidate.GetSignatureForError (), loc, rc.Report);
5009
5010                                 best_candidate.MemberDefinition.SetIsUsed ();
5011                         }
5012
5013                         args = best_candidate_args;
5014                         return (T) best_candidate;
5015                 }
5016
5017                 public MethodSpec ResolveOperator (ResolveContext rc, ref Arguments args)
5018                 {
5019                         return ResolveMember<MethodSpec> (rc, ref args);
5020                 }
5021
5022                 void ReportArgumentMismatch (ResolveContext ec, int idx, MemberSpec method,
5023                                                                                                         Argument a, AParametersCollection expected_par, TypeSpec paramType)
5024                 {
5025                         if (custom_errors != null && custom_errors.ArgumentMismatch (ec, method, a, idx))
5026                                 return;
5027
5028                         if (a.Type == InternalType.ErrorType)
5029                                 return;
5030
5031                         if (a is CollectionElementInitializer.ElementInitializerArgument) {
5032                                 ec.Report.SymbolRelatedToPreviousError (method);
5033                                 if ((expected_par.FixedParameters[idx].ModFlags & Parameter.Modifier.RefOutMask) != 0) {
5034                                         ec.Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have `ref' or `out' modifier",
5035                                                 TypeManager.CSharpSignature (method));
5036                                         return;
5037                                 }
5038                                 ec.Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments",
5039                                           TypeManager.CSharpSignature (method));
5040                         } else if (IsDelegateInvoke) {
5041                                 ec.Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments",
5042                                         DelegateType.GetSignatureForError ());
5043                         } else {
5044                                 ec.Report.SymbolRelatedToPreviousError (method);
5045                                 ec.Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments",
5046                                         method.GetSignatureForError ());
5047                         }
5048
5049                         Parameter.Modifier mod = idx >= expected_par.Count ? 0 : expected_par.FixedParameters[idx].ModFlags;
5050
5051                         string index = (idx + 1).ToString ();
5052                         if (((mod & Parameter.Modifier.RefOutMask) ^ (a.Modifier & Parameter.Modifier.RefOutMask)) != 0) {
5053                                 if ((mod & Parameter.Modifier.RefOutMask) == 0)
5054                                         ec.Report.Error (1615, a.Expr.Location, "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' modifier",
5055                                                 index, Parameter.GetModifierSignature (a.Modifier));
5056                                 else
5057                                         ec.Report.Error (1620, a.Expr.Location, "Argument `#{0}' is missing `{1}' modifier",
5058                                                 index, Parameter.GetModifierSignature (mod));
5059                         } else {
5060                                 string p1 = a.GetSignatureForError ();
5061                                 string p2 = paramType.GetSignatureForError ();
5062
5063                                 if (p1 == p2) {
5064                                         p1 = a.Type.GetSignatureForErrorIncludingAssemblyName ();
5065                                         p2 = paramType.GetSignatureForErrorIncludingAssemblyName ();
5066                                 }
5067
5068                                 if ((mod & Parameter.Modifier.RefOutMask) != 0) {
5069                                         p1 = Parameter.GetModifierSignature (a.Modifier) + " " + p1;
5070                                         p2 = Parameter.GetModifierSignature (a.Modifier) + " " + p2;
5071                                 }
5072
5073                                 ec.Report.Error (1503, a.Expr.Location,
5074                                         "Argument `#{0}' cannot convert `{1}' expression to type `{2}'", index, p1, p2);
5075                         }
5076                 }
5077
5078                 //
5079                 // We have failed to find exact match so we return error info about the closest match
5080                 //
5081                 void ReportOverloadError (ResolveContext rc, MemberSpec best_candidate, IParametersMember pm, Arguments args, bool params_expanded)
5082                 {
5083                         int ta_count = type_arguments == null ? 0 : type_arguments.Count;
5084                         int arg_count = args == null ? 0 : args.Count;
5085
5086                         if (ta_count != best_candidate.Arity && (ta_count > 0 || ((IParametersMember) best_candidate).Parameters.IsEmpty)) {
5087                                 var mg = new MethodGroupExpr (new [] { best_candidate }, best_candidate.DeclaringType, loc);
5088                                 mg.Error_TypeArgumentsCannotBeUsed (rc, best_candidate, ta_count, loc);
5089                                 return;
5090                         }
5091
5092                         if (lambda_conv_msgs != null && lambda_conv_msgs.Merge (rc.Report.Printer)) {
5093                                 return;
5094                         }
5095
5096
5097                         if ((best_candidate.Modifiers & (Modifiers.PROTECTED | Modifiers.STATIC)) == Modifiers.PROTECTED &&
5098                                 InstanceQualifier != null && !InstanceQualifier.CheckProtectedMemberAccess (rc, best_candidate)) {
5099                                 MemberExpr.Error_ProtectedMemberAccess (rc, best_candidate, InstanceQualifier.InstanceType, loc);
5100                         }
5101
5102                         //
5103                         // For candidates which match on parameters count report more details about incorrect arguments
5104                         //
5105                         if (pm != null) {
5106                                 int unexpanded_count = ((IParametersMember) best_candidate).Parameters.HasParams ? pm.Parameters.Count - 1 : pm.Parameters.Count;
5107                                 if (pm.Parameters.Count == arg_count || params_expanded || unexpanded_count == arg_count) {
5108                                         // Reject any inaccessible member
5109                                         if (!best_candidate.IsAccessible (rc) || !best_candidate.DeclaringType.IsAccessible (rc)) {
5110                                                 rc.Report.SymbolRelatedToPreviousError (best_candidate);
5111                                                 Expression.ErrorIsInaccesible (rc, best_candidate.GetSignatureForError (), loc);
5112                                                 return;
5113                                         }
5114
5115                                         var ms = best_candidate as MethodSpec;
5116                                         if (ms != null && ms.IsGeneric) {
5117                                                 bool constr_ok = true;
5118                                                 if (ms.TypeArguments != null)
5119                                                         constr_ok = new ConstraintChecker (rc.MemberContext).CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc);
5120
5121                                                 if (ta_count == 0) {
5122                                                         if (custom_errors != null && custom_errors.TypeInferenceFailed (rc, best_candidate))
5123                                                                 return;
5124
5125                                                         if (constr_ok) {
5126                                                                 rc.Report.Error (411, loc,
5127                                                                         "The type arguments for method `{0}' cannot be inferred from the usage. Try specifying the type arguments explicitly",
5128                                                                         ms.GetGenericMethodDefinition ().GetSignatureForError ());
5129                                                         }
5130
5131                                                         return;
5132                                                 }
5133                                         }
5134
5135                                         VerifyArguments (rc, ref args, best_candidate, pm, params_expanded);
5136                                         return;
5137                                 }
5138                         }
5139
5140                         //
5141                         // We failed to find any method with correct argument count, report best candidate
5142                         //
5143                         if (custom_errors != null && custom_errors.NoArgumentMatch (rc, best_candidate))
5144                                 return;
5145
5146                         if (best_candidate.Kind == MemberKind.Constructor) {
5147                                 rc.Report.SymbolRelatedToPreviousError (best_candidate);
5148                                 Error_ConstructorMismatch (rc, best_candidate.DeclaringType, arg_count, loc);
5149                         } else if (IsDelegateInvoke) {
5150                                 rc.Report.SymbolRelatedToPreviousError (DelegateType);
5151                                 rc.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",
5152                                         DelegateType.GetSignatureForError (), arg_count.ToString ());
5153                         } else {
5154                                 string name = best_candidate.Kind == MemberKind.Indexer ? "this" : best_candidate.Name;
5155                                 rc.Report.SymbolRelatedToPreviousError (best_candidate);
5156                                 rc.Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments",
5157                                         name, arg_count.ToString ());
5158                         }
5159                 }
5160
5161                 bool VerifyArguments (ResolveContext ec, ref Arguments args, MemberSpec member, IParametersMember pm, bool chose_params_expanded)
5162                 {
5163                         var pd = pm.Parameters;
5164                         TypeSpec[] ptypes = ((IParametersMember) member).Parameters.Types;
5165
5166                         Parameter.Modifier p_mod = 0;
5167                         TypeSpec pt = null;
5168                         int a_idx = 0, a_pos = 0;
5169                         Argument a = null;
5170                         ArrayInitializer params_initializers = null;
5171                         bool has_unsafe_arg = pm.MemberType.IsPointer;
5172                         int arg_count = args == null ? 0 : args.Count;
5173
5174                         for (; a_idx < arg_count; a_idx++, ++a_pos) {
5175                                 a = args[a_idx];
5176                                 if (p_mod != Parameter.Modifier.PARAMS) {
5177                                         p_mod = pd.FixedParameters[a_idx].ModFlags;
5178                                         pt = ptypes[a_idx];
5179                                         has_unsafe_arg |= pt.IsPointer;
5180
5181                                         if (p_mod == Parameter.Modifier.PARAMS) {
5182                                                 if (chose_params_expanded) {
5183                                                         params_initializers = new ArrayInitializer (arg_count - a_idx, a.Expr.Location);
5184                                                         pt = TypeManager.GetElementType (pt);
5185                                                 }
5186                                         }
5187                                 }
5188
5189                                 //
5190                                 // Types have to be identical when ref or out modifer is used 
5191                                 //
5192                                 if (((a.Modifier | p_mod) & Parameter.Modifier.RefOutMask) != 0) {
5193                                         if ((a.Modifier & Parameter.Modifier.RefOutMask) != (p_mod & Parameter.Modifier.RefOutMask))
5194                                                 break;
5195
5196                                         if (a.Expr.Type == pt || TypeSpecComparer.IsEqual (a.Expr.Type, pt))
5197                                                 continue;
5198
5199                                         break;
5200                                 }
5201
5202                                 NamedArgument na = a as NamedArgument;
5203                                 if (na != null) {
5204                                         int name_index = pd.GetParameterIndexByName (na.Name);
5205                                         if (name_index < 0 || name_index >= pd.Count) {
5206                                                 if (IsDelegateInvoke) {
5207                                                         ec.Report.SymbolRelatedToPreviousError (DelegateType);
5208                                                         ec.Report.Error (1746, na.Location,
5209                                                                 "The delegate `{0}' does not contain a parameter named `{1}'",
5210                                                                 DelegateType.GetSignatureForError (), na.Name);
5211                                                 } else {
5212                                                         ec.Report.SymbolRelatedToPreviousError (member);
5213                                                         ec.Report.Error (1739, na.Location,
5214                                                                 "The best overloaded method match for `{0}' does not contain a parameter named `{1}'",
5215                                                                 TypeManager.CSharpSignature (member), na.Name);
5216                                                 }
5217                                         } else if (args[name_index] != a) {
5218                                                 if (IsDelegateInvoke)
5219                                                         ec.Report.SymbolRelatedToPreviousError (DelegateType);
5220                                                 else
5221                                                         ec.Report.SymbolRelatedToPreviousError (member);
5222
5223                                                 ec.Report.Error (1744, na.Location,
5224                                                         "Named argument `{0}' cannot be used for a parameter which has positional argument specified",
5225                                                         na.Name);
5226                                         }
5227                                 }
5228                                 
5229                                 if (a.Expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
5230                                         continue;
5231
5232                                 if ((restrictions & Restrictions.CovariantDelegate) != 0 && !Delegate.IsTypeCovariant (ec, a.Expr.Type, pt)) {
5233                                         custom_errors.NoArgumentMatch (ec, member);
5234                                         return false;
5235                                 }
5236
5237                                 Expression conv = null;
5238                                 if (a.ArgType == Argument.AType.ExtensionType) {
5239                                         if (a.Expr.Type == pt || TypeSpecComparer.IsEqual (a.Expr.Type, pt)) {
5240                                                 conv = a.Expr;
5241                                         } else {
5242                                                 conv = Convert.ImplicitReferenceConversion (a.Expr, pt, false);
5243                                                 if (conv == null)
5244                                                         conv = Convert.ImplicitBoxingConversion (a.Expr, a.Expr.Type, pt);
5245                                         }
5246                                 } else {
5247                                         conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc);
5248                                 }
5249
5250                                 if (conv == null)
5251                                         break;
5252
5253                                 //
5254                                 // Convert params arguments to an array initializer
5255                                 //
5256                                 if (params_initializers != null) {
5257                                         // we choose to use 'a.Expr' rather than 'conv' so that
5258                                         // we don't hide the kind of expression we have (esp. CompoundAssign.Helper)
5259                                         params_initializers.Add (a.Expr);
5260                                         args.RemoveAt (a_idx--);
5261                                         --arg_count;
5262                                         continue;
5263                                 }
5264
5265                                 // Update the argument with the implicit conversion
5266                                 a.Expr = conv;
5267                         }
5268
5269                         if (a_idx != arg_count) {
5270                                 ReportArgumentMismatch (ec, a_pos, member, a, pd, pt);
5271                                 return false;
5272                         }
5273
5274                         //
5275                         // Fill not provided arguments required by params modifier
5276                         //
5277                         if (params_initializers == null && pd.HasParams && arg_count + 1 == pd.Count) {
5278                                 if (args == null)
5279                                         args = new Arguments (1);
5280
5281                                 pt = ptypes[pd.Count - 1];
5282                                 pt = TypeManager.GetElementType (pt);
5283                                 has_unsafe_arg |= pt.IsPointer;
5284                                 params_initializers = new ArrayInitializer (0, loc);
5285                         }
5286
5287                         //
5288                         // Append an array argument with all params arguments
5289                         //
5290                         if (params_initializers != null) {
5291                                 args.Add (new Argument (
5292                                         new ArrayCreation (new TypeExpression (pt, loc), params_initializers, loc).Resolve (ec)));
5293                                 arg_count++;
5294                         }
5295
5296                         if (has_unsafe_arg && !ec.IsUnsafe) {
5297                                 Expression.UnsafeError (ec, loc);
5298                         }
5299
5300                         //
5301                         // We could infer inaccesible type arguments
5302                         //
5303                         if (type_arguments == null && member.IsGeneric) {
5304                                 var ms = (MethodSpec) member;
5305                                 foreach (var ta in ms.TypeArguments) {
5306                                         if (!ta.IsAccessible (ec)) {
5307                                                 ec.Report.SymbolRelatedToPreviousError (ta);
5308                                                 Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
5309                                                 break;
5310                                         }
5311                                 }
5312                         }
5313
5314                         return true;
5315                 }
5316         }
5317
5318         public class ConstantExpr : MemberExpr
5319         {
5320                 readonly ConstSpec constant;
5321
5322                 public ConstantExpr (ConstSpec constant, Location loc)
5323                 {
5324                         this.constant = constant;
5325                         this.loc = loc;
5326                 }
5327
5328                 public override string Name {
5329                         get { throw new NotImplementedException (); }
5330                 }
5331
5332                 public override string KindName {
5333                         get { return "constant"; }
5334                 }
5335
5336                 public override bool IsInstance {
5337                         get { return !IsStatic; }
5338                 }
5339
5340                 public override bool IsStatic {
5341                         get { return true; }
5342                 }
5343
5344                 protected override TypeSpec DeclaringType {
5345                         get { return constant.DeclaringType; }
5346                 }
5347
5348                 public override Expression CreateExpressionTree (ResolveContext ec)
5349                 {
5350                         throw new NotSupportedException ("ET");
5351                 }
5352
5353                 protected override Expression DoResolve (ResolveContext rc)
5354                 {
5355                         ResolveInstanceExpression (rc, null);
5356                         DoBestMemberChecks (rc, constant);
5357
5358                         var c = constant.GetConstant (rc);
5359
5360                         // Creates reference expression to the constant value
5361                         return Constant.CreateConstantFromValue (constant.MemberType, c.GetValue (), loc);
5362                 }
5363
5364                 public override void Emit (EmitContext ec)
5365                 {
5366                         throw new NotSupportedException ();
5367                 }
5368
5369                 public override string GetSignatureForError ()
5370                 {
5371                         return constant.GetSignatureForError ();
5372                 }
5373
5374                 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
5375                 {
5376                         Error_TypeArgumentsCannotBeUsed (ec, "constant", GetSignatureForError (), loc);
5377                 }
5378         }
5379
5380         //
5381         // Fully resolved expression that references a Field
5382         //
5383         public class FieldExpr : MemberExpr, IDynamicAssign, IMemoryLocation, IVariableReference
5384         {
5385                 protected FieldSpec spec;
5386                 VariableInfo variable_info;
5387                 
5388                 LocalTemporary temp;
5389                 bool prepared;
5390                 
5391                 protected FieldExpr (Location l)
5392                 {
5393                         loc = l;
5394                 }
5395
5396                 public FieldExpr (FieldSpec spec, Location loc)
5397                 {
5398                         this.spec = spec;
5399                         this.loc = loc;
5400
5401                         type = spec.MemberType;
5402                 }
5403                 
5404                 public FieldExpr (FieldBase fi, Location l)
5405                         : this (fi.Spec, l)
5406                 {
5407                 }
5408
5409                 #region Properties
5410
5411                 public override string Name {
5412                         get {
5413                                 return spec.Name;
5414                         }
5415                 }
5416
5417                 public bool IsHoisted {
5418                         get {
5419                                 IVariableReference hv = InstanceExpression as IVariableReference;
5420                                 return hv != null && hv.IsHoisted;
5421                         }
5422                 }
5423
5424                 public override bool IsInstance {
5425                         get {
5426                                 return !spec.IsStatic;
5427                         }
5428                 }
5429
5430                 public override bool IsStatic {
5431                         get {
5432                                 return spec.IsStatic;
5433                         }
5434                 }
5435
5436                 public override string KindName {
5437                         get { return "field"; }
5438                 }
5439
5440                 public FieldSpec Spec {
5441                         get {
5442                                 return spec;
5443                         }
5444                 }
5445
5446                 protected override TypeSpec DeclaringType {
5447                         get {
5448                                 return spec.DeclaringType;
5449                         }
5450                 }
5451
5452                 public VariableInfo VariableInfo {
5453                         get {
5454                                 return variable_info;
5455                         }
5456                 }
5457
5458 #endregion
5459
5460                 public override string GetSignatureForError ()
5461                 {
5462                         return spec.GetSignatureForError ();
5463                 }
5464
5465                 public bool IsMarshalByRefAccess (ResolveContext rc)
5466                 {
5467                         // Checks possible ldflda of field access expression
5468                         return !spec.IsStatic && TypeSpec.IsValueType (spec.MemberType) && !(InstanceExpression is This) &&
5469                                 rc.Module.PredefinedTypes.MarshalByRefObject.Define () &&
5470                                 TypeSpec.IsBaseClass (spec.DeclaringType, rc.Module.PredefinedTypes.MarshalByRefObject.TypeSpec, false);
5471                 }
5472
5473                 public void SetHasAddressTaken ()
5474                 {
5475                         IVariableReference vr = InstanceExpression as IVariableReference;
5476                         if (vr != null) {
5477                                 vr.SetHasAddressTaken ();
5478                         }
5479                 }
5480
5481                 public override Expression CreateExpressionTree (ResolveContext ec)
5482                 {
5483                         return CreateExpressionTree (ec, true);
5484                 }
5485
5486                 public Expression CreateExpressionTree (ResolveContext ec, bool convertInstance)
5487                 {
5488                         Arguments args;
5489                         Expression instance;
5490
5491                         if (InstanceExpression == null) {
5492                                 instance = new NullLiteral (loc);
5493                         } else if (convertInstance) {
5494                                 instance = InstanceExpression.CreateExpressionTree (ec);
5495                         } else {
5496                                 args = new Arguments (1);
5497                                 args.Add (new Argument (InstanceExpression));
5498                                 instance = CreateExpressionFactoryCall (ec, "Constant", args);
5499                         }
5500
5501                         args = Arguments.CreateForExpressionTree (ec, null,
5502                                 instance,
5503                                 CreateTypeOfExpression ());
5504
5505                         return CreateExpressionFactoryCall (ec, "Field", args);
5506                 }
5507
5508                 public Expression CreateTypeOfExpression ()
5509                 {
5510                         return new TypeOfField (spec, loc);
5511                 }
5512
5513                 protected override Expression DoResolve (ResolveContext ec)
5514                 {
5515                         spec.MemberDefinition.SetIsUsed ();
5516
5517                         return DoResolve (ec, null);
5518                 }
5519
5520                 Expression DoResolve (ResolveContext ec, Expression rhs)
5521                 {
5522                         bool lvalue_instance = rhs != null && IsInstance && spec.DeclaringType.IsStruct;
5523
5524                         if (rhs != this) {
5525                                 if (ResolveInstanceExpression (ec, rhs)) {
5526                                         // Resolve the field's instance expression while flow analysis is turned
5527                                         // off: when accessing a field "a.b", we must check whether the field
5528                                         // "a.b" is initialized, not whether the whole struct "a" is initialized.
5529
5530                                         if (lvalue_instance) {
5531                                                 using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
5532                                                         bool out_access = rhs == EmptyExpression.OutAccess || rhs == EmptyExpression.LValueMemberOutAccess;
5533
5534                                                         Expression right_side =
5535                                                                 out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
5536
5537                                                         InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
5538                                                 }
5539                                         } else {
5540                                                 using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
5541                                                         InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
5542                                                 }
5543                                         }
5544
5545                                         if (InstanceExpression == null)
5546                                                 return null;
5547                                 }
5548
5549                                 DoBestMemberChecks (ec, spec);
5550                         }
5551
5552                         var fb = spec as FixedFieldSpec;
5553                         IVariableReference var = InstanceExpression as IVariableReference;
5554
5555                         if (lvalue_instance && var != null && var.VariableInfo != null) {
5556                                 var.VariableInfo.SetStructFieldAssigned (ec, Name);
5557                         }
5558
5559                         if (fb != null) {
5560                                 IFixedExpression fe = InstanceExpression as IFixedExpression;
5561                                 if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) {
5562                                         ec.Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement");
5563                                 }
5564
5565                                 if (InstanceExpression.eclass != ExprClass.Variable) {
5566                                         ec.Report.SymbolRelatedToPreviousError (spec);
5567                                         ec.Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields",
5568                                                 TypeManager.GetFullNameSignature (spec));
5569                                 } else if (var != null && var.IsHoisted) {
5570                                         AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, var, loc);
5571                                 }
5572
5573                                 return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec);
5574                         }
5575
5576                         //
5577                         // Set flow-analysis variable info for struct member access. It will be check later
5578                         // for precise error reporting
5579                         //
5580                         if (var != null && var.VariableInfo != null && InstanceExpression.Type.IsStruct) {
5581                                 variable_info = var.VariableInfo.GetStructFieldInfo (Name);
5582                                 if (rhs != null && variable_info != null)
5583                                         variable_info.SetStructFieldAssigned (ec, Name);
5584                         }
5585
5586                         eclass = ExprClass.Variable;
5587                         return this;
5588                 }
5589
5590                 public void VerifyAssignedStructField (ResolveContext rc, Expression rhs)
5591                 {
5592                         var fe = this;
5593
5594                         do {
5595                                 var var = fe.InstanceExpression as IVariableReference;
5596                                 if (var != null) {
5597                                         var vi = var.VariableInfo;
5598
5599                                         if (vi != null && !vi.IsStructFieldAssigned (rc, fe.Name) && (rhs == null || !fe.type.IsStruct)) {
5600                                                 if (rhs != null) {
5601                                                         rc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
5602                                                 } else {
5603                                                         rc.Report.Error (170, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
5604                                                 }
5605
5606                                                 return;
5607                                         }
5608                                 }
5609
5610                                 fe = fe.InstanceExpression as FieldExpr;
5611
5612                         } while (fe != null);
5613                 }
5614
5615                 static readonly int [] codes = {
5616                         191,    // instance, write access
5617                         192,    // instance, out access
5618                         198,    // static, write access
5619                         199,    // static, out access
5620                         1648,   // member of value instance, write access
5621                         1649,   // member of value instance, out access
5622                         1650,   // member of value static, write access
5623                         1651    // member of value static, out access
5624                 };
5625
5626                 static readonly string [] msgs = {
5627                         /*0191*/ "A readonly field `{0}' cannot be assigned to (except in a constructor or a variable initializer)",
5628                         /*0192*/ "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
5629                         /*0198*/ "A static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
5630                         /*0199*/ "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
5631                         /*1648*/ "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)",
5632                         /*1649*/ "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)",
5633                         /*1650*/ "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
5634                         /*1651*/ "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)"
5635                 };
5636
5637                 // The return value is always null.  Returning a value simplifies calling code.
5638                 Expression Report_AssignToReadonly (ResolveContext ec, Expression right_side)
5639                 {
5640                         int i = 0;
5641                         if (right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess)
5642                                 i += 1;
5643                         if (IsStatic)
5644                                 i += 2;
5645                         if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess)
5646                                 i += 4;
5647                         ec.Report.Error (codes [i], loc, msgs [i], GetSignatureForError ());
5648
5649                         return null;
5650                 }
5651                 
5652                 override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
5653                 {
5654                         if (spec is FixedFieldSpec) {
5655                                 // It could be much better error message but we want to be error compatible
5656                                 Error_ValueAssignment (ec, right_side);
5657                         }
5658
5659                         Expression e = DoResolve (ec, right_side);
5660
5661                         if (e == null)
5662                                 return null;
5663
5664                         spec.MemberDefinition.SetIsAssigned ();
5665
5666                         if ((right_side == EmptyExpression.UnaryAddress || right_side == EmptyExpression.OutAccess) &&
5667                                         (spec.Modifiers & Modifiers.VOLATILE) != 0) {
5668                                 ec.Report.Warning (420, 1, loc,
5669                                         "`{0}': A volatile field references will not be treated as volatile",
5670                                         spec.GetSignatureForError ());
5671                         }
5672
5673                         if (spec.IsReadOnly) {
5674                                 // InitOnly fields can only be assigned in constructors or initializers
5675                                 if (!ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.ConstructorScope))
5676                                         return Report_AssignToReadonly (ec, right_side);
5677
5678                                 if (ec.HasSet (ResolveContext.Options.ConstructorScope)) {
5679
5680                                         // InitOnly fields cannot be assigned-to in a different constructor from their declaring type
5681                                         if (ec.CurrentMemberDefinition.Parent.PartialContainer.Definition != spec.DeclaringType.GetDefinition ())
5682                                                 return Report_AssignToReadonly (ec, right_side);
5683                                         // static InitOnly fields cannot be assigned-to in an instance constructor
5684                                         if (IsStatic && !ec.IsStatic)
5685                                                 return Report_AssignToReadonly (ec, right_side);
5686                                         // instance constructors can't modify InitOnly fields of other instances of the same type
5687                                         if (!IsStatic && !(InstanceExpression is This))
5688                                                 return Report_AssignToReadonly (ec, right_side);
5689                                 }
5690                         }
5691
5692                         if (right_side == EmptyExpression.OutAccess && IsMarshalByRefAccess (ec)) {
5693                                 ec.Report.SymbolRelatedToPreviousError (spec.DeclaringType);
5694                                 ec.Report.Warning (197, 1, loc,
5695                                                 "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",
5696                                                 GetSignatureForError ());
5697                         }
5698
5699                         eclass = ExprClass.Variable;
5700                         return this;
5701                 }
5702
5703                 public override int GetHashCode ()
5704                 {
5705                         return spec.GetHashCode ();
5706                 }
5707                 
5708                 public bool IsFixed {
5709                         get {
5710                                 //
5711                                 // A variable of the form V.I is fixed when V is a fixed variable of a struct type
5712                                 //
5713                                 IVariableReference variable = InstanceExpression as IVariableReference;
5714                                 if (variable != null)
5715                                         return InstanceExpression.Type.IsStruct && variable.IsFixed;
5716
5717                                 IFixedExpression fe = InstanceExpression as IFixedExpression;
5718                                 return fe != null && fe.IsFixed;
5719                         }
5720                 }
5721
5722                 public override bool Equals (object obj)
5723                 {
5724                         FieldExpr fe = obj as FieldExpr;
5725                         if (fe == null)
5726                                 return false;
5727
5728                         if (spec != fe.spec)
5729                                 return false;
5730
5731                         if (InstanceExpression == null || fe.InstanceExpression == null)
5732                                 return true;
5733
5734                         return InstanceExpression.Equals (fe.InstanceExpression);
5735                 }
5736                 
5737                 public void Emit (EmitContext ec, bool leave_copy)
5738                 {
5739                         bool is_volatile = (spec.Modifiers & Modifiers.VOLATILE) != 0;
5740
5741                         if (IsStatic){
5742                                 if (is_volatile)
5743                                         ec.Emit (OpCodes.Volatile);
5744
5745                                 ec.Emit (OpCodes.Ldsfld, spec);
5746                         } else {
5747                                 if (!prepared)
5748                                         EmitInstance (ec, false);
5749
5750                                 // Optimization for build-in types
5751                                 if (type.IsStruct && type == ec.CurrentType && InstanceExpression.Type == type) {
5752                                         ec.EmitLoadFromPtr (type);
5753                                 } else {
5754                                         var ff = spec as FixedFieldSpec;
5755                                         if (ff != null) {
5756                                                 ec.Emit (OpCodes.Ldflda, spec);
5757                                                 ec.Emit (OpCodes.Ldflda, ff.Element);
5758                                         } else {
5759                                                 if (is_volatile)
5760                                                         ec.Emit (OpCodes.Volatile);
5761
5762                                                 ec.Emit (OpCodes.Ldfld, spec);
5763                                         }
5764                                 }
5765                         }
5766
5767                         if (leave_copy) {
5768                                 ec.Emit (OpCodes.Dup);
5769                                 if (!IsStatic) {
5770                                         temp = new LocalTemporary (this.Type);
5771                                         temp.Store (ec);
5772                                 }
5773                         }
5774                 }
5775
5776                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
5777                 {
5778                         bool has_await_source = ec.HasSet (BuilderContext.Options.AsyncBody) && source.ContainsEmitWithAwait ();
5779                         if (isCompound && !(source is DynamicExpressionStatement)) {
5780                                 if (has_await_source) {
5781                                         if (IsInstance)
5782                                                 InstanceExpression = InstanceExpression.EmitToField (ec);
5783                                 } else {
5784                                         prepared = true;
5785                                 }
5786                         }
5787
5788                         if (IsInstance) {
5789                                 if (has_await_source)
5790                                         source = source.EmitToField (ec);
5791
5792                                 EmitInstance (ec, prepared);
5793                         }
5794
5795                         source.Emit (ec);
5796
5797                         if (leave_copy) {
5798                                 ec.Emit (OpCodes.Dup);
5799                                 if (!IsStatic) {
5800                                         temp = new LocalTemporary (this.Type);
5801                                         temp.Store (ec);
5802                                 }
5803                         }
5804
5805                         if ((spec.Modifiers & Modifiers.VOLATILE) != 0)
5806                                 ec.Emit (OpCodes.Volatile);
5807                                         
5808                         spec.MemberDefinition.SetIsAssigned ();
5809
5810                         if (IsStatic)
5811                                 ec.Emit (OpCodes.Stsfld, spec);
5812                         else
5813                                 ec.Emit (OpCodes.Stfld, spec);
5814                         
5815                         if (temp != null) {
5816                                 temp.Emit (ec);
5817                                 temp.Release (ec);
5818                                 temp = null;
5819                         }
5820                 }
5821
5822                 //
5823                 // Emits store to field with prepared values on stack
5824                 //
5825                 public void EmitAssignFromStack (EmitContext ec)
5826                 {
5827                         if (IsStatic) {
5828                                 ec.Emit (OpCodes.Stsfld, spec);
5829                         } else {
5830                                 ec.Emit (OpCodes.Stfld, spec);
5831                         }
5832                 }
5833
5834                 public override void Emit (EmitContext ec)
5835                 {
5836                         Emit (ec, false);
5837                 }
5838
5839                 public override void EmitSideEffect (EmitContext ec)
5840                 {
5841                         bool is_volatile = (spec.Modifiers & Modifiers.VOLATILE) != 0;
5842
5843                         if (is_volatile) // || is_marshal_by_ref ())
5844                                 base.EmitSideEffect (ec);
5845                 }
5846
5847                 public virtual void AddressOf (EmitContext ec, AddressOp mode)
5848                 {
5849                         if ((mode & AddressOp.Store) != 0)
5850                                 spec.MemberDefinition.SetIsAssigned ();
5851                         if ((mode & AddressOp.Load) != 0)
5852                                 spec.MemberDefinition.SetIsUsed ();
5853
5854                         //
5855                         // Handle initonly fields specially: make a copy and then
5856                         // get the address of the copy.
5857                         //
5858                         bool need_copy;
5859                         if (spec.IsReadOnly){
5860                                 need_copy = true;
5861                                 if (ec.HasSet (EmitContext.Options.ConstructorScope) && spec.DeclaringType == ec.CurrentType) {
5862                                         if (IsStatic){
5863                                                 if (ec.IsStatic)
5864                                                         need_copy = false;
5865                                         } else
5866                                                 need_copy = false;
5867                                 }
5868                         } else
5869                                 need_copy = false;
5870                         
5871                         if (need_copy) {
5872                                 Emit (ec);
5873                                 var temp = ec.GetTemporaryLocal (type);
5874                                 ec.Emit (OpCodes.Stloc, temp);
5875                                 ec.Emit (OpCodes.Ldloca, temp);
5876                                 ec.FreeTemporaryLocal (temp, type);
5877                                 return;
5878                         }
5879
5880
5881                         if (IsStatic){
5882                                 ec.Emit (OpCodes.Ldsflda, spec);
5883                         } else {
5884                                 if (!prepared)
5885                                         EmitInstance (ec, false);
5886                                 ec.Emit (OpCodes.Ldflda, spec);
5887                         }
5888                 }
5889
5890                 public SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source)
5891                 {
5892                         return MakeExpression (ctx);
5893                 }
5894
5895                 public override SLE.Expression MakeExpression (BuilderContext ctx)
5896                 {
5897 #if STATIC
5898                         return base.MakeExpression (ctx);
5899 #else
5900                         return SLE.Expression.Field (
5901                                 IsStatic ? null : InstanceExpression.MakeExpression (ctx),
5902                                 spec.GetMetaInfo ());
5903 #endif
5904                 }
5905
5906                 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
5907                 {
5908                         Error_TypeArgumentsCannotBeUsed (ec, "field", GetSignatureForError (), loc);
5909                 }
5910         }
5911
5912         
5913         //
5914         // Expression that evaluates to a Property.
5915         //
5916         // This is not an LValue because we need to re-write the expression. We
5917         // can not take data from the stack and store it.
5918         //
5919         sealed class PropertyExpr : PropertyOrIndexerExpr<PropertySpec>
5920         {
5921                 Arguments arguments;
5922
5923                 public PropertyExpr (PropertySpec spec, Location l)
5924                         : base (l)
5925                 {
5926                         best_candidate = spec;
5927                         type = spec.MemberType;
5928                 }
5929
5930                 #region Properties
5931
5932                 protected override Arguments Arguments {
5933                         get {
5934                                 return arguments;
5935                         }
5936                         set {
5937                                 arguments = value;
5938                         }
5939                 }
5940
5941                 protected override TypeSpec DeclaringType {
5942                         get {
5943                                 return best_candidate.DeclaringType;
5944                         }
5945                 }
5946
5947                 public override string Name {
5948                         get {
5949                                 return best_candidate.Name;
5950                         }
5951                 }
5952
5953                 public override bool IsInstance {
5954                         get {
5955                                 return !IsStatic;
5956                         }
5957                 }
5958
5959                 public override bool IsStatic {
5960                         get {
5961                                 return best_candidate.IsStatic;
5962                         }
5963                 }
5964
5965                 public override string KindName {
5966                         get { return "property"; }
5967                 }
5968
5969                 public PropertySpec PropertyInfo {
5970                         get {
5971                                 return best_candidate;
5972                         }
5973                 }
5974
5975                 #endregion
5976
5977                 public override MethodGroupExpr CanReduceLambda (AnonymousMethodBody body)
5978                 {
5979                         if (best_candidate == null || !(best_candidate.IsStatic || InstanceExpression is This))
5980                                 return null;
5981
5982                         var args_count = arguments == null ? 0 : arguments.Count;
5983                         if (args_count != body.Parameters.Count && args_count == 0)
5984                                 return null;
5985
5986                         var mg = MethodGroupExpr.CreatePredefined (best_candidate.Get, DeclaringType, loc);
5987                         mg.InstanceExpression = InstanceExpression;
5988
5989                         return mg;
5990                 }
5991
5992                 public static PropertyExpr CreatePredefined (PropertySpec spec, Location loc)
5993                 {
5994                         return new PropertyExpr (spec, loc) {
5995                                 Getter = spec.Get,
5996                                 Setter = spec.Set
5997                         };
5998                 }
5999
6000                 public override Expression CreateExpressionTree (ResolveContext ec)
6001                 {
6002                         Arguments args;
6003                         if (IsSingleDimensionalArrayLength ()) {
6004                                 args = new Arguments (1);
6005                                 args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
6006                                 return CreateExpressionFactoryCall (ec, "ArrayLength", args);
6007                         }
6008
6009                         args = new Arguments (2);
6010                         if (InstanceExpression == null)
6011                                 args.Add (new Argument (new NullLiteral (loc)));
6012                         else
6013                                 args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
6014                         args.Add (new Argument (new TypeOfMethod (Getter, loc)));
6015                         return CreateExpressionFactoryCall (ec, "Property", args);
6016                 }
6017
6018                 public Expression CreateSetterTypeOfExpression (ResolveContext rc)
6019                 {
6020                         DoResolveLValue (rc, null);
6021                         return new TypeOfMethod (Setter, loc);
6022                 }
6023
6024                 public override string GetSignatureForError ()
6025                 {
6026                         return best_candidate.GetSignatureForError ();
6027                 }
6028
6029                 public override SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source)
6030                 {
6031 #if STATIC
6032                         return base.MakeExpression (ctx);
6033 #else
6034                         return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) Setter.GetMetaInfo ());
6035 #endif
6036                 }
6037
6038                 public override SLE.Expression MakeExpression (BuilderContext ctx)
6039                 {
6040 #if STATIC
6041                         return base.MakeExpression (ctx);
6042 #else
6043                         return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) Getter.GetMetaInfo ());
6044 #endif
6045                 }
6046
6047                 void Error_PropertyNotValid (ResolveContext ec)
6048                 {
6049                         ec.Report.SymbolRelatedToPreviousError (best_candidate);
6050                         ec.Report.Error (1546, loc, "Property or event `{0}' is not supported by the C# language",
6051                                 GetSignatureForError ());
6052                 }
6053
6054                 bool IsSingleDimensionalArrayLength ()
6055                 {
6056                         if (best_candidate.DeclaringType.BuiltinType != BuiltinTypeSpec.Type.Array || !best_candidate.HasGet || Name != "Length")
6057                                 return false;
6058
6059                         ArrayContainer ac = InstanceExpression.Type as ArrayContainer;
6060                         return ac != null && ac.Rank == 1;
6061                 }
6062
6063                 public override void Emit (EmitContext ec, bool leave_copy)
6064                 {
6065                         //
6066                         // Special case: length of single dimension array property is turned into ldlen
6067                         //
6068                         if (IsSingleDimensionalArrayLength ()) {
6069                                 EmitInstance (ec, false);
6070                                 ec.Emit (OpCodes.Ldlen);
6071                                 ec.Emit (OpCodes.Conv_I4);
6072                                 return;
6073                         }
6074
6075                         base.Emit (ec, leave_copy);
6076                 }
6077
6078                 public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
6079                 {
6080                         Arguments args;
6081                         LocalTemporary await_source_arg = null;
6082
6083                         if (isCompound && !(source is DynamicExpressionStatement)) {
6084                                 emitting_compound_assignment = true;
6085                                 source.Emit (ec);
6086
6087                                 if (has_await_arguments) {
6088                                         await_source_arg = new LocalTemporary (Type);
6089                                         await_source_arg.Store (ec);
6090
6091                                         args = new Arguments (1);
6092                                         args.Add (new Argument (await_source_arg));
6093
6094                                         if (leave_copy) {
6095                                                 temp = await_source_arg;
6096                                         }
6097
6098                                         has_await_arguments = false;
6099                                 } else {
6100                                         args = null;
6101
6102                                         if (leave_copy) {
6103                                                 ec.Emit (OpCodes.Dup);
6104                                                 temp = new LocalTemporary (this.Type);
6105                                                 temp.Store (ec);
6106                                         }
6107                                 }
6108                         } else {
6109                                 args = arguments == null ? new Arguments (1) : arguments;
6110
6111                                 if (leave_copy) {
6112                                         source.Emit (ec);
6113                                         temp = new LocalTemporary (this.Type);
6114                                         temp.Store (ec);
6115                                         args.Add (new Argument (temp));
6116                                 } else {
6117                                         args.Add (new Argument (source));
6118                                 }
6119                         }
6120
6121                         emitting_compound_assignment = false;
6122
6123                         var call = new CallEmitter ();
6124                         call.InstanceExpression = InstanceExpression;
6125                         if (args == null)
6126                                 call.InstanceExpressionOnStack = true;
6127
6128                         call.Emit (ec, Setter, args, loc);
6129
6130                         if (temp != null) {
6131                                 temp.Emit (ec);
6132                                 temp.Release (ec);
6133                         }
6134
6135                         if (await_source_arg != null) {
6136                                 await_source_arg.Release (ec);
6137                         }
6138                 }
6139
6140                 protected override Expression OverloadResolve (ResolveContext rc, Expression right_side)
6141                 {
6142                         eclass = ExprClass.PropertyAccess;
6143
6144                         if (best_candidate.IsNotCSharpCompatible) {
6145                                 Error_PropertyNotValid (rc);
6146                         }
6147
6148                         ResolveInstanceExpression (rc, right_side);
6149
6150                         if ((best_candidate.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0 && best_candidate.DeclaringType != InstanceExpression.Type) {
6151                                 var filter = new MemberFilter (best_candidate.Name, 0, MemberKind.Property, null, null);
6152                                 var p = MemberCache.FindMember (InstanceExpression.Type, filter, BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly) as PropertySpec;
6153                                 if (p != null) {
6154                                         type = p.MemberType;
6155                                 }
6156                         }
6157
6158                         DoBestMemberChecks (rc, best_candidate);
6159
6160                         // Handling of com-imported properties with any number of default property parameters
6161                         if (best_candidate.HasGet && !best_candidate.Get.Parameters.IsEmpty) {
6162                                 var p = best_candidate.Get.Parameters;
6163                                 arguments = new Arguments (p.Count);
6164                                 for (int i = 0; i < p.Count; ++i) {
6165                                         arguments.Add (new Argument (OverloadResolver.ResolveDefaultValueArgument (rc, p.Types [i], p.FixedParameters [i].DefaultValue, loc)));
6166                                 }
6167                         } else if (best_candidate.HasSet && best_candidate.Set.Parameters.Count > 1) {
6168                                 var p = best_candidate.Set.Parameters;
6169                                 arguments = new Arguments (p.Count - 1);
6170                                 for (int i = 0; i < p.Count - 1; ++i) {
6171                                         arguments.Add (new Argument (OverloadResolver.ResolveDefaultValueArgument (rc, p.Types [i], p.FixedParameters [i].DefaultValue, loc)));
6172                                 }
6173                         }
6174
6175                         return this;
6176                 }
6177
6178                 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
6179                 {
6180                         Error_TypeArgumentsCannotBeUsed (ec, "property", GetSignatureForError (), loc);
6181                 }
6182         }
6183
6184         abstract class PropertyOrIndexerExpr<T> : MemberExpr, IDynamicAssign where T : PropertySpec
6185         {
6186                 // getter and setter can be different for base calls
6187                 MethodSpec getter, setter;
6188                 protected T best_candidate;
6189
6190                 protected LocalTemporary temp;
6191                 protected bool emitting_compound_assignment;
6192                 protected bool has_await_arguments;
6193
6194                 protected PropertyOrIndexerExpr (Location l)
6195                 {
6196                         loc = l;
6197                 }
6198
6199                 #region Properties
6200
6201                 protected abstract Arguments Arguments { get; set; }
6202
6203                 public MethodSpec Getter {
6204                         get {
6205                                 return getter;
6206                         }
6207                         set {
6208                                 getter = value;
6209                         }
6210                 }
6211
6212                 public MethodSpec Setter {
6213                         get {
6214                                 return setter;
6215                         }
6216                         set {
6217                                 setter = value;
6218                         }
6219                 }
6220
6221                 #endregion
6222
6223                 protected override Expression DoResolve (ResolveContext ec)
6224                 {
6225                         if (eclass == ExprClass.Unresolved) {
6226                                 var expr = OverloadResolve (ec, null);
6227                                 if (expr == null)
6228                                         return null;
6229
6230                                 if (expr != this)
6231                                         return expr.Resolve (ec);
6232                         }
6233
6234                         if (!ResolveGetter (ec))
6235                                 return null;
6236
6237                         return this;
6238                 }
6239
6240                 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
6241                 {
6242                         if (right_side == EmptyExpression.OutAccess) {
6243                                 // TODO: best_candidate can be null at this point
6244                                 INamedBlockVariable variable = null;
6245                                 if (best_candidate != null && ec.CurrentBlock.ParametersBlock.TopBlock.GetLocalName (best_candidate.Name, ec.CurrentBlock, ref variable) && variable is Linq.RangeVariable) {
6246                                         ec.Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter",
6247                                                 best_candidate.Name);
6248                                 } else {
6249                                         right_side.DoResolveLValue (ec, this);
6250                                 }
6251                                 return null;
6252                         }
6253
6254                         if (eclass == ExprClass.Unresolved) {
6255                                 var expr = OverloadResolve (ec, right_side);
6256                                 if (expr == null)
6257                                         return null;
6258
6259                                 if (expr != this)
6260                                         return expr.ResolveLValue (ec, right_side);
6261                         }
6262
6263                         if (!ResolveSetter (ec))
6264                                 return null;
6265
6266                         return this;
6267                 }
6268
6269                 //
6270                 // Implements the IAssignMethod interface for assignments
6271                 //
6272                 public virtual void Emit (EmitContext ec, bool leave_copy)
6273                 {
6274                         var call = new CallEmitter ();
6275                         call.InstanceExpression = InstanceExpression;
6276                         if (has_await_arguments)
6277                                 call.HasAwaitArguments = true;
6278                         else
6279                                 call.DuplicateArguments = emitting_compound_assignment;
6280
6281                         call.Emit (ec, Getter, Arguments, loc);
6282
6283                         if (call.HasAwaitArguments) {
6284                                 InstanceExpression = call.InstanceExpression;
6285                                 Arguments = call.EmittedArguments;
6286                                 has_await_arguments = true;
6287                         }
6288
6289                         if (leave_copy) {
6290                                 ec.Emit (OpCodes.Dup);
6291                                 temp = new LocalTemporary (Type);
6292                                 temp.Store (ec);
6293                         }
6294                 }
6295
6296                 public abstract void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound);
6297
6298                 public override void Emit (EmitContext ec)
6299                 {
6300                         Emit (ec, false);
6301                 }
6302
6303                 protected override FieldExpr EmitToFieldSource (EmitContext ec)
6304                 {
6305                         has_await_arguments = true;
6306                         Emit (ec, false);
6307                         return null;
6308                 }
6309
6310                 public abstract SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source);
6311
6312                 protected abstract Expression OverloadResolve (ResolveContext rc, Expression right_side);
6313
6314                 bool ResolveGetter (ResolveContext rc)
6315                 {
6316                         if (!best_candidate.HasGet) {
6317                                 if (InstanceExpression != EmptyExpression.Null) {
6318                                         rc.Report.SymbolRelatedToPreviousError (best_candidate);
6319                                         rc.Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
6320                                                 best_candidate.GetSignatureForError ());
6321                                         return false;
6322                                 }
6323                         } else if (!best_candidate.Get.IsAccessible (rc)) {
6324                                 if (best_candidate.HasDifferentAccessibility) {
6325                                         rc.Report.SymbolRelatedToPreviousError (best_candidate.Get);
6326                                         rc.Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
6327                                                 TypeManager.CSharpSignature (best_candidate));
6328                                 } else {
6329                                         rc.Report.SymbolRelatedToPreviousError (best_candidate.Get);
6330                                         ErrorIsInaccesible (rc, best_candidate.Get.GetSignatureForError (), loc);
6331                                 }
6332                         }
6333
6334                         if (best_candidate.HasDifferentAccessibility) {
6335                                 CheckProtectedMemberAccess (rc, best_candidate.Get);
6336                         }
6337
6338                         getter = CandidateToBaseOverride (rc, best_candidate.Get);
6339                         return true;
6340                 }
6341
6342                 bool ResolveSetter (ResolveContext rc)
6343                 {
6344                         if (!best_candidate.HasSet) {
6345                                 rc.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read-only)",
6346                                         GetSignatureForError ());
6347                                 return false;
6348                         }
6349
6350                         if (!best_candidate.Set.IsAccessible (rc)) {
6351                                 if (best_candidate.HasDifferentAccessibility) {
6352                                         rc.Report.SymbolRelatedToPreviousError (best_candidate.Set);
6353                                         rc.Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
6354                                                 GetSignatureForError ());
6355                                 } else {
6356                                         rc.Report.SymbolRelatedToPreviousError (best_candidate.Set);
6357                                         ErrorIsInaccesible (rc, best_candidate.GetSignatureForError (), loc);
6358                                 }
6359                         }
6360
6361                         if (best_candidate.HasDifferentAccessibility)
6362                                 CheckProtectedMemberAccess (rc, best_candidate.Set);
6363
6364                         setter = CandidateToBaseOverride (rc, best_candidate.Set);
6365                         return true;
6366                 }
6367         }
6368
6369         /// <summary>
6370         ///   Fully resolved expression that evaluates to an Event
6371         /// </summary>
6372         public class EventExpr : MemberExpr, IAssignMethod
6373         {
6374                 readonly EventSpec spec;
6375                 MethodSpec op;
6376
6377                 public EventExpr (EventSpec spec, Location loc)
6378                 {
6379                         this.spec = spec;
6380                         this.loc = loc;
6381                 }
6382
6383                 #region Properties
6384
6385                 protected override TypeSpec DeclaringType {
6386                         get {
6387                                 return spec.DeclaringType;
6388                         }
6389                 }
6390
6391                 public override string Name {
6392                         get {
6393                                 return spec.Name;
6394                         }
6395                 }
6396
6397                 public override bool IsInstance {
6398                         get {
6399                                 return !spec.IsStatic;
6400                         }
6401                 }
6402
6403                 public override bool IsStatic {
6404                         get {
6405                                 return spec.IsStatic;
6406                         }
6407                 }
6408
6409                 public override string KindName {
6410                         get { return "event"; }
6411                 }
6412
6413                 public MethodSpec Operator {
6414                         get {
6415                                 return op;
6416                         }
6417                 }
6418
6419                 #endregion
6420
6421                 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
6422                 {
6423                         //
6424                         // If the event is local to this class and we are not lhs of +=/-= we transform ourselves into a FieldExpr
6425                         //
6426                         if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) {
6427                                 if (spec.BackingField != null &&
6428                                         (spec.DeclaringType == ec.CurrentType || TypeManager.IsNestedChildOf (ec.CurrentType, spec.DeclaringType.MemberDefinition))) {
6429
6430                                         spec.MemberDefinition.SetIsUsed ();
6431
6432                                         if (!ec.IsObsolete) {
6433                                                 ObsoleteAttribute oa = spec.GetAttributeObsolete ();
6434                                                 if (oa != null)
6435                                                         AttributeTester.Report_ObsoleteMessage (oa, spec.GetSignatureForError (), loc, ec.Report);
6436                                         }
6437
6438                                         if ((spec.Modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
6439                                                 Error_AssignmentEventOnly (ec);
6440
6441                                         FieldExpr ml = new FieldExpr (spec.BackingField, loc);
6442
6443                                         InstanceExpression = null;
6444
6445                                         return ml.ResolveMemberAccess (ec, left, original);
6446                                 }
6447                         }
6448
6449                         return base.ResolveMemberAccess (ec, left, original);
6450                 }
6451
6452                 public override Expression CreateExpressionTree (ResolveContext ec)
6453                 {
6454                         throw new NotSupportedException ("ET");
6455                 }
6456
6457                 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
6458                 {
6459                         if (right_side == EmptyExpression.EventAddition) {
6460                                 op = spec.AccessorAdd;
6461                         } else if (right_side == EmptyExpression.EventSubtraction) {
6462                                 op = spec.AccessorRemove;
6463                         }
6464
6465                         if (op == null) {
6466                                 Error_AssignmentEventOnly (ec);
6467                                 return null;
6468                         }
6469
6470                         op = CandidateToBaseOverride (ec, op);
6471                         return this;
6472                 }
6473
6474                 protected override Expression DoResolve (ResolveContext ec)
6475                 {
6476                         eclass = ExprClass.EventAccess;
6477                         type = spec.MemberType;
6478
6479                         ResolveInstanceExpression (ec, null);
6480
6481                         if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) {
6482                                 Error_AssignmentEventOnly (ec);
6483                         }
6484
6485                         DoBestMemberChecks (ec, spec);
6486                         return this;
6487                 }               
6488
6489                 public override void Emit (EmitContext ec)
6490                 {
6491                         throw new NotSupportedException ();
6492                         //Error_CannotAssign ();
6493                 }
6494
6495                 #region IAssignMethod Members
6496
6497                 public void Emit (EmitContext ec, bool leave_copy)
6498                 {
6499                         throw new NotImplementedException ();
6500                 }
6501
6502                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
6503                 {
6504                         if (leave_copy || !isCompound)
6505                                 throw new NotImplementedException ("EventExpr::EmitAssign");
6506
6507                         Arguments args = new Arguments (1);
6508                         args.Add (new Argument (source));
6509
6510                         var call = new CallEmitter ();
6511                         call.InstanceExpression = InstanceExpression;
6512                         call.Emit (ec, op, args, loc);
6513                 }
6514
6515                 #endregion
6516
6517                 void Error_AssignmentEventOnly (ResolveContext ec)
6518                 {
6519                         if (spec.DeclaringType == ec.CurrentType || TypeManager.IsNestedChildOf (ec.CurrentType, spec.DeclaringType.MemberDefinition)) {
6520                                 ec.Report.Error (79, loc,
6521                                         "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator",
6522                                         GetSignatureForError ());
6523                         } else {
6524                                 ec.Report.Error (70, loc,
6525                                         "The event `{0}' can only appear on the left hand side of += or -= when used outside of the type `{1}'",
6526                                         GetSignatureForError (), spec.DeclaringType.GetSignatureForError ());
6527                         }
6528                 }
6529
6530                 protected override void Error_CannotCallAbstractBase (ResolveContext rc, string name)
6531                 {
6532                         name = name.Substring (0, name.LastIndexOf ('.'));
6533                         base.Error_CannotCallAbstractBase (rc, name);
6534                 }
6535
6536                 public override string GetSignatureForError ()
6537                 {
6538                         return TypeManager.CSharpSignature (spec);
6539                 }
6540
6541                 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
6542                 {
6543                         Error_TypeArgumentsCannotBeUsed (ec, "event", GetSignatureForError (), loc);
6544                 }
6545         }
6546
6547         public class TemporaryVariableReference : VariableReference
6548         {
6549                 public class Declarator : Statement
6550                 {
6551                         TemporaryVariableReference variable;
6552
6553                         public Declarator (TemporaryVariableReference variable)
6554                         {
6555                                 this.variable = variable;
6556                                 loc = variable.loc;
6557                         }
6558
6559                         protected override void DoEmit (EmitContext ec)
6560                         {
6561                                 variable.li.CreateBuilder (ec);
6562                         }
6563
6564                         public override void Emit (EmitContext ec)
6565                         {
6566                                 // Don't create sequence point
6567                                 DoEmit (ec);
6568                         }
6569
6570                         protected override void CloneTo (CloneContext clonectx, Statement target)
6571                         {
6572                                 // Nothing
6573                         }
6574                 }
6575
6576                 LocalVariable li;
6577
6578                 public TemporaryVariableReference (LocalVariable li, Location loc)
6579                 {
6580                         this.li = li;
6581                         this.type = li.Type;
6582                         this.loc = loc;
6583                 }
6584
6585                 public override bool IsLockedByStatement {
6586                         get {
6587                                 return false;
6588                         }
6589                         set {
6590                         }
6591                 }
6592
6593                 public LocalVariable LocalInfo {
6594                     get {
6595                         return li;
6596                     }
6597                 }
6598
6599                 public static TemporaryVariableReference Create (TypeSpec type, Block block, Location loc)
6600                 {
6601                         var li = LocalVariable.CreateCompilerGenerated (type, block, loc);
6602                         return new TemporaryVariableReference (li, loc);
6603                 }
6604
6605                 protected override Expression DoResolve (ResolveContext ec)
6606                 {
6607                         eclass = ExprClass.Variable;
6608
6609                         //
6610                         // Don't capture temporary variables except when using
6611                         // state machine redirection and block yields
6612                         //
6613                         if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod is StateMachineInitializer &&
6614                                 (ec.CurrentBlock.Explicit.HasYield || ec.CurrentBlock.Explicit.HasAwait) &&
6615                                 ec.IsVariableCapturingRequired) {
6616                                 AnonymousMethodStorey storey = li.Block.Explicit.CreateAnonymousMethodStorey (ec);
6617                                 storey.CaptureLocalVariable (ec, li);
6618                         }
6619
6620                         return this;
6621                 }
6622
6623                 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
6624                 {
6625                         return Resolve (ec);
6626                 }
6627                 
6628                 public override void Emit (EmitContext ec)
6629                 {
6630                         li.CreateBuilder (ec);
6631
6632                         Emit (ec, false);
6633                 }
6634
6635                 public void EmitAssign (EmitContext ec, Expression source)
6636                 {
6637                         li.CreateBuilder (ec);
6638
6639                         EmitAssign (ec, source, false, false);
6640                 }
6641
6642                 public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
6643                 {
6644                         return li.HoistedVariant;
6645                 }
6646
6647                 public override bool IsFixed {
6648                         get { return true; }
6649                 }
6650
6651                 public override bool IsRef {
6652                         get { return false; }
6653                 }
6654
6655                 public override string Name {
6656                         get { throw new NotImplementedException (); }
6657                 }
6658
6659                 public override void SetHasAddressTaken ()
6660                 {
6661                         throw new NotImplementedException ();
6662                 }
6663
6664                 protected override ILocalVariable Variable {
6665                         get { return li; }
6666                 }
6667
6668                 public override VariableInfo VariableInfo {
6669                         get { return null; }
6670                 }
6671
6672                 public override void VerifyAssigned (ResolveContext rc)
6673                 {
6674                 }
6675         }
6676
6677         /// 
6678         /// Handles `var' contextual keyword; var becomes a keyword only
6679         /// if no type called var exists in a variable scope
6680         /// 
6681         class VarExpr : SimpleName
6682         {
6683                 public VarExpr (Location loc)
6684                         : base ("var", loc)
6685                 {
6686                 }
6687
6688                 public bool InferType (ResolveContext ec, Expression right_side)
6689                 {
6690                         if (type != null)
6691                                 throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
6692                         
6693                         type = right_side.Type;
6694                         if (type == InternalType.NullLiteral || type.Kind == MemberKind.Void || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) {
6695                                 ec.Report.Error (815, loc,
6696                                         "An implicitly typed local variable declaration cannot be initialized with `{0}'",
6697                                         type.GetSignatureForError ());
6698                                 return false;
6699                         }
6700
6701                         eclass = ExprClass.Variable;
6702                         return true;
6703                 }
6704
6705                 protected override void Error_TypeOrNamespaceNotFound (IMemberContext ec)
6706                 {
6707                         if (ec.Module.Compiler.Settings.Version < LanguageVersion.V_3)
6708                                 base.Error_TypeOrNamespaceNotFound (ec);
6709                         else
6710                                 ec.Module.Compiler.Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration");
6711                 }
6712         }
6713 }