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