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