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