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