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