Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/ecore.cs @ 13397

Last change on this file since 13397 was 11700, checked in by jkarder, 9 years ago

#2077: created branch and added first version

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