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