Fix compound event assigments with dynamic side effect
[mono.git] / mcs / mcs / ecore.cs
index ab04c7cb904237a2e574c67896151998bd00cb88..abc7fc252b9f0cfb31606b244665c21ce3d2445d 100644 (file)
@@ -61,9 +61,6 @@ namespace Mono.CSharp {
 
                // Mask of all the expression class flags.
                MaskExprClass = VariableOrValue | Type | MethodGroup | TypeParameter,
-
-               // Set if this is resolving the first part of a MemberAccess.
-               Intermediate            = 1 << 11,
        }
 
        //
@@ -128,7 +125,7 @@ namespace Mono.CSharp {
                        set { type = value; }
                }
 
-               public virtual Location Location {
+               public Location Location {
                        get { return loc; }
                }
 
@@ -142,40 +139,6 @@ namespace Mono.CSharp {
                        return type.GetDefinition ().GetSignatureForError ();
                }
 
-               public static bool IsMemberAccessible (TypeSpec invocation_type, MemberSpec mi, out bool must_do_cs1540_check)
-               {
-                       var ma = mi.Modifiers & Modifiers.AccessibilityMask;
-
-                       must_do_cs1540_check = false; // by default we do not check for this
-
-                       if (ma == Modifiers.PUBLIC)
-                               return true;
-               
-                       //
-                       // If only accessible to the current class or children
-                       //
-                       if (ma == Modifiers.PRIVATE)
-                               return invocation_type.MemberDefinition == mi.DeclaringType.MemberDefinition ||
-                                       TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
-
-                       if ((ma & Modifiers.INTERNAL) != 0) {
-                               var b = TypeManager.IsThisOrFriendAssembly (invocation_type == InternalType.FakeInternalType ?
-                                        CodeGen.Assembly.Builder : invocation_type.Assembly, mi.DeclaringType.Assembly);
-                               if (b || ma == Modifiers.INTERNAL)
-                                       return b;
-                       }
-
-                       // Family and FamANDAssem require that we derive.
-                       // FamORAssem requires that we derive if in different assemblies.
-                       if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
-                               return false;
-
-                       if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
-                               must_do_cs1540_check = true;
-
-                       return true;
-               }
-
                public virtual bool IsNull {
                        get {
                                return false;
@@ -232,15 +195,6 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               //
-               // C# 3.0 introduced contextual keywords (var) which behaves like a type if type with
-               // same name exists or as a keyword when no type was found
-               // 
-               public virtual TypeExpr ResolveAsContextualType (IMemberContext rc, bool silent)
-               {
-                       return ResolveAsTypeTerminal (rc, silent);
-               }               
-               
                //
                // This is used to resolve the expression as a type, a null
                // value will be returned if the expression is not a type
@@ -264,7 +218,7 @@ namespace Mono.CSharp {
 
                        if (!te.CheckAccessLevel (ec)) {
                                ec.Compiler.Report.SymbolRelatedToPreviousError (te.Type);
-                               ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type), ec.Compiler.Report);
+                               ErrorIsInaccesible (ec, te.Type.GetSignatureForError (), loc);
                        }
 
                        te.loc = loc;
@@ -283,19 +237,9 @@ namespace Mono.CSharp {
                        return te;
                }
        
-               public static void ErrorIsInaccesible (Location loc, string name, Report Report)
-               {
-                       Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name);
-               }
-
-               protected static void Error_CannotAccessProtected (ResolveContext ec, Location loc, MemberSpec m, TypeSpec qualifier, TypeSpec container)
+               public static void ErrorIsInaccesible (IMemberContext rc, string member, Location loc)
                {
-                       ec.Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}'."
-                               + " The qualifier must be of type `{2}' or derived from it", 
-                               m.GetSignatureForError (),
-                               TypeManager.CSharpName (qualifier),
-                               TypeManager.CSharpName (container));
-
+                       rc.Compiler.Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", member);
                }
 
                public void Error_ExpressionMustBeConstant (ResolveContext rc, Location loc, string e_name)
@@ -376,11 +320,6 @@ namespace Mono.CSharp {
                                type.GetSignatureForError (), target.GetSignatureForError ());
                }
 
-               public virtual void Error_VariableIsUsedBeforeItIsDeclared (Report Report, string name)
-               {
-                       Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", name);
-               }
-
                public void Error_TypeArgumentsCannotBeUsed (Report report, Location loc, MemberSpec member, int arity)
                {
                        // Better message for possible generic expressions
@@ -400,11 +339,16 @@ namespace Mono.CSharp {
                                                name, member.GetSignatureForError ());
                                }
                        } else {
-                               report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments",
-                                       ExprClassName, GetSignatureForError ());
+                               Error_TypeArgumentsCannotBeUsed (report, ExprClassName, GetSignatureForError (), loc);
                        }
                }
 
+               public void Error_TypeArgumentsCannotBeUsed (Report report, string exprType, string name, Location loc)
+               {
+                       report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments",
+                               exprType, name);
+               }
+
                protected virtual void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name)
                {
                        Error_TypeDoesNotContainDefinition (ec, loc, type, name);
@@ -422,7 +366,12 @@ namespace Mono.CSharp {
                        ec.Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer");
                }
 
-               ResolveFlags ExprClassToResolveFlags {
+               protected void Error_VoidPointerOperation (ResolveContext rc)
+               {
+                       rc.Report.Error (242, loc, "The operation in question is undefined on void pointers");
+               }
+
+               public ResolveFlags ExprClassToResolveFlags {
                        get {
                                switch (eclass) {
                                case ExprClass.Type:
@@ -460,26 +409,30 @@ namespace Mono.CSharp {
                {
                        if (eclass != ExprClass.Unresolved)
                                return this;
-
+                       
                        Expression e;
-                       if (this is SimpleName) {
-                               e = ((SimpleName) this).DoResolve (ec, (flags & ResolveFlags.Intermediate) != 0);
-                       } else {
+                       try {
                                e = DoResolve (ec);
-                       }
 
-                       if (e == null)
-                               return null;
+                               if (e == null)
+                                       return null;
 
-                       if ((flags & e.ExprClassToResolveFlags) == 0) {
-                               e.Error_UnexpectedKind (ec, flags, loc);
-                               return null;
-                       }
+                               if ((flags & e.ExprClassToResolveFlags) == 0) {
+                                       e.Error_UnexpectedKind (ec, flags, loc);
+                                       return null;
+                               }
 
-                       if (e.type == null)
-                               throw new InternalErrorException ("Expression `{0}' didn't set its type in DoResolve", e.GetType ());
+                               if (e.type == null)
+                                       throw new InternalErrorException ("Expression `{0}' didn't set its type in DoResolve", e.GetType ());
 
-                       return e;
+                               return e;
+                       } catch (Exception ex) {
+                               if (loc.IsNull || Report.DebugFlags > 0 || ex is CompletionResult || ec.Report.IsDisabled)
+                                       throw;
+
+                               ec.Report.Error (584, loc, "Internal compiler error: {0}", ex.Message);
+                               return EmptyExpression.Null;    // TODO: Add location
+                       }
                }
 
                /// <summary>
@@ -535,7 +488,8 @@ namespace Mono.CSharp {
 
                public virtual void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
                {
-                       Attribute.Error_AttributeArgumentNotValid (rc, loc);
+                       rc.Compiler.Report.Error (182, loc,
+                               "An attribute argument must be a constant expression, typeof expression or array creation expression");
                }
 
                /// <summary>
@@ -581,7 +535,7 @@ namespace Mono.CSharp {
                ///   Returns a fully formed expression after a MemberLookup
                /// </summary>
                /// 
-               public static Expression ExprClassFromMemberInfo (TypeSpec container_type, MemberSpec spec, Location loc)
+               static Expression ExprClassFromMemberInfo (MemberSpec spec, Location loc)
                {
                        if (spec is EventSpec)
                                return new EventExpr ((EventSpec) spec, loc);
@@ -590,194 +544,106 @@ namespace Mono.CSharp {
                        if (spec is FieldSpec)
                                return new FieldExpr ((FieldSpec) spec, loc);
                        if (spec is PropertySpec)
-                               return new PropertyExpr (container_type, (PropertySpec) spec, loc);
+                               return new PropertyExpr ((PropertySpec) spec, loc);
                        if (spec is TypeSpec)
                                return new TypeExpression (((TypeSpec) spec), loc);
 
                        return null;
                }
 
-               //
-               // FIXME: Probably implement a cache for (t,name,current_access_set)?
-               //
-               // This code could use some optimizations, but we need to do some
-               // measurements.  For example, we could use a delegate to `flag' when
-               // something can not any longer be a method-group (because it is something
-               // else).
-               //
-               // Return values:
-               //     If the return value is an Array, then it is an array of
-               //     MethodBases
-               //   
-               //     If the return value is an MemberInfo, it is anything, but a Method
-               //
-               //     null on error.
-               //
-               // FIXME: When calling MemberLookup inside an `Invocation', we should pass
-               // the arguments here and have MemberLookup return only the methods that
-               // match the argument count/type, unlike we are doing now (we delay this
-               // decision).
-               //
-               // This is so we can catch correctly attempts to invoke instance methods
-               // from a static body (scan for error 120 in ResolveSimpleName).
-               //
-               //
-               // FIXME: Potential optimization, have a static ArrayList
-               //
-
-               public static Expression MemberLookup (CompilerContext ctx, TypeSpec container_type, TypeSpec queried_type, string name, int arity,
-                                                      MemberKind mt, BindingRestriction bf, Location loc)
+               protected static MethodSpec ConstructorLookup (ResolveContext rc, TypeSpec type, ref Arguments args, Location loc)
                {
-                       return MemberLookup (ctx, container_type, null, queried_type, name, arity, mt, bf, loc);
-               }
-
-               //
-               // Lookup type `queried_type' for code in class `container_type' with a qualifier of
-               // `qualifier_type' or null to lookup members in the current class.
-               //
-               public static Expression MemberLookup (CompilerContext ctx, TypeSpec container_type,
-                                                      TypeSpec qualifier_type, TypeSpec queried_type,
-                                                      string name, int arity, MemberKind mt,
-                                                      BindingRestriction binding, Location loc)
-               {
-                       var mi = TypeManager.MemberLookup (container_type, qualifier_type,
-                                                                    queried_type, mt, binding, name, arity, null);
-                       if (mi == null)
-                               return null;
-
-                       var first = mi [0];
-                       if (mi.Count > 1) {
-                               foreach (var mc in mi) {
-                                       if (mc is MethodSpec)
-                                               return new MethodGroupExpr (mi, queried_type, loc);
+                       var ctors = MemberCache.FindMembers (type, ConstructorInfo.ConstructorName, true);
+                       if (ctors == null) {
+                               rc.Report.SymbolRelatedToPreviousError (type);
+                               if (type.IsStruct) {
+                                       // Report meaningful error for struct as they always have default ctor in C# context
+                                       OverloadResolver.Error_ConstructorMismatch (rc, type, args == null ? 0 : args.Count, loc);
+                               } else {
+                                       rc.Report.Error (143, loc, "The class `{0}' has no constructors defined",
+                                               type.GetSignatureForError ());
                                }
 
-                               ctx.Report.SymbolRelatedToPreviousError (mi [1]);
-                               ctx.Report.SymbolRelatedToPreviousError (first);
-                               ctx.Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
-                                       first.GetSignatureForError (), mi [1].GetSignatureForError ());
+                               return null;
                        }
 
-                       if (first is MethodSpec)
-                               return new MethodGroupExpr (mi, queried_type, loc);
-
-                       return ExprClassFromMemberInfo (container_type, first, loc);
-               }
-
-               public static Expression MemberLookup (CompilerContext ctx, TypeSpec container_type, TypeSpec queried_type,
-                                                          string name, int arity, BindingRestriction binding, Location loc)
-               {
-                       return MemberLookup (ctx, container_type, null, queried_type, name, arity,
-                                            MemberKind.All, binding | BindingRestriction.AccessibleOnly, loc);
-               }
-
-               public static Expression MemberLookup (CompilerContext ctx, TypeSpec container_type, TypeSpec qualifier_type,
-                                                          TypeSpec queried_type, string name, int arity, BindingRestriction binding, Location loc)
-               {
-                       return MemberLookup (ctx, container_type, qualifier_type, queried_type,
-                                                name, arity, MemberKind.All, binding | BindingRestriction.AccessibleOnly, loc);
+                       var r = new OverloadResolver (ctors, OverloadResolver.Restrictions.NoBaseMembers, loc);
+                       return r.ResolveMember<MethodSpec> (rc, ref args);
                }
 
-               public static MethodGroupExpr MethodLookup (CompilerContext ctx, TypeSpec container_type, TypeSpec queried_type,
-                                                      MemberKind kind, string name, int arity, Location loc)
+               [Flags]
+               public enum MemberLookupRestrictions
                {
-                       return (MethodGroupExpr)MemberLookup (ctx, container_type, null, queried_type, name, arity,
-                                            kind, BindingRestriction.AccessibleOnly, loc);
+                       None = 0,
+                       InvocableOnly = 1,
+                       ExactArity = 1 << 2,
+                       ReadAccess = 1 << 3
                }
 
-               /// <summary>
-               ///   This is a wrapper for MemberLookup that is not used to "probe", but
-               ///   to find a final definition.  If the final definition is not found, we
-               ///   look for private members and display a useful debugging message if we
-               ///   find it.
-               /// </summary>
-               protected Expression MemberLookupFinal (ResolveContext ec, TypeSpec qualifier_type,
-                                                           TypeSpec queried_type, string name, int arity,
-                                                           MemberKind mt, BindingRestriction bf,
-                                                           Location loc)
+               //
+               // Lookup type `queried_type' for code in class `container_type' with a qualifier of
+               // `qualifier_type' or null to lookup members in the current class.
+               //
+               public static Expression MemberLookup (ResolveContext rc, TypeSpec currentType, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc)
                {
-                       Expression e;
-
-                       int errors = ec.Report.Errors;
-                       e = MemberLookup (ec.Compiler, ec.CurrentType, qualifier_type, queried_type, name, arity, mt, bf, loc);
+                       var members = MemberCache.FindMembers (queried_type, name, false);
+                       if (members == null)
+                               return null;
 
-                       if (e != null || errors != ec.Report.Errors)
-                               return e;
+                       MemberSpec non_method = null;
+                       MemberSpec ambig_non_method = null;
+                       currentType = currentType ?? InternalType.FakeInternalType;
+                       do {
+                               for (int i = 0; i < members.Count; ++i) {
+                                       var member = members[i];
 
-                       // No errors were reported by MemberLookup, but there was an error.
-                       return Error_MemberLookupFailed (ec, ec.CurrentType, qualifier_type, queried_type,
-                                       name, arity, null, mt, bf);
-               }
+                                       // HACK: for events because +=/-= can appear at same class only, should use OverrideToBase there
+                                       if ((member.Modifiers & Modifiers.OVERRIDE) != 0 && member.Kind != MemberKind.Event)
+                                               continue;
 
-               protected virtual Expression Error_MemberLookupFailed (ResolveContext ec, TypeSpec container_type, TypeSpec qualifier_type,
-                                                      TypeSpec queried_type, string name, int arity, string class_name,
-                                                          MemberKind mt, BindingRestriction bf)
-               {
-                       IList<MemberSpec> lookup = null;
-                       if (queried_type == null) {
-                               class_name = "global::";
-                       } else {
-                               BindingRestriction restriction = bf & BindingRestriction.DeclaredOnly;
+                                       if ((arity > 0 || (restrictions & MemberLookupRestrictions.ExactArity) != 0) && member.Arity != arity)
+                                               continue;
 
-                               lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
-                                       mt, restriction, name, arity, null);
+                                       if (rc != null && !member.IsAccessible (currentType))
+                                               continue;
 
-                               if (lookup != null) {
-                                       Expression e = Error_MemberLookupFailed (ec, queried_type, lookup);
+                                       if ((restrictions & MemberLookupRestrictions.InvocableOnly) != 0) {
+                                               if (member is MethodSpec)
+                                                       return new MethodGroupExpr (members, queried_type, loc);
 
-                                       //
-                                       // FIXME: This is still very wrong, it should be done inside
-                                       // OverloadResolve to do correct arguments matching.
-                                       // Requires MemberLookup accessiblity check removal
-                                       //
-                                       if (e == null || (mt & (MemberKind.Method | MemberKind.Constructor)) == 0) {
-                                               var mi = lookup.First ();
-                                               ec.Report.SymbolRelatedToPreviousError (mi);
-                                               if ((mi.Modifiers & Modifiers.PROTECTED) != 0 && qualifier_type != null && container_type != null && qualifier_type != container_type &&
-                                                       TypeManager.IsNestedFamilyAccessible (container_type, mi.DeclaringType)) {
-                                                       // Although a derived class can access protected members of
-                                                       // its base class it cannot do so through an instance of the
-                                                       // base class (CS1540).  If the qualifier_type is a base of the
-                                                       // ec.CurrentType and the lookup succeeds with the latter one,
-                                                       // then we are in this situation.
-                                                       Error_CannotAccessProtected (ec, loc, mi, qualifier_type, container_type);
-                                               } else {
-                                                       ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (mi), ec.Report);
-                                               }
+                                               if (!Invocation.IsMemberInvocable (member))
+                                                       continue;
                                        }
 
-                                       return e;
+                                       if (non_method == null || member is MethodSpec) {
+                                               non_method = member;
+                                       } else if (currentType != null) {
+                                               ambig_non_method = member;
+                                       }
                                }
 
-                               lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
-                                       MemberKind.All, BindingRestriction.None, name, -System.Math.Max (1, arity), null);
-                       }
+                               if (non_method != null) {
+                                       if (ambig_non_method != null && rc != null) {
+                                               rc.Report.SymbolRelatedToPreviousError (non_method);
+                                               rc.Report.SymbolRelatedToPreviousError (ambig_non_method);
+                                               rc.Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
+                                                       non_method.GetSignatureForError (), ambig_non_method.GetSignatureForError ());
+                                       }
 
-                       if (lookup == null) {
-                               if (class_name != null) {
-                                       ec.Report.Error (103, loc, "The name `{0}' does not exist in the current context",
-                                               name);
-                               } else {
-                                       Error_TypeDoesNotContainDefinition (ec, queried_type, name);
-                               }
-                               return null;
-                       }
+                                       if (non_method is MethodSpec)
+                                               return new MethodGroupExpr (members, queried_type, loc);
 
-                       var mge = Error_MemberLookupFailed (ec, queried_type, lookup);
-                       if (arity > 0 && mge != null) {
-                               mge.SetTypeArguments (ec, new TypeArguments (new FullNamedExpression [arity]));
-                       }
+                                       return ExprClassFromMemberInfo (non_method, loc);
+                               }
 
-                       return mge;
-               }
+                               if (members[0].DeclaringType.BaseType == null)
+                                       members = null;
+                               else
+                                       members = MemberCache.FindMembers (members[0].DeclaringType.BaseType, name, false);
 
-               protected virtual MemberExpr Error_MemberLookupFailed (ResolveContext ec, TypeSpec type, IList<MemberSpec> members)
-               {
-                       if (members.Any ((m) => !(m is MethodSpec)))
-                               return (MemberExpr) ExprClassFromMemberInfo (type, members.First (), loc);
+                       } while (members != null);
 
-                       // By default propagate the closest candidates upwards
-                       return new MethodGroupExpr (members, type, loc, true);
+                       return null;
                }
 
                protected virtual void Error_NegativeArrayIndex (ResolveContext ec, Location loc)
@@ -810,23 +676,23 @@ namespace Mono.CSharp {
 
                static Expression GetOperatorTrueOrFalse (ResolveContext ec, Expression e, bool is_true, Location loc)
                {
-                       MethodGroupExpr operator_group;
-                       string mname = Operator.GetMetadataName (is_true ? Operator.OpType.True : Operator.OpType.False);
-                       operator_group = MethodLookup (ec.Compiler, ec.CurrentType, e.Type, MemberKind.Operator, mname, 0, loc) as MethodGroupExpr;
-                       if (operator_group == null)
+                       var op = is_true ? Operator.OpType.True : Operator.OpType.False;
+                       var methods = MemberCache.GetUserOperator (e.type, op, false);
+                       if (methods == null)
                                return null;
 
                        Arguments arguments = new Arguments (1);
                        arguments.Add (new Argument (e));
-                       operator_group = operator_group.OverloadResolve (
-                               ec, ref arguments, false, loc);
 
-                       if (operator_group == null)
+                       var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc);
+                       var oper = res.ResolveOperator (ec, ref arguments);
+
+                       if (oper == null)
                                return null;
 
-                       return new UserOperatorCall (operator_group, arguments, null, loc);
+                       return new UserOperatorCall (oper, arguments, null, loc);
                }
-
+               
                public virtual string ExprClassName
                {
                        get {
@@ -948,12 +814,7 @@ namespace Mono.CSharp {
                        else
                                return 0;
                }
-
-               protected void Error_CannotCallAbstractBase (ResolveContext ec, string name)
-               {
-                       ec.Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
-               }
-               
+       
                protected void Error_CannotModifyIntermediateExpressionValue (ResolveContext ec)
                {
                        ec.Report.SymbolRelatedToPreviousError (type);
@@ -1033,7 +894,7 @@ namespace Mono.CSharp {
                // compile the same code using different type values for the same
                // arguments to find the correct overload
                //
-               public Expression Clone (CloneContext clonectx)
+               public virtual Expression Clone (CloneContext clonectx)
                {
                        Expression cloned = (Expression) MemberwiseClone ();
                        CloneTo (clonectx, cloned);
@@ -1095,7 +956,7 @@ namespace Mono.CSharp {
        /// </summary>
        public abstract class ExpressionStatement : Expression {
 
-               public virtual ExpressionStatement ResolveStatement (BlockContext ec)
+               public ExpressionStatement ResolveStatement (BlockContext ec)
                {
                        Expression e = Resolve (ec);
                        if (e == null)
@@ -1247,21 +1108,18 @@ namespace Mono.CSharp {
                // 'child.Type' to our target type (type)
                MethodSpec GetConversionOperator (bool find_explicit)
                {
-                       string operator_name = find_explicit ? "op_Explicit" : "op_Implicit";
-
-                       // Operators are always public
-                       var mi = TypeManager.MemberLookup (child.Type, child.Type, child.Type, MemberKind.Operator,
-                               BindingRestriction.None, operator_name, 0, null);
+                       var op = find_explicit ? Operator.OpType.Explicit : Operator.OpType.Implicit;
 
+                       var mi = MemberCache.GetUserOperator (child.Type, op, true);
                        if (mi == null){
-                               mi = TypeManager.MemberLookup (type, type, type, MemberKind.Operator,
-                                       BindingRestriction.None, operator_name, 0, null);
+                               mi = MemberCache.GetUserOperator (type, op, true);
                        }
                        
                        foreach (MethodSpec oper in mi) {
-                               AParametersCollection pd = oper.Parameters;
+                               if (oper.ReturnType != type)
+                                       continue;
 
-                               if (pd.Types [0] == child.Type && oper.ReturnType == type)
+                               if (oper.Parameters.Types [0] == child.Type)
                                        return oper;
                        }
 
@@ -1309,9 +1167,7 @@ namespace Mono.CSharp {
                public Expression Resolve ()
                {
                        if (operators == null) {
-                               var all_oper = TypeManager.MemberLookup (TypeManager.decimal_type,
-                                  TypeManager.decimal_type, TypeManager.decimal_type, MemberKind.Operator,
-                                  BindingRestriction.None, "op_Explicit", 0, null);
+                               var all_oper = MemberCache.GetUserOperator (TypeManager.decimal_type, Operator.OpType.Explicit, true);
 
                                operators = new Dictionary<TypeSpec, MethodSpec> ();
                                foreach (MethodSpec oper in all_oper) {
@@ -2017,6 +1873,16 @@ namespace Mono.CSharp {
                        this.loc = orig_expr.Location;
                }
 
+               #region Properties
+
+               public Expression OriginalExpression {
+                       get {
+                               return orig_expr;
+                       }
+               }
+
+               #endregion
+
                //
                // Creates fully resolved expression switcher
                //
@@ -2254,6 +2120,8 @@ namespace Mono.CSharp {
 
                        return Name;
                }
+
+               public abstract Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restriction);
        }
        
        /// <summary>
@@ -2282,18 +2150,6 @@ namespace Mono.CSharp {
                        return new SimpleName (Name, targs, loc);
                }
 
-               public static void Error_ObjectRefRequired (ResolveContext ec, Location l, string name)
-               {
-                       if (ec.HasSet (ResolveContext.Options.FieldInitializerScope))
-                               ec.Report.Error (236, l,
-                                       "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
-                                       name);
-                       else
-                               ec.Report.Error (120, l,
-                                       "An object reference is required to access non-static member `{0}'",
-                                       name);
-               }
-
                protected virtual void Error_TypeOrNamespaceNotFound (IMemberContext ec)
                {
                        if (ec.CurrentType != null) {
@@ -2345,18 +2201,6 @@ namespace Mono.CSharp {
                        NamespaceEntry.Error_NamespaceNotFound (loc, Name, ec.Compiler.Report);
                }
 
-               public bool IdenticalNameAndTypeName (IMemberContext mc, Expression resolved_to, Location loc)
-               {
-                       if (resolved_to == null || resolved_to.Type == null)
-                               return false;
-
-                       if (resolved_to.Type is ElementTypeSpec || resolved_to.Type is InternalType)
-                               return false;
-
-                       return resolved_to.Type.Name == Name &&
-                               (mc.LookupNamespaceOrType (Name, Arity, loc, /* ignore_cs0104 = */ true) != null);
-               }
-
                protected override Expression DoResolve (ResolveContext ec)
                {
                        return SimpleNameResolve (ec, null, false);
@@ -2367,50 +2211,41 @@ namespace Mono.CSharp {
                        return SimpleNameResolve (ec, right_side, false);
                }
 
-               public Expression DoResolve (ResolveContext ec, bool intermediate)
-               {
-                       return SimpleNameResolve (ec, null, intermediate);
-               }
-
-               static bool IsNestedChild (TypeSpec t, TypeSpec parent)
-               {
-                       while (parent != null) {
-                               if (TypeManager.IsNestedChildOf (t, parent))
-                                       return true;
-
-                               parent = parent.BaseType;
-                       }
-
-                       return false;
-               }
-
                public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
                {
                        int errors = ec.Compiler.Report.Errors;
                        FullNamedExpression fne = ec.LookupNamespaceOrType (Name, Arity, loc, /*ignore_cs0104=*/ false);
 
                        if (fne != null) {
-                               if (HasTypeArguments && fne.Type != null && TypeManager.IsGenericType (fne.Type)) {
-                                       GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc);
-                                       return ct.ResolveAsTypeStep (ec, false);
+                               if (fne.Type != null && Arity > 0) {
+                                       if (HasTypeArguments) {
+                                               GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc);
+                                               return ct.ResolveAsTypeStep (ec, false);
+                                       }
+
+                                       return new GenericOpenTypeExpr (fne.Type, loc);
                                }
 
-                               return fne;
+                               //
+                               // dynamic namespace is ignored when dynamic is allowed (does not apply to types)
+                               //
+                               if (!(fne is Namespace))
+                                       return fne;
                        }
 
-                       if (!HasTypeArguments && Name == "dynamic" &&
-                               RootContext.Version > LanguageVersion.V_3 &&
-                               RootContext.MetadataCompatibilityVersion > MetadataVersion.v2) {
-
-                               if (!PredefinedAttributes.Get.Dynamic.IsDefined) {
+                       if (Arity == 0 && Name == "dynamic" && RootContext.Version > LanguageVersion.V_3) {
+                               if (!ec.Compiler.PredefinedAttributes.Dynamic.IsDefined) {
                                        ec.Compiler.Report.Error (1980, Location,
                                                "Dynamic keyword requires `{0}' to be defined. Are you missing System.Core.dll assembly reference?",
-                                               PredefinedAttributes.Get.Dynamic.GetSignatureForError ());
+                                               ec.Compiler.PredefinedAttributes.Dynamic.GetSignatureForError ());
                                }
 
                                return new DynamicTypeExpr (loc);
                        }
 
+                       if (fne != null)
+                               return fne;
+
                        if (silent || errors != ec.Compiler.Report.Errors)
                                return null;
 
@@ -2418,211 +2253,154 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               Expression SimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate)
+               public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions)
                {
-                       Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
-
-                       if (e == null)
-                               return null;
+                       int lookup_arity = Arity;
+                       bool errorMode = false;
+                       Expression e;
+                       Block current_block = rc.CurrentBlock;
+                       INamedBlockVariable variable = null;
+                       bool variable_found = false;
 
-                       if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
-                               return e;
+                       while (true) {
+                               //
+                               // Stage 1: binding to local variables or parameters
+                               //
+                               // LAMESPEC: It should take invocableOnly into account but that would break csc compatibility
+                               //
+                               if (current_block != null && lookup_arity == 0) {
+                                       if (current_block.ParametersBlock.TopBlock.GetLocalName (Name, current_block.Original, ref variable)) {
+                                               if (!variable.IsDeclared) {
+                                                       // We found local name in accessible block but it's not
+                                                       // initialized yet, maybe the user wanted to bind to something else
+                                                       errorMode = true;
+                                                       variable_found = true;
+                                               } else {
+                                                       e = variable.CreateReferenceExpression (rc, loc);
+                                                       if (e != null) {
+                                                               if (Arity > 0)
+                                                                       Error_TypeArgumentsCannotBeUsed (rc.Report, "variable", Name, loc);
 
-                       return null;
-               }
+                                                               return e;
+                                                       }
+                                               }
+                                       }
+                               }
 
-               /// <remarks>
-               ///   7.5.2: Simple Names. 
-               ///
-               ///   Local Variables and Parameters are handled at
-               ///   parse time, so they never occur as SimpleNames.
-               ///
-               ///   The `intermediate' flag is used by MemberAccess only
-               ///   and it is used to inform us that it is ok for us to 
-               ///   avoid the static check, because MemberAccess might end
-               ///   up resolving the Name as a Type name and the access as
-               ///   a static type access.
-               ///
-               ///   ie: Type Type; .... { Type.GetType (""); }
-               ///
-               ///   Type is both an instance variable and a Type;  Type.GetType
-               ///   is the static method not an instance method of type.
-               /// </remarks>
-               Expression DoSimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate)
-               {
-                       Expression e = null;
+                               //
+                               // Stage 2: Lookup members if we are inside a type up to top level type for nested types
+                               //
+                               TypeSpec member_type = rc.CurrentType;
+                               TypeSpec current_type = member_type;
+                               for (; member_type != null; member_type = member_type.DeclaringType) {
+                                       var me = MemberLookup (errorMode ? null : rc, current_type, member_type, Name, lookup_arity, restrictions, loc) as MemberExpr;
+                                       if (me == null)
+                                               continue;
 
-                       //
-                       // Stage 1: Performed by the parser (binding to locals or parameters).
-                       //
-                       Block current_block = ec.CurrentBlock;
-                       if (current_block != null){
-                               LocalInfo vi = current_block.GetLocalInfo (Name);
-                               if (vi != null){
-                                       e = new LocalVariableReference (ec.CurrentBlock, Name, loc);
-
-                                       if (right_side != null) {
-                                               e = e.ResolveLValue (ec, right_side);
-                                       } else {
-                                               if (intermediate) {
-                                                       using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
-                                                               e = e.Resolve (ec, ResolveFlags.VariableOrValue);
+                                       if (errorMode) {
+                                               if (variable != null) {
+                                                       if (me is FieldExpr || me is ConstantExpr || me is EventExpr || me is PropertyExpr) {
+                                                               rc.Report.Error (844, loc,
+                                                                       "A local variable `{0}' cannot be used before it is declared. Consider renaming the local variable when it hides the member `{1}'",
+                                                                       Name, me.GetSignatureForError ());
+                                                       } else {
+                                                               break;
                                                        }
+                                               } else if (me is MethodGroupExpr) {
+                                                       // Leave it to overload resolution to report correct error
                                                } else {
-                                                       e = e.Resolve (ec, ResolveFlags.VariableOrValue);
+                                                       // TODO: rc.Report.SymbolRelatedToPreviousError ()
+                                                       ErrorIsInaccesible (rc, me.GetSignatureForError (), loc);
+                                               }
+                                       } else {
+                                               if (variable != null && (restrictions & MemberLookupRestrictions.InvocableOnly) == 0) {
+                                                       rc.Report.SymbolRelatedToPreviousError (variable.Location, Name);
+                                                       rc.Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", Name);
                                                }
-                                       }
-
-                                       if (HasTypeArguments && e != null)
-                                               e.Error_TypeArgumentsCannotBeUsed (ec.Report, loc, null, 0);
 
-                                       return e;
-                               }
+                                               //
+                                               // MemberLookup does not check accessors availability, this is actually needed for properties only
+                                               //
+                                               var pe = me as PropertyExpr;
+                                               if (pe != null) {
 
-                               e = current_block.Toplevel.GetParameterReference (Name, loc);
-                               if (e != null) {
-                                       if (right_side != null)
-                                               e = e.ResolveLValue (ec, right_side);
-                                       else
-                                               e = e.Resolve (ec);
+                                                       // Break as there is no other overload available anyway
+                                                       if ((restrictions & MemberLookupRestrictions.ReadAccess) != 0) {
+                                                               if (!pe.PropertyInfo.HasGet || !pe.PropertyInfo.Get.IsAccessible (current_type))
+                                                                       break;
 
-                                       if (HasTypeArguments && e != null)
-                                               e.Error_TypeArgumentsCannotBeUsed (ec.Report, loc, null, 0);
+                                                               pe.Getter = pe.PropertyInfo.Get;
+                                                       } else {
+                                                               if (!pe.PropertyInfo.HasSet || !pe.PropertyInfo.Set.IsAccessible (current_type))
+                                                                       break;
 
-                                       return e;
-                               }
-                       }
-                       
-                       //
-                       // Stage 2: Lookup members 
-                       //
-                       int arity = HasTypeArguments ? Arity : -1;
-//                     TypeSpec almost_matched_type = null;
-//                     IList<MemberSpec> almost_matched = null;
-                       for (TypeSpec lookup_ds = ec.CurrentType; lookup_ds != null; lookup_ds = lookup_ds.DeclaringType) {
-                               e = MemberLookup (ec.Compiler, ec.CurrentType, lookup_ds, Name, arity, BindingRestriction.NoOverrides, loc);
-                               if (e != null) {
-                                       PropertyExpr pe = e as PropertyExpr;
-                                       if (pe != null) {
-                                               // since TypeManager.MemberLookup doesn't know if we're doing a lvalue access or not,
-                                               // it doesn't know which accessor to check permissions against
-                                               if (pe.PropertyInfo.Kind == MemberKind.Property && pe.IsAccessibleFrom (ec.CurrentType, right_side != null))
-                                                       break;
-                                       } else if (e is EventExpr) {
-                                               if (((EventExpr) e).IsAccessibleFrom (ec.CurrentType))
-                                                       break;
-                                       } else if (HasTypeArguments && e is TypeExpression) {
-                                               e = new GenericTypeExpr (e.Type, targs, loc).ResolveAsTypeStep (ec, false);
-                                               break;
-                                       } else {
-                                               break;
+                                                               pe.Setter = pe.PropertyInfo.Set;
+                                                       }
+                                               }
                                        }
-                                       e = null;
-                               }
-/*
-                               if (almost_matched == null && almost_matched_members.Count > 0) {
-                                       almost_matched_type = lookup_ds;
-                                       almost_matched = new List<MemberSpec>(almost_matched_members);
-                               }
-*/ 
-                       }
 
-                       if (e == null) {
-/*
-                               if (almost_matched == null && almost_matched_members.Count > 0) {
-                                       almost_matched_type = ec.CurrentType;
-                                       almost_matched = new List<MemberSpec> (almost_matched_members);
-                               }
-*/ 
-                               e = ResolveAsTypeStep (ec, true);
-                       }
+                                       // TODO: It's used by EventExpr -> FieldExpr transformation only
+                                       // TODO: Should go to MemberAccess
+                                       me = me.ResolveMemberAccess (rc, null, null);
 
-                       if (e == null) {
-                               if (current_block != null) {
-                                       IKnownVariable ikv = current_block.Explicit.GetKnownVariable (Name);
-                                       if (ikv != null) {
-                                               LocalInfo li = ikv as LocalInfo;
-                                               // Supress CS0219 warning
-                                               if (li != null)
-                                                       li.Used = true;
-
-                                               Error_VariableIsUsedBeforeItIsDeclared (ec.Report, Name);
-                                               return null;
+                                       if (Arity > 0) {
+                                               targs.Resolve (rc);
+                                               me.SetTypeArguments (rc, targs);
                                        }
-                               }
 
-                               if (RootContext.EvalMode){
-                                       FieldInfo fi = Evaluator.LookupField (Name);
-                                       if (fi != null)
-                                               return new FieldExpr (Import.CreateField (fi, null), loc).Resolve (ec);
+                                       return me;
                                }
-/*
-                               if (almost_matched != null)
-                                       almost_matched_members = almost_matched;
-                               if (almost_matched_type == null)
-                                       almost_matched_type = ec.CurrentType;
-*/
-                               string type_name = ec.MemberContext.CurrentType == null ? null : ec.MemberContext.CurrentType.Name;
-                               return Error_MemberLookupFailed (ec, ec.CurrentType, null, ec.CurrentType, Name, arity,
-                                       type_name, MemberKind.All, BindingRestriction.AccessibleOnly);
-                       }
 
-                       if (e is MemberExpr) {
-                               MemberExpr me = (MemberExpr) e;
+                               //
+                               // Stage 3: Lookup nested types, namespaces and type parameters in the context
+                               //
+                               if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0 && !variable_found) {
+                                       e = ResolveAsTypeStep (rc, lookup_arity == 0 || !errorMode);
+                                       if (e != null)
+                                               return e;
+                               }
 
-                               Expression left;
-                               if (me.IsInstance) {
-                                       if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer | ResolveContext.Options.ConstantScope)) {
-                                               //
-                                               // Note that an MemberExpr can be both IsInstance and IsStatic.
-                                               // An unresolved MethodGroupExpr can contain both kinds of methods
-                                               // and each predicate is true if the MethodGroupExpr contains
-                                               // at least one of that kind of method.
-                                               //
-/*
-                                               if (!me.IsStatic &&
-                                                   (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
-                                                       Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
-                                                       return null;
-                                               }
-*/
-                                               //
-                                               // Pass the buck to MemberAccess and Invocation.
-                                               //
-                                               left = EmptyExpression.Null;
+                               if (errorMode) {
+                                       if (variable_found) {
+                                               rc.Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", Name);
                                        } else {
-                                               left = ec.GetThis (loc);
+                                               rc.Report.Error (103, loc, "The name `{0}' does not exist in the current context", Name);
                                        }
-                               } else {
-                                       left = new TypeExpression (ec.CurrentType, loc);
-                               }
 
-                               me = me.ResolveMemberAccess (ec, left, loc, null);
-                               if (me == null)
                                        return null;
+                               }
 
-                               if (HasTypeArguments) {
-                                       if (!targs.Resolve (ec))
-                                               return null;
-
-                                       me.SetTypeArguments (ec, targs);
+                               if (RootContext.EvalMode) {
+                                       var fi = Evaluator.LookupField (Name);
+                                       if (fi != null)
+                                               return new FieldExpr (fi.Item1, loc);
                                }
 
-                               if (!me.IsStatic && (me.InstanceExpression != null && me.InstanceExpression != EmptyExpression.Null) &&
-                                   TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
-                                   me.InstanceExpression.Type != me.DeclaringType &&
-                                   !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
-                                   (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
-                                       ec.Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
-                                               TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type));
-                                       return null;
+                               lookup_arity = 0;
+                               restrictions &= ~MemberLookupRestrictions.InvocableOnly;
+                               errorMode = true;
+                       }
+               }
+               
+               Expression SimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate)
+               {
+                       Expression e = LookupNameExpression (ec, right_side == null ? MemberLookupRestrictions.ReadAccess : MemberLookupRestrictions.None);
+
+                       if (e == null)
+                               return null;
+
+                       if (right_side != null) {
+                               if (e is TypeExpr) {
+                                   e.Error_UnexpectedKind (ec, ResolveFlags.VariableOrValue, loc);
+                                   return null;
                                }
 
-                               return (right_side != null)
-                                       ? me.DoResolveLValue (ec, right_side)
-                                       : me.Resolve (ec);
+                               e = e.ResolveLValue (ec, right_side);
+                       } else {
+                               e = e.Resolve (ec);
                        }
 
+                       //if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
                        return e;
                }
        }
@@ -2723,31 +2501,17 @@ namespace Mono.CSharp {
                }
        }
 
-       //
-       // Used to create types from a fully qualified name.  These are just used
-       // by the parser to setup the core types.
-       //
-       public sealed class TypeLookupExpression : TypeExpr {
-               
-               public TypeLookupExpression (TypeSpec type)
-               {
-                       eclass = ExprClass.Type;
-                       this.type = type;
-               }
-
-               protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec)
-               {
-                       return this;
-               }
-       }
-
        /// <summary>
        ///   This class denotes an expression which evaluates to a member
        ///   of a struct or a class.
        /// </summary>
        public abstract class MemberExpr : Expression
        {
-               protected bool is_base;
+               //
+               // An instance expression associated with this member, if it's a
+               // non-static member
+               //
+               public Expression InstanceExpression;
 
                /// <summary>
                ///   The name of this member.
@@ -2760,8 +2524,7 @@ namespace Mono.CSharp {
                // When base.member is used
                //
                public bool IsBase {
-                       get { return is_base; }
-                       set { is_base = value; }
+                       get { return InstanceExpression is BaseThis; }
                }
 
                /// <summary>
@@ -2778,291 +2541,750 @@ namespace Mono.CSharp {
                        get;
                }
 
-               /// <summary>
-               ///   The type which declares this member.
-               /// </summary>
-               public abstract TypeSpec DeclaringType {
+               // TODO: Not needed
+               protected abstract TypeSpec DeclaringType {
                        get;
                }
 
-               /// <summary>
-               ///   The instance expression associated with this member, if it's a
-               ///   non-static member.
-               /// </summary>
-               public Expression InstanceExpression;
+               //
+               // Converts best base candidate for virtual method starting from QueriedBaseType
+               //
+               protected MethodSpec CandidateToBaseOverride (ResolveContext rc, MethodSpec method)
+               {
+                       //
+                       // Only when base.member is used and method is virtual
+                       //
+                       if (!IsBase)
+                               return method;
+
+                       //
+                       // Overload resulution works on virtual or non-virtual members only (no overrides). That
+                       // means for base.member access we have to find the closest match after we found best candidate
+                       //
+                       if ((method.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.STATIC)) != Modifiers.STATIC) {
+                               //
+                               // The method could already be what we are looking for
+                               //
+                               TypeSpec[] targs = null;
+                               if (method.DeclaringType != InstanceExpression.Type) {
+                                       var base_override = MemberCache.FindMember (InstanceExpression.Type, new MemberFilter (method), BindingRestriction.InstanceOnly) as MethodSpec;
+                                       if (base_override != null && base_override.DeclaringType != method.DeclaringType) {
+                                               if (base_override.IsGeneric)
+                                                       targs = method.TypeArguments;
+
+                                               method = base_override;
+                                       }
+                               }
+
+                               // TODO: For now we do it for any hoisted call even if it's needed for
+                               // hoisted stories only but that requires a new expression wrapper
+                               if (rc.CurrentAnonymousMethod != null) {
+                                       if (targs == null && method.IsGeneric) {
+                                               targs = method.TypeArguments;
+                                               method = method.GetGenericMethodDefinition ();
+                                       }
+
+                                       if (method.Parameters.HasArglist)
+                                               throw new NotImplementedException ("__arglist base call proxy");
+
+                                       method = rc.CurrentMemberDefinition.Parent.PartialContainer.CreateHoistedBaseCallProxy (rc, method);
+
+                                       // Ideally this should apply to any proxy rewrite but in the case of unary mutators on
+                                       // get/set member expressions second call would fail to proxy because left expression
+                                       // would be of 'this' and not 'base'
+                                       if (rc.CurrentType.IsStruct)
+                                               InstanceExpression = rc.GetThis (loc);
+                               }
+
+                               if (targs != null)
+                                       method = method.MakeGenericMethod (targs);
+                       }
+
+                       //
+                       // Only base will allow this invocation to happen.
+                       //
+                       if (method.IsAbstract) {
+                               Error_CannotCallAbstractBase (rc, method.GetSignatureForError ());
+                       }
 
-               public static void error176 (ResolveContext ec, Location loc, string name)
+                       return method;
+               }
+
+               protected void CheckProtectedMemberAccess<T> (ResolveContext rc, T member) where T : MemberSpec
                {
-                       ec.Report.Error (176, loc, "Static member `{0}' cannot be accessed " +
-                                     "with an instance reference, qualify it with a type name instead", name);
+                       if (InstanceExpression == null)
+                               return;
+
+                       if ((member.Modifiers & Modifiers.AccessibilityMask) == Modifiers.PROTECTED && !(InstanceExpression is This)) {
+                               var ct = rc.CurrentType;
+                               var expr_type = InstanceExpression.Type;
+                               if (ct != expr_type) {
+                                       expr_type = expr_type.GetDefinition ();
+                                       if (ct != expr_type && !IsSameOrBaseQualifier (ct, expr_type)) {
+                                               rc.Report.SymbolRelatedToPreviousError (member);
+                                               rc.Report.Error (1540, loc,
+                                                       "Cannot access protected member `{0}' via a qualifier of type `{1}'. The qualifier must be of type `{2}' or derived from it",
+                                                       member.GetSignatureForError (), expr_type.GetSignatureForError (), ct.GetSignatureForError ());
+                                       }
+                               }
+                       }
                }
 
-               public static void Error_BaseAccessInExpressionTree (ResolveContext ec, Location loc)
+               static bool IsSameOrBaseQualifier (TypeSpec type, TypeSpec qtype)
                {
-                       ec.Report.Error (831, loc, "An expression tree may not contain a base access");
+                       do {
+                               type = type.GetDefinition ();
+
+                               if (type == qtype || TypeManager.IsFamilyAccessible (qtype, type))
+                                       return true;
+
+                               type = type.DeclaringType;
+                       } while (type != null);
+
+                       return false;
                }
 
-               public virtual MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
-                                                              SimpleName original)
+               protected void DoBestMemberChecks<T> (ResolveContext rc, T member) where T : MemberSpec, IInterfaceMemberSpec
                {
-                       //
-                       // Precondition:
-                       //   original == null || original.Resolve (...) ==> left
-                       //
+                       if (InstanceExpression != null) {
+                               InstanceExpression = InstanceExpression.Resolve (rc);
+                               CheckProtectedMemberAccess (rc, member);
+                       }
 
-                       if (left is TypeExpr) {
-                               left = ((TypeExpr) left).ResolveAsTypeTerminal (ec, false);
-                               if (left == null)
-                                       return null;
+                       if (member.MemberType.IsPointer && !rc.IsUnsafe) {
+                               UnsafeError (rc, loc);
+                       }
+
+                       if (!rc.IsObsolete) {
+                               ObsoleteAttribute oa = member.GetAttributeObsolete ();
+                               if (oa != null)
+                                       AttributeTester.Report_ObsoleteMessage (oa, member.GetSignatureForError (), loc, rc.Report);
+                       }
+
+                       if (!(member is FieldSpec))
+                               member.MemberDefinition.SetIsUsed ();
+               }
+
+               protected virtual void Error_CannotCallAbstractBase (ResolveContext rc, string name)
+               {
+                       rc.Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
+               }
+
+               //
+               // Implements identicial simple name and type-name
+               //
+               public Expression ProbeIdenticalTypeName (ResolveContext rc, Expression left, SimpleName name)
+               {
+                       var t = left.Type;
+                       if (t.Kind == MemberKind.InternalCompilerType || t is ElementTypeSpec || t.Arity > 0)
+                               return left;
+
+                       // 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
+                       // a constant, field, property, local variable, or parameter with the same type as the meaning of E as a type-name
+
+                       if (left is MemberExpr || left is VariableReference) {
+                               rc.Report.DisableReporting ();
+                               Expression identical_type = rc.LookupNamespaceOrType (name.Name, 0, loc, true) as TypeExpr;
+                               rc.Report.EnableReporting ();
+                               if (identical_type != null && identical_type.Type == left.Type)
+                                       return identical_type;
+                       }
+
+                       return left;
+               }
+
+               public bool ResolveInstanceExpression (ResolveContext rc)
+               {
+                       if (IsStatic) {
+                               if (InstanceExpression != null) {
+                                       if (InstanceExpression is TypeExpr) {
+                                               ObsoleteAttribute oa = InstanceExpression.Type.GetAttributeObsolete ();
+                                               if (oa != null && !rc.IsObsolete) {
+                                                       AttributeTester.Report_ObsoleteMessage (oa, InstanceExpression.GetSignatureForError (), loc, rc.Report);
+                                               }
+                                       } else {
+                                               var runtime_expr = InstanceExpression as RuntimeValueExpression;
+                                               if (runtime_expr == null || !runtime_expr.IsSuggestionOnly) {
+                                                       rc.Report.Error (176, loc,
+                                                               "Static member `{0}' cannot be accessed with an instance reference, qualify it with a type name instead",
+                                                               GetSignatureForError ());
+                                               }
+                                       }
 
-                               // TODO: Same problem as in class.cs, TypeTerminal does not
-                               // always do all necessary checks
-                               ObsoleteAttribute oa = left.Type.GetAttributeObsolete ();
-                               if (oa != null && !ec.IsObsolete) {
-                                       AttributeTester.Report_ObsoleteMessage (oa, left.GetSignatureForError (), loc, ec.Report);
+                                       InstanceExpression = null;
                                }
 
-//                             GenericTypeExpr ct = left as GenericTypeExpr;
-//                             if (ct != null && !ct.CheckConstraints (ec))
-//                                     return null;
-                               //
+                               return false;
+                       }
 
-                               if (!IsStatic) {
-                                       SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
-                                       return null;
+                       if (InstanceExpression == null || InstanceExpression is TypeExpr) {
+                               if (InstanceExpression != null || !This.IsThisAvailable (rc, true)) {
+                                       if (rc.HasSet (ResolveContext.Options.FieldInitializerScope))
+                                               rc.Report.Error (236, loc,
+                                                       "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
+                                                       GetSignatureForError ());
+                                       else
+                                               rc.Report.Error (120, loc,
+                                                       "An object reference is required to access non-static member `{0}'",
+                                                       GetSignatureForError ());
+
+                                       return false;
                                }
 
-                               return this;
+                               if (!TypeManager.IsFamilyAccessible (rc.CurrentType, DeclaringType)) {
+                                       rc.Report.Error (38, loc,
+                                               "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
+                                               DeclaringType.GetSignatureForError (), rc.CurrentType.GetSignatureForError ());
+                               }
+
+                               InstanceExpression = rc.GetThis (loc);
+                               return false;
                        }
-                               
-                       if (!IsInstance) {
-                               if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
-                                       return this;
 
-                               return ResolveExtensionMemberAccess (ec, left);
+                       var me = InstanceExpression as MemberExpr;
+                       if (me != null) {
+                               me.ResolveInstanceExpression (rc);
+
+                               var fe = me as FieldExpr;
+                               if (fe != null && fe.IsMarshalByRefAccess ()) {
+                                       rc.Report.SymbolRelatedToPreviousError (me.DeclaringType);
+                                       rc.Report.Warning (1690, 1, loc,
+                                               "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
+                                               me.GetSignatureForError ());
+                               }
                        }
 
-                       InstanceExpression = left;
-                       return this;
+                       return true;
                }
 
-               protected virtual MemberExpr ResolveExtensionMemberAccess (ResolveContext ec, Expression left)
+               public virtual MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
                {
-                       error176 (ec, loc, GetSignatureForError ());
+                       if (left != null && left.IsNull && TypeManager.IsReferenceType (left.Type)) {
+                               ec.Report.Warning (1720, 1, left.Location,
+                                       "Expression will always cause a `{0}'", "System.NullReferenceException");
+                       }
+
+                       InstanceExpression = left;
                        return this;
                }
 
                protected void EmitInstance (EmitContext ec, bool prepare_for_load)
                {
-                       if (IsStatic)
-                               return;
-
-                       if (InstanceExpression == EmptyExpression.Null) {
-                               // FIXME: This should not be here at all
-                               SimpleName.Error_ObjectRefRequired (new ResolveContext (ec.MemberContext), loc, GetSignatureForError ());
-                               return;
-                       }
-
-                       if (TypeManager.IsValueType (InstanceExpression.Type)) {
+                       TypeSpec instance_type = InstanceExpression.Type;
+                       if (TypeManager.IsValueType (instance_type)) {
                                if (InstanceExpression is IMemoryLocation) {
                                        ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
                                } else {
-                                       LocalTemporary t = new LocalTemporary (InstanceExpression.Type);
+                                       LocalTemporary t = new LocalTemporary (instance_type);
                                        InstanceExpression.Emit (ec);
                                        t.Store (ec);
                                        t.AddressOf (ec, AddressOp.Store);
                                }
-                       } else
-                               InstanceExpression.Emit (ec);
+                       } else {
+                               InstanceExpression.Emit (ec);
+
+                               // Only to make verifier happy
+                               if (instance_type.IsGenericParameter && !(InstanceExpression is This) && TypeManager.IsReferenceType (instance_type))
+                                       ec.Emit (OpCodes.Box, instance_type);
+                       }
+
+                       if (prepare_for_load)
+                               ec.Emit (OpCodes.Dup);
+               }
+
+               public abstract void SetTypeArguments (ResolveContext ec, TypeArguments ta);
+       }
+
+       // 
+       // Represents a group of extension method candidates for whole namespace
+       // 
+       class ExtensionMethodGroupExpr : MethodGroupExpr, OverloadResolver.IErrorHandler
+       {
+               NamespaceEntry namespace_entry;
+               public readonly Expression ExtensionExpression;
+
+               public ExtensionMethodGroupExpr (IList<MethodSpec> list, NamespaceEntry n, Expression extensionExpr, Location l)
+                       : base (list.Cast<MemberSpec>().ToList (), extensionExpr.Type, l)
+               {
+                       this.namespace_entry = n;
+                       this.ExtensionExpression = extensionExpr;
+               }
+
+               public override bool IsStatic {
+                       get { return true; }
+               }
+
+               public override IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
+               {
+                       if (namespace_entry == null)
+                               return null;
+
+                       //
+                       // For extension methodgroup we are not looking for base members but parent
+                       // namespace extension methods
+                       //
+                       int arity = type_arguments == null ? 0 : type_arguments.Count;
+                       var found = namespace_entry.LookupExtensionMethod (DeclaringType, Name, arity, ref namespace_entry);
+                       if (found == null)
+                               return null;
+
+                       return found.Cast<MemberSpec> ().ToList ();
+               }
+
+               public override MethodGroupExpr LookupExtensionMethod (ResolveContext rc)
+               {
+                       // We are already here
+                       return null;
+               }
+
+               public override MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments arguments, OverloadResolver.IErrorHandler ehandler, OverloadResolver.Restrictions restr)
+               {
+                       if (arguments == null)
+                               arguments = new Arguments (1);
+
+                       arguments.Insert (0, new Argument (ExtensionExpression, Argument.AType.ExtensionType));
+                       var res = base.OverloadResolve (ec, ref arguments, ehandler ?? this, restr);
+
+                       // Store resolved argument and restore original arguments
+                       if (res == null) {
+                               // Clean-up modified arguments for error reporting
+                               arguments.RemoveAt (0);
+                               return null;
+                       }
+
+                       var me = ExtensionExpression as MemberExpr;
+                       if (me != null)
+                               me.ResolveInstanceExpression (ec);
+
+                       InstanceExpression = null;
+                       return this;
+               }
+
+               #region IErrorHandler Members
+
+               bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext rc, MemberSpec best, MemberSpec ambiguous)
+               {
+                       return false;
+               }
+
+               bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index)
+               {
+                       rc.Report.SymbolRelatedToPreviousError (best);
+                       rc.Report.Error (1928, loc,
+                               "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' has some invalid arguments",
+                               queried_type.GetSignatureForError (), Name, best.GetSignatureForError ());
+
+                       if (index == 0) {
+                               rc.Report.Error (1929, loc,
+                                       "Extension method instance type `{0}' cannot be converted to `{1}'",
+                                       arg.Type.GetSignatureForError (), ((MethodSpec)best).Parameters.ExtensionMethodType.GetSignatureForError ());
+                       }
+
+                       return true;
+               }
+
+               bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best)
+               {
+                       return false;
+               }
+
+               bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best)
+               {
+                       return false;
+               }
+
+               #endregion
+       }
+
+       /// <summary>
+       ///   MethodGroupExpr represents a group of method candidates which
+       ///   can be resolved to the best method overload
+       /// </summary>
+       public class MethodGroupExpr : MemberExpr, OverloadResolver.IBaseMembersProvider
+       {
+               protected IList<MemberSpec> Methods;
+               MethodSpec best_candidate;
+               protected TypeArguments type_arguments;
+
+               SimpleName simple_name;
+               protected TypeSpec queried_type;
+
+               public MethodGroupExpr (IList<MemberSpec> mi, TypeSpec type, Location loc)
+               {
+                       Methods = mi;
+                       this.loc = loc;
+                       this.type = InternalType.MethodGroup;
+
+                       eclass = ExprClass.MethodGroup;
+                       queried_type = type;
+               }
+
+               public MethodGroupExpr (MethodSpec m, TypeSpec type, Location loc)
+                       : this (new MemberSpec[] { m }, type, loc)
+               {
+               }
+
+               #region Properties
+
+               public MethodSpec BestCandidate {
+                       get {
+                               return best_candidate;
+                       }
+               }
+
+               protected override TypeSpec DeclaringType {
+                       get {
+                               return queried_type;
+                       }
+               }
+
+               public override bool IsInstance {
+                       get {
+                               if (best_candidate != null)
+                                       return !best_candidate.IsStatic;
+
+                               return false;
+                       }
+               }
+
+               public override bool IsStatic {
+                       get {
+                               if (best_candidate != null)
+                                       return best_candidate.IsStatic;
+
+                               return false;
+                       }
+               }
+
+               public override string Name {
+                       get {
+                               if (best_candidate != null)
+                                       return best_candidate.Name;
+
+                               // TODO: throw ?
+                               return Methods.First ().Name;
+                       }
+               }
+
+               #endregion
+
+               //
+               // When best candidate is already know this factory can be used
+               // to avoid expensive overload resolution to be called
+               //
+               // NOTE: InstanceExpression has to be set manually
+               //
+               public static MethodGroupExpr CreatePredefined (MethodSpec best, TypeSpec queriedType, Location loc)
+               {
+                       return new MethodGroupExpr (best, queriedType, loc) {
+                               best_candidate = best
+                       };
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       if (best_candidate != null)
+                               return best_candidate.GetSignatureForError ();
+
+                       return Methods.First ().GetSignatureForError ();
+               }
+
+               public override Expression CreateExpressionTree (ResolveContext ec)
+               {
+                       if (best_candidate == null) {
+                               ec.Report.Error (1953, loc, "An expression tree cannot contain an expression with method group");
+                               return null;
+                       }
+
+                       if (best_candidate.IsConditionallyExcluded (loc))
+                               ec.Report.Error (765, loc,
+                                       "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
+                       
+                       return new TypeOfMethod (best_candidate, loc);
+               }
+               
+               protected override Expression DoResolve (ResolveContext ec)
+               {
+                       this.eclass = ExprClass.MethodGroup;
+
+                       if (InstanceExpression != null) {
+                               InstanceExpression = InstanceExpression.Resolve (ec);
+                               if (InstanceExpression == null)
+                                       return null;
+                       }
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new NotSupportedException ();
+               }
+               
+               public void EmitCall (EmitContext ec, Arguments arguments)
+               {
+                       Invocation.EmitCall (ec, InstanceExpression, best_candidate, arguments, loc);                   
+               }
+
+               public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
+               {
+                       ec.Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method",
+                               Name, TypeManager.CSharpName (target));
+               }
+
+               public static bool IsExtensionMethodArgument (Expression expr)
+               {
+                       //
+                       // LAMESPEC: No details about which expressions are not allowed
+                       //
+                       return !(expr is TypeExpr) && !(expr is BaseThis);
+               }
+
+               /// <summary>
+               ///   Find the Applicable Function Members (7.4.2.1)
+               ///
+               ///   me: Method Group expression with the members to select.
+               ///       it might contain constructors or methods (or anything
+               ///       that maps to a method).
+               ///
+               ///   Arguments: ArrayList containing resolved Argument objects.
+               ///
+               ///   loc: The location if we want an error to be reported, or a Null
+               ///        location for "probing" purposes.
+               ///
+               ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
+               ///            that is the best match of me on Arguments.
+               ///
+               /// </summary>
+               public virtual MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments args, OverloadResolver.IErrorHandler cerrors, OverloadResolver.Restrictions restr)
+               {
+                       // TODO: causes issues with probing mode, remove explicit Kind check
+                       if (best_candidate != null && best_candidate.Kind == MemberKind.Destructor)
+                               return this;
+
+                       var r = new OverloadResolver (Methods, type_arguments, restr, loc);
+                       if ((restr & OverloadResolver.Restrictions.NoBaseMembers) == 0) {
+                               r.BaseMembersProvider = this;
+                       }
+
+                       if (cerrors != null)
+                               r.CustomErrors = cerrors;
+
+                       // TODO: When in probing mode do IsApplicable only and when called again do VerifyArguments for full error reporting
+                       best_candidate = r.ResolveMember<MethodSpec> (ec, ref args);
+                       if (best_candidate == null)
+                               return r.BestCandidateIsDynamic ? this : null;
+
+                       // Overload resolver had to create a new method group, all checks bellow have already been executed
+                       if (r.BestCandidateNewMethodGroup != null)
+                               return r.BestCandidateNewMethodGroup;
+
+                       if (best_candidate.Kind == MemberKind.Method) {
+                               if (InstanceExpression != null) {
+                                       if (best_candidate.IsExtensionMethod && args[0].Expr == InstanceExpression) {
+                                               InstanceExpression = null;
+                                       } else {
+                                               if (best_candidate.IsStatic && simple_name != null) {
+                                                       InstanceExpression = ProbeIdenticalTypeName (ec, InstanceExpression, simple_name);
+                                               }
+
+                                               InstanceExpression.Resolve (ec);
+                                       }
+                               }
 
-                       if (prepare_for_load)
-                               ec.Emit (OpCodes.Dup);
-               }
+                               ResolveInstanceExpression (ec);
+                               if (InstanceExpression != null)
+                                       CheckProtectedMemberAccess (ec, best_candidate);
+                       }
 
-               public virtual void SetTypeArguments (ResolveContext ec, TypeArguments ta)
-               {
-                       // TODO: need to get correct member type
-                       ec.Report.Error (307, loc, "The property `{0}' cannot be used with type arguments",
-                               GetSignatureForError ());
+                       best_candidate = CandidateToBaseOverride (ec, best_candidate);
+                       return this;
                }
-       }
-
-       /// 
-       /// Represents group of extension methods
-       /// 
-       public class ExtensionMethodGroupExpr : MethodGroupExpr
-       {
-               readonly NamespaceEntry namespace_entry;
-               public Expression ExtensionExpression;
 
-               public ExtensionMethodGroupExpr (List<MethodSpec> list, NamespaceEntry n, TypeSpec extensionType, Location l)
-                       : base (list.Cast<MemberSpec>().ToList (), extensionType, l)
+               public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
                {
-                       this.namespace_entry = n;
+                       simple_name = original;
+                       return base.ResolveMemberAccess (ec, left, original);
                }
 
-               public override bool IsStatic {
-                       get { return true; }
+               public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
+               {
+                       type_arguments = ta;
                }
 
-               public bool IsTopLevel {
-                       get { return namespace_entry == null; }
-               }
+               #region IBaseMembersProvider Members
 
-               public override MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments arguments, bool may_fail, Location loc)
+               public virtual IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
                {
-                       if (arguments == null)
-                               arguments = new Arguments (1);
-
-                       arguments.Insert (0, new Argument (ExtensionExpression));
-                       MethodGroupExpr mg = ResolveOverloadExtensions (ec, ref arguments, namespace_entry, loc);
-
-                       // Store resolved argument and restore original arguments
-                       if (mg == null)
-                               arguments.RemoveAt (0); // Clean-up modified arguments for error reporting
-
-                       return mg;
+                       return baseType == null ? null : MemberCache.FindMembers (baseType, Methods [0].Name, false);
                }
 
-               MethodGroupExpr ResolveOverloadExtensions (ResolveContext ec, ref Arguments arguments, NamespaceEntry ns, Location loc)
+               //
+               // Extension methods lookup after ordinary methods candidates failed to apply
+               //
+               public virtual MethodGroupExpr LookupExtensionMethod (ResolveContext rc)
                {
-                       // Use normal resolve rules
-                       MethodGroupExpr mg = base.OverloadResolve (ec, ref arguments, ns != null, loc);
-                       if (mg != null)
-                               return mg;
+                       if (InstanceExpression == null)
+                               return null;
 
-                       if (ns == null)
+                       InstanceExpression = InstanceExpression.Resolve (rc);
+                       if (!IsExtensionMethodArgument (InstanceExpression))
                                return null;
 
-                       // Search continues
-                       int arity = type_arguments == null ? -1 : type_arguments.Count;
-                       ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, Name, arity, loc);
-                       if (e == null)
-                               return base.OverloadResolve (ec, ref arguments, false, loc);
+                       int arity = type_arguments == null ? 0 : type_arguments.Count;
+                       NamespaceEntry methods_scope = null;
+                       var methods = rc.LookupExtensionMethod (InstanceExpression.Type, Methods[0].Name, arity, ref methods_scope);
+                       if (methods == null)
+                               return null;
 
-                       e.ExtensionExpression = ExtensionExpression;
-                       e.SetTypeArguments (ec, type_arguments);                        
-                       return e.ResolveOverloadExtensions (ec, ref arguments, e.namespace_entry, loc);
-               }               
+                       var emg = new ExtensionMethodGroupExpr (methods, methods_scope, InstanceExpression, loc);
+                       emg.SetTypeArguments (rc, type_arguments);
+                       return emg;
+               }
+
+               #endregion
        }
 
-       /// <summary>
-       ///   MethodGroupExpr represents a group of method candidates which
-       ///   can be resolved to the best method overload
-       /// </summary>
-       public class MethodGroupExpr : MemberExpr
+       public struct OverloadResolver
        {
-               public interface IErrorHandler
+               [Flags]
+               public enum Restrictions
                {
-                       bool AmbiguousCall (ResolveContext ec, MethodSpec ambiguous);
-                       bool NoExactMatch (ResolveContext ec, MethodSpec method);
+                       None = 0,
+                       DelegateInvoke = 1,
+                       ProbingOnly     = 1 << 1,
+                       CovariantDelegate = 1 << 2,
+                       NoBaseMembers = 1 << 3,
+                       BaseMembersIncluded = 1 << 4
                }
 
-               public IErrorHandler CustomErrorHandler;
-               public IList<MemberSpec> Methods;
-               MethodSpec best_candidate;
-               // TODO: make private
-               public TypeArguments type_arguments;
-               bool identical_type_name;
-               bool has_inaccessible_candidates_only;
-               TypeSpec delegate_type;
-               TypeSpec queried_type;
-
-               public MethodGroupExpr (IList<MemberSpec> mi, TypeSpec type, Location l)
-                       : this (type, l)
+               public interface IBaseMembersProvider
                {
-                       Methods = mi;
+                       IList<MemberSpec> GetBaseMembers (TypeSpec baseType);
+                       MethodGroupExpr LookupExtensionMethod (ResolveContext rc);
                }
 
-               public MethodGroupExpr (MethodSpec m, TypeSpec type, Location l)
-                       : this (type, l)
+               public interface IErrorHandler
                {
-                       Methods = new List<MemberSpec> (1) { m };
+                       bool AmbiguousCandidates (ResolveContext rc, MemberSpec best, MemberSpec ambiguous);
+                       bool ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument a, int index);
+                       bool NoArgumentMatch (ResolveContext rc, MemberSpec best);
+                       bool TypeInferenceFailed (ResolveContext rc, MemberSpec best);
                }
 
-               public MethodGroupExpr (IList<MemberSpec> mi, TypeSpec type, Location l, bool inacessibleCandidatesOnly)
-                       : this (mi, type, l)
-               {
-                       has_inaccessible_candidates_only = inacessibleCandidatesOnly;
-               }
-               
-               protected MethodGroupExpr (TypeSpec type, Location loc)
+               sealed class NoBaseMembers : IBaseMembersProvider
                {
-                       this.loc = loc;
-                       eclass = ExprClass.MethodGroup;
-                       this.type = InternalType.MethodGroup;
-                       queried_type = type;
-               }
+                       public static readonly IBaseMembersProvider Instance = new NoBaseMembers ();
 
-               public override TypeSpec DeclaringType {
-                       get {
-                               return queried_type;
+                       public IList<MemberSpec> GetBaseMembers (TypeSpec baseType)
+                       {
+                               return null;
                        }
-               }
 
-               public MethodSpec BestCandidate {
-                       get {
-                               return best_candidate;
+                       public MethodGroupExpr LookupExtensionMethod (ResolveContext rc)
+                       {
+                               return null;
                        }
                }
 
-               public TypeSpec DelegateType {
-                       set {
-                               delegate_type = value;
+               struct AmbiguousCandidate
+               {
+                       public readonly MemberSpec Member;
+                       public readonly bool Expanded;
+
+                       public AmbiguousCandidate (MemberSpec member, bool expanded)
+                       {
+                               Member = member;
+                               Expanded = expanded;
                        }
                }
 
-               public bool IdenticalTypeName {
-                       get {
-                               return identical_type_name;
-                       }
+               Location loc;
+               IList<MemberSpec> members;
+               TypeArguments type_arguments;
+               IBaseMembersProvider base_provider;
+               IErrorHandler custom_errors;
+               Restrictions restrictions;
+               MethodGroupExpr best_candidate_extension_group;
+
+               SessionReportPrinter lambda_conv_msgs;
+               ReportPrinter prev_recorder;
+
+               public OverloadResolver (IList<MemberSpec> members, Restrictions restrictions, Location loc)
+                       : this (members, null, restrictions, loc)
+               {
                }
 
-               public override string GetSignatureForError ()
+               public OverloadResolver (IList<MemberSpec> members, TypeArguments targs, Restrictions restrictions, Location loc)
+                       : this ()
                {
-                       if (best_candidate != null)
-                               return best_candidate.GetSignatureForError ();
+                       if (members == null || members.Count == 0)
+                               throw new ArgumentException ("empty members set");
 
-                       return Methods.First ().GetSignatureForError ();
+                       this.members = members;
+                       this.loc = loc;
+                       type_arguments = targs;
+                       this.restrictions = restrictions;
+                       if (IsDelegateInvoke)
+                               this.restrictions |= Restrictions.NoBaseMembers;
+
+                       base_provider = NoBaseMembers.Instance;
                }
 
-               public override string Name {
+               #region Properties
+
+               public IBaseMembersProvider BaseMembersProvider {
                        get {
-                               return Methods.First ().Name;
+                               return base_provider;
+                       }
+                       set {
+                               base_provider = value;
                        }
                }
 
-               public override bool IsInstance {
-                       get {
-                               if (best_candidate != null)
-                                       return !best_candidate.IsStatic;
+               public bool BestCandidateIsDynamic { get; set; }
 
-                               foreach (var mb in Methods)
-                                       if (!mb.IsStatic)
-                                               return true;
+               //
+               // Best candidate was found in newly created MethodGroupExpr, used by extension methods
+               //
+               public MethodGroupExpr BestCandidateNewMethodGroup {
+                       get {
+                               return best_candidate_extension_group;
+                       }
+               }
 
-                               return false;
+               public IErrorHandler CustomErrors {
+                       get {
+                               return custom_errors;
+                       }
+                       set {
+                               custom_errors = value;
                        }
                }
 
-               public override bool IsStatic {
+               TypeSpec DelegateType {
                        get {
-                               if (best_candidate != null)
-                                       return best_candidate.IsStatic;
+                               if ((restrictions & Restrictions.DelegateInvoke) == 0)
+                                       throw new InternalErrorException ("Not running in delegate mode", loc);
 
-                               foreach (var mb in Methods)
-                                       if (mb.IsStatic)
-                                               return true;
+                               return members [0].DeclaringType;
+                       }
+               }
 
-                               return false;
+               bool IsProbingOnly {
+                       get {
+                               return (restrictions & Restrictions.ProbingOnly) != 0;
                        }
                }
 
-               public static explicit operator MethodSpec (MethodGroupExpr mg)
-               {
-                       return mg.best_candidate;
+               bool IsDelegateInvoke {
+                       get {
+                               return (restrictions & Restrictions.DelegateInvoke) != 0;
+                       }
                }
 
+               #endregion
+
                //
                //  7.4.3.3  Better conversion from expression
                //  Returns :   1    if a->p is better,
@@ -3077,12 +3299,12 @@ namespace Mono.CSharp {
                                // Uwrap delegate from Expression<T>
                                //
                                if (p.GetDefinition () == TypeManager.expression_type) {
-                                       p = TypeManager.GetTypeArguments (p) [0];
+                                       p = TypeManager.GetTypeArguments (p)[0];
                                }
                                if (q.GetDefinition () == TypeManager.expression_type) {
-                                       q = TypeManager.GetTypeArguments (q) [0];
+                                       q = TypeManager.GetTypeArguments (q)[0];
                                }
-                               
+
                                p = Delegate.GetInvokeMethod (ec.Compiler, p).ReturnType;
                                q = Delegate.GetInvokeMethod (ec.Compiler, q).ReturnType;
                                if (p == TypeManager.void_type && q != TypeManager.void_type)
@@ -3171,39 +3393,37 @@ namespace Mono.CSharp {
                ///     false if candidate ain't better
                ///     true  if candidate is better than the current best match
                /// </remarks>
-               static bool BetterFunction (ResolveContext ec, Arguments args, int argument_count,
-                       MethodSpec candidate, bool candidate_params,
-                       MethodSpec best, bool best_params)
+               static bool BetterFunction (ResolveContext ec, Arguments args, MemberSpec candidate, bool candidate_params,
+                       MemberSpec best, bool best_params)
                {
-                       AParametersCollection candidate_pd = candidate.Parameters;
-                       AParametersCollection best_pd = best.Parameters;
-               
+                       AParametersCollection candidate_pd = ((IParametersMember) candidate).Parameters;
+                       AParametersCollection best_pd = ((IParametersMember) best).Parameters;
+
                        bool better_at_least_one = false;
                        bool same = true;
-                       for (int j = 0, c_idx = 0, b_idx = 0; j < argument_count; ++j, ++c_idx, ++b_idx) 
-                       {
-                               Argument a = args [j];
+                       int args_count = args == null ? 0 : args.Count;
+                       int j = 0;
+                       for (int c_idx = 0, b_idx = 0; j < args_count; ++j, ++c_idx, ++b_idx) {
+                               Argument a = args[j];
 
-                               // Provided default argument value is never better
-                               if (a.IsDefaultArgument && candidate_params == best_params)
-                                       return false;
+                               // Default arguments are ignored for better decision
+                               if (a.IsDefaultArgument)
+                                       break;
 
-                               TypeSpec ct = candidate_pd.Types [c_idx];
-                               TypeSpec bt = best_pd.Types [b_idx];
+                               TypeSpec ct = candidate_pd.Types[c_idx];
+                               TypeSpec bt = best_pd.Types[b_idx];
 
-                               if (candidate_params && candidate_pd.FixedParameters [c_idx].ModFlags == Parameter.Modifier.PARAMS) 
-                               {
+                               if (candidate_params && candidate_pd.FixedParameters[c_idx].ModFlags == Parameter.Modifier.PARAMS) {
                                        ct = TypeManager.GetElementType (ct);
                                        --c_idx;
                                }
 
-                               if (best_params && best_pd.FixedParameters [b_idx].ModFlags == Parameter.Modifier.PARAMS) 
-                               {
+                               if (best_params && best_pd.FixedParameters[b_idx].ModFlags == Parameter.Modifier.PARAMS) {
                                        bt = TypeManager.GetElementType (bt);
                                        --b_idx;
                                }
-                               
-                               if (TypeManager.IsEqual (ct, bt))
+
+                               if (ct == bt)
                                        continue;
 
                                same = false;
@@ -3236,239 +3456,88 @@ namespace Mono.CSharp {
                                return false;
 
                        //
-                       // The two methods have equal parameter types.  Now apply tie-breaking rules
+                       // The two methods have equal non-optional parameter types, apply tie-breaking rules
                        //
-                       if (best.IsGeneric) {
-                               if (!candidate.IsGeneric)
-                                       return true;
-                       } else if (candidate.IsGeneric) {
-                               return false;
-                       }
 
                        //
                        // This handles the following cases:
                        //
-                       //   Trim () is better than Trim (params char[] chars)
-                       //   Concat (string s1, string s2, string s3) is better than
-                       //     Concat (string s1, params string [] srest)
-                       //   Foo (int, params int [] rest) is better than Foo (params int [] rest)
-                       //
-                       if (!candidate_params && best_params)
-                               return true;
-                       if (candidate_params && !best_params)
-                               return false;
-
-                       int candidate_param_count = candidate_pd.Count;
-                       int best_param_count = best_pd.Count;
-
-                       if (candidate_param_count != best_param_count)
-                               // can only happen if (candidate_params && best_params)
-                               return candidate_param_count > best_param_count && best_pd.HasParams;
-
+                       //  Foo (int i) is better than Foo (int i, long l = 0)
+                       //  Foo (params int[] args) is better than Foo (int i = 0, params int[] args)
                        //
-                       // Both methods have the same number of parameters, and the parameters have equal types
-                       // Pick the "more specific" signature using rules over original (non-inflated) types
+                       // Prefer non-optional version
                        //
-                       var candidate_def_pd = ((IParametersMember) candidate.MemberDefinition).Parameters;
-                       var best_def_pd = ((IParametersMember) best.MemberDefinition).Parameters;
+                       // LAMESPEC: Specification claims this should be done at last but the opposite is true
+                       if (candidate_params == best_params && candidate_pd.Count != best_pd.Count) {
+                               if (candidate_pd.Count >= best_pd.Count)
+                                       return false;
 
-                       bool specific_at_least_once = false;
-                       for (int j = 0; j < candidate_param_count; ++j) 
-                       {
-                               var ct = candidate_def_pd.Types [j];
-                               var bt = best_def_pd.Types [j];
-                               if (ct == bt)
-                                       continue;
-                               TypeSpec specific = MoreSpecific (ct, bt);
-                               if (specific == bt)
+                               if (j < candidate_pd.Count && candidate_pd.FixedParameters[j].HasDefaultValue)
                                        return false;
-                               if (specific == ct)
-                                       specific_at_least_once = true;
-                       }
 
-                       if (specific_at_least_once)
                                return true;
-
-                       // FIXME: handle lifted operators
-                       // ...
-
-                       return false;
-               }
-
-               protected override MemberExpr ResolveExtensionMemberAccess (ResolveContext ec, Expression left)
-               {
-                       if (!IsStatic)
-                               return base.ResolveExtensionMemberAccess (ec, left);
+                       }
 
                        //
-                       // When left side is an expression and at least one candidate method is 
-                       // static, it can be extension method
+                       // One is a non-generic method and second is a generic method, then non-generic is better
                        //
-                       InstanceExpression = left;
-                       return this;
-               }
-
-               public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
-                                                               SimpleName original)
-               {
-                       if (!(left is TypeExpr) &&
-                           original != null && original.IdenticalNameAndTypeName (ec, left, loc))
-                               identical_type_name = true;
-
-                       return base.ResolveMemberAccess (ec, left, loc, original);
-               }
-
-               public override Expression CreateExpressionTree (ResolveContext ec)
-               {
-                       if (best_candidate == null) {
-                               ec.Report.Error (1953, loc, "An expression tree cannot contain an expression with method group");
-                               return null;
-                       }
-
-                       if (best_candidate.IsConditionallyExcluded (loc))
-                               ec.Report.Error (765, loc,
-                                       "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
-                       
-                       return new TypeOfMethod (best_candidate, loc);
-               }
-               
-               protected override Expression DoResolve (ResolveContext ec)
-               {
-                       this.eclass = ExprClass.MethodGroup;
-
-                       if (InstanceExpression != null) {
-                               InstanceExpression = InstanceExpression.Resolve (ec);
-                               if (InstanceExpression == null)
-                                       return null;
-                       }
-
-                       return this;
-               }
-
-               public void ReportUsageError (ResolveContext ec)
-               {
-                       ec.Report.Error (654, loc, "Method `" + DeclaringType + "." +
-                                     Name + "()' is referenced without parentheses");
-               }
-
-               override public void Emit (EmitContext ec)
-               {
-                       throw new NotSupportedException ();
-                       // ReportUsageError ();
-               }
-               
-               public void EmitCall (EmitContext ec, Arguments arguments)
-               {
-                       Invocation.EmitCall (ec, IsBase, InstanceExpression, best_candidate, arguments, loc);                   
-               }
-
-               void Error_AmbiguousCall (ResolveContext ec, MethodSpec ambiguous)
-               {
-                       if (CustomErrorHandler != null && CustomErrorHandler.AmbiguousCall (ec, ambiguous))
-                               return;
-
-                       ec.Report.SymbolRelatedToPreviousError (best_candidate);
-                       ec.Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'",
-                               best_candidate.GetSignatureForError (), ambiguous.GetSignatureForError ());
-               }
-
-               protected virtual void Error_InvalidArguments (ResolveContext ec, Location loc, int idx, MethodSpec method,
-                                                                                                       Argument a, AParametersCollection expected_par, TypeSpec paramType)
-               {
-                       ExtensionMethodGroupExpr emg = this as ExtensionMethodGroupExpr;
-
-                       if (a is CollectionElementInitializer.ElementInitializerArgument) {
-                               ec.Report.SymbolRelatedToPreviousError (method);
-                               if ((expected_par.FixedParameters [idx].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
-                                       ec.Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier",
-                                               TypeManager.CSharpSignature (method));
-                                       return;
-                               }
-                               ec.Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments",
-                                         TypeManager.CSharpSignature (method));
-                       } else if (TypeManager.IsDelegateType (method.DeclaringType)) {
-                               ec.Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments",
-                                       TypeManager.CSharpName (method.DeclaringType));
-                       } else {
-                               ec.Report.SymbolRelatedToPreviousError (method);
-                               if (emg != null) {
-                                       ec.Report.Error (1928, loc,
-                                               "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' has some invalid arguments",
-                                               emg.ExtensionExpression.GetSignatureForError (),
-                                               emg.Name, TypeManager.CSharpSignature (method));
-                               } else {
-                                       ec.Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments",
-                                               TypeManager.CSharpSignature (method));
-                               }
-                       }
+                       if (best.IsGeneric != candidate.IsGeneric)
+                               return best.IsGeneric;
 
-                       Parameter.Modifier mod = idx >= expected_par.Count ? 0 : expected_par.FixedParameters [idx].ModFlags;
+                       //
+                       // This handles the following cases:
+                       //
+                       //   Trim () is better than Trim (params char[] chars)
+                       //   Concat (string s1, string s2, string s3) is better than
+                       //     Concat (string s1, params string [] srest)
+                       //   Foo (int, params int [] rest) is better than Foo (params int [] rest)
+                       //
+                       // Prefer non-expanded version
+                       //
+                       if (candidate_params != best_params)
+                               return best_params;
 
-                       string index = (idx + 1).ToString ();
-                       if (((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) ^
-                               (a.Modifier & (Parameter.Modifier.REF | Parameter.Modifier.OUT))) != 0) {
-                               if ((mod & Parameter.Modifier.ISBYREF) == 0)
-                                       ec.Report.Error (1615, loc, "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' modifier",
-                                               index, Parameter.GetModifierSignature (a.Modifier));
-                               else
-                                       ec.Report.Error (1620, loc, "Argument `#{0}' is missing `{1}' modifier",
-                                               index, Parameter.GetModifierSignature (mod));
-                       } else {
-                               string p1 = a.GetSignatureForError ();
-                               string p2 = TypeManager.CSharpName (paramType);
+                       int candidate_param_count = candidate_pd.Count;
+                       int best_param_count = best_pd.Count;
 
-                               if (p1 == p2) {
-                                       ec.Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous ");
-                                       ec.Report.SymbolRelatedToPreviousError (a.Expr.Type);
-                                       ec.Report.SymbolRelatedToPreviousError (paramType);
-                               }
+                       if (candidate_param_count != best_param_count)
+                               // can only happen if (candidate_params && best_params)
+                               return candidate_param_count > best_param_count && best_pd.HasParams;
 
-                               if (idx == 0 && emg != null) {
-                                       ec.Report.Error (1929, loc,
-                                               "Extension method instance type `{0}' cannot be converted to `{1}'", p1, p2);
-                               } else {
-                                       ec.Report.Error (1503, loc,
-                                               "Argument `#{0}' cannot convert `{1}' expression to type `{2}'", index, p1, p2);
-                               }
+                       //
+                       // Both methods have the same number of parameters, and the parameters have equal types
+                       // Pick the "more specific" signature using rules over original (non-inflated) types
+                       //
+                       var candidate_def_pd = ((IParametersMember) candidate.MemberDefinition).Parameters;
+                       var best_def_pd = ((IParametersMember) best.MemberDefinition).Parameters;
+
+                       bool specific_at_least_once = false;
+                       for (j = 0; j < candidate_param_count; ++j) {
+                               var ct = candidate_def_pd.Types[j];
+                               var bt = best_def_pd.Types[j];
+                               if (ct == bt)
+                                       continue;
+                               TypeSpec specific = MoreSpecific (ct, bt);
+                               if (specific == bt)
+                                       return false;
+                               if (specific == ct)
+                                       specific_at_least_once = true;
                        }
-               }
 
-               public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
-               {
-                       ec.Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method",
-                               Name, TypeManager.CSharpName (target));
-               }
+                       if (specific_at_least_once)
+                               return true;
 
-               void Error_ArgumentCountWrong (ResolveContext ec, int arg_count)
-               {
-                       ec.Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments",
-                                     Name, arg_count.ToString ());
-               }
-               
-               protected virtual int GetApplicableParametersCount (MethodSpec method, AParametersCollection parameters)
-               {
-                       return parameters.Count;
-               }
+                       // FIXME: handle lifted operators
+                       // ...
 
-               protected virtual IList<MemberSpec> GetBaseTypeMethods (ResolveContext rc, TypeSpec type)
-               {
-                       return TypeManager.MemberLookup (rc.CurrentType, null, type,
-                               MemberKind.Method, BindingRestriction.AccessibleOnly | BindingRestriction.NoOverrides,
-                               Name, 0, null); // TODO MemberCache: Arity !
+                       return false;
                }
 
-               bool GetBaseTypeMethods (ResolveContext rc)
+               public static void Error_ConstructorMismatch (ResolveContext rc, TypeSpec type, int argCount, Location loc)
                {
-                       var base_type = Methods.First ().DeclaringType.BaseType;
-                       if (base_type == null)
-                               return false;
-
-                       var methods = GetBaseTypeMethods (rc, base_type);
-                       if (methods == null)
-                               return false;
-
-                       Methods = methods;
-                       return true;
+                       rc.Report.Error (1729, loc,
+                               "The type `{0}' does not contain a constructor that takes `{1}' arguments",
+                               type.GetSignatureForError (), argCount.ToString ());
                }
 
                ///
@@ -3477,18 +3546,16 @@ namespace Mono.CSharp {
                /// A return value rates candidate method compatibility,
                /// 0 = the best, int.MaxValue = the worst
                ///
-               public int IsApplicable (ResolveContext ec,
-                                               ref Arguments arguments, int arg_count, ref MethodSpec method, ref bool params_expanded_form)
+               int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref MemberSpec candidate, ref bool params_expanded_form)
                {
-                       var candidate = method;
-
-                       AParametersCollection pd = candidate.Parameters;
-                       int param_count = GetApplicableParametersCount (candidate, pd);
+                       AParametersCollection pd = ((IParametersMember) candidate).Parameters;
+                       int param_count = pd.Count;
                        int optional_count = 0;
+                       int score;
 
                        if (arg_count != param_count) {
                                for (int i = 0; i < pd.Count; ++i) {
-                                       if (pd.FixedParameters [i].HasDefaultValue) {
+                                       if (pd.FixedParameters[i].HasDefaultValue) {
                                                optional_count = pd.Count - i;
                                                break;
                                        }
@@ -3514,22 +3581,19 @@ namespace Mono.CSharp {
                                                return int.MaxValue - 10000 + args_gap;
                                }
 
-                               // Initialize expanded form of a method with 1 params parameter
-                               params_expanded_form = param_count == 1 && pd.HasParams;
-
                                // Resize to fit optional arguments
                                if (optional_count != 0) {
-                                       Arguments resized;
                                        if (arguments == null) {
-                                               resized = new Arguments (optional_count);
+                                               arguments = new Arguments (optional_count);
                                        } else {
-                                               resized = new Arguments (param_count);
+                                               // Have to create a new container, so the next run can do same
+                                               var resized = new Arguments (param_count);
                                                resized.AddRange (arguments);
+                                               arguments = resized;
                                        }
 
                                        for (int i = arg_count; i < param_count; ++i)
-                                               resized.Add (null);
-                                       arguments = resized;
+                                               arguments.Add (null);
                                }
                        }
 
@@ -3537,7 +3601,7 @@ namespace Mono.CSharp {
                                //
                                // Shuffle named arguments to the right positions if there are any
                                //
-                               if (arguments [arg_count - 1] is NamedArgument) {
+                               if (arguments[arg_count - 1] is NamedArgument) {
                                        arg_count = arguments.Count;
 
                                        for (int i = 0; i < arg_count; ++i) {
@@ -3550,19 +3614,31 @@ namespace Mono.CSharp {
                                                        int index = pd.GetParameterIndexByName (na.Name);
 
                                                        // Named parameter not found or already reordered
-                                                       if (index <= i)
+                                                       if (index == i || index < 0)
                                                                break;
 
-                                                       // When using parameters which should not be available to the user
-                                                       if (index >= param_count)
-                                                               break;
+                                                       Argument temp;
+                                                       if (index >= param_count) {
+                                                               // When using parameters which should not be available to the user
+                                                               if ((pd.FixedParameters[index].ModFlags & Parameter.Modifier.PARAMS) == 0)
+                                                                       break;
+
+                                                               arguments.Add (null);
+                                                               ++arg_count;
+                                                               temp = null;
+                                                       } else {
+                                                               temp = arguments[index];
+
+                                                               // The slot has been taken by positional argument
+                                                               if (temp != null && !(temp is NamedArgument))
+                                                                       break;
+                                                       }
 
                                                        if (!arg_moved) {
                                                                arguments.MarkReorderedArgument (na);
                                                                arg_moved = true;
                                                        }
 
-                                                       Argument temp = arguments[index];
                                                        arguments[index] = arguments[i];
                                                        arguments[i] = temp;
 
@@ -3580,22 +3656,47 @@ namespace Mono.CSharp {
                        //
                        // 1. Handle generic method using type arguments when specified or type inference
                        //
-                       if (candidate.IsGeneric) {
+                       var ms = candidate as MethodSpec;
+                       if (ms != null && ms.IsGeneric) {
+                               // Setup constraint checker for probing only
+                               ConstraintChecker cc = new ConstraintChecker (null);
+
                                if (type_arguments != null) {
-                                       var g_args_count = candidate.Arity;
+                                       var g_args_count = ms.Arity;
                                        if (g_args_count != type_arguments.Count)
                                                return int.MaxValue - 20000 + System.Math.Abs (type_arguments.Count - g_args_count);
 
-                                       method = candidate.MakeGenericMethod (type_arguments.Arguments);
-                                       candidate = method;
-                                       pd = candidate.Parameters;
+                                       candidate = ms = ms.MakeGenericMethod (type_arguments.Arguments);
+                                       pd = ms.Parameters;
                                } else {
-                                       int score = TypeManager.InferTypeArguments (ec, arguments, ref candidate);
-                                       if (score != 0)
-                                               return score - 20000;
+                                       // TODO: It should not be here (we don't know yet whether any argument is lambda) but
+                                       // for now it simplifies things. I should probably add a callback to ResolveContext
+                                       if (lambda_conv_msgs == null) {
+                                               lambda_conv_msgs = new SessionReportPrinter ();
+                                               prev_recorder = ec.Report.SetPrinter (lambda_conv_msgs);
+                                       }
+
+                                       var ti = new TypeInference (arguments);
+                                       TypeSpec[] i_args = ti.InferMethodArguments (ec, ms);
+                                       lambda_conv_msgs.EndSession ();
+
+                                       if (i_args == null)
+                                               return ti.InferenceScore - 20000;
+
+                                       if (i_args.Length != 0) {
+                                               candidate = ms = ms.MakeGenericMethod (i_args);
+                                               pd = ms.Parameters;
+                                       }
 
-                                       pd = candidate.Parameters;
+                                       cc.IgnoreInferredDynamic = true;
                                }
+
+                               //
+                               // Type arguments constraints have to match for the method to be applicable
+                               //
+                               if (!cc.CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc))
+                                       return int.MaxValue - 25000;
+
                        } else {
                                if (type_arguments != null)
                                        return int.MaxValue - 15000;
@@ -3604,38 +3705,59 @@ namespace Mono.CSharp {
                        //
                        // 2. Each argument has to be implicitly convertible to method parameter
                        //
-                       method = candidate;
                        Parameter.Modifier p_mod = 0;
                        TypeSpec pt = null;
                        for (int i = 0; i < arg_count; i++) {
-                               Argument a = arguments [i];
+                               Argument a = arguments[i];
                                if (a == null) {
-                                       if (!pd.FixedParameters [i].HasDefaultValue)
+                                       if (!pd.FixedParameters[i].HasDefaultValue)
                                                throw new InternalErrorException ();
 
-                                       Expression e = pd.FixedParameters [i].DefaultValue as Constant;
-                                       if (e == null)
-                                               e = new DefaultValueExpression (new TypeExpression (pd.Types [i], loc), loc).Resolve (ec);
+                                       //
+                                       // Get the default value expression, we can use the same expression
+                                       // if the type matches
+                                       //
+                                       Expression e = pd.FixedParameters[i].DefaultValue;
+                                       if (!(e is Constant) || e.Type.IsGenericOrParentIsGeneric) {
+                                               //
+                                               // LAMESPEC: No idea what the exact rules are for System.Reflection.Missing.Value instead of null
+                                               //
+                                               if (e == EmptyExpression.MissingValue && pd.Types[i] == TypeManager.object_type) {
+                                                       e = new MemberAccess (new MemberAccess (new MemberAccess (
+                                                               new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Reflection", loc), "Missing", loc), "Value", loc);
+                                               } else {
+                                                       e = new DefaultValueExpression (new TypeExpression (pd.Types[i], loc), loc);
+                                               }
+
+                                               e = e.Resolve (ec);
+                                       }
 
-                                       arguments [i] = new Argument (e, Argument.AType.Default);
+                                       arguments[i] = new Argument (e, Argument.AType.Default);
                                        continue;
                                }
 
                                if (p_mod != Parameter.Modifier.PARAMS) {
-                                       p_mod = pd.FixedParameters [i].ModFlags & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
-                                       pt = pd.Types [i];
-                               } else {
+                                       p_mod = pd.FixedParameters[i].ModFlags;
+                                       pt = pd.Types[i];
+                               } else if (!params_expanded_form) {
                                        params_expanded_form = true;
+                                       pt = ((ElementTypeSpec) pt).Element;
+                                       i -= 2;
+                                       continue;
                                }
 
-                               Parameter.Modifier a_mod = a.Modifier & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
-                               int score = 1;
+                               score = 1;
                                if (!params_expanded_form)
-                                       score = IsArgumentCompatible (ec, a_mod, a, p_mod & ~Parameter.Modifier.PARAMS, pt);
+                                       score = IsArgumentCompatible (ec, a, p_mod & ~Parameter.Modifier.PARAMS, pt);
 
-                               if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && delegate_type == null) {
-                                       // It can be applicable in expanded form
-                                       score = IsArgumentCompatible (ec, a_mod, a, 0, TypeManager.GetElementType (pt));
+                               //
+                               // It can be applicable in expanded form (when not doing exact match like for delegates)
+                               //
+                               if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && (restrictions & Restrictions.CovariantDelegate) == 0) {
+                                       if (!params_expanded_form)
+                                               pt = ((ElementTypeSpec) pt).Element;
+
+                                       score = IsArgumentCompatible (ec, a, Parameter.Modifier.NONE, pt);
                                        if (score == 0)
                                                params_expanded_form = true;
                                }
@@ -3646,67 +3768,65 @@ namespace Mono.CSharp {
                                        return (arg_count - i) * 2 + score;
                                }
                        }
-                       
-                       if (arg_count != param_count)
-                               params_expanded_form = true;    
-                       
+
+                       //
+                       // When params parameter has notargument, will be provided later if the method is the best candidate
+                       //
+                       if (arg_count + 1 == pd.Count && (pd.FixedParameters [arg_count].ModFlags & Parameter.Modifier.PARAMS) != 0)
+                               params_expanded_form = true;
+
                        return 0;
                }
 
-               int IsArgumentCompatible (ResolveContext ec, Parameter.Modifier arg_mod, Argument argument, Parameter.Modifier param_mod, TypeSpec parameter)
+               int IsArgumentCompatible (ResolveContext ec, Argument argument, Parameter.Modifier param_mod, TypeSpec parameter)
                {
                        //
-                       // Types have to be identical when ref or out modifer is used 
+                       // Types have to be identical when ref or out modifer
+                       // is used and argument is not of dynamic type
                        //
-                       if (arg_mod != 0 || param_mod != 0) {
-                               if (TypeManager.HasElementType (parameter))
-                                       parameter = TypeManager.GetElementType (parameter);
-
-                               TypeSpec a_type = argument.Type;
-                               if (TypeManager.HasElementType (a_type))
-                                       a_type = TypeManager.GetElementType (a_type);
-
-                               if (a_type != parameter) {
-                                       if (a_type == InternalType.Dynamic)
-                                               return 0;
+                       if ((argument.Modifier | param_mod) != 0) {
+                               //
+                               // Defer to dynamic binder
+                               //
+                               if (argument.Type == InternalType.Dynamic)
+                                       return 0;
 
-                                       return 2;
+                               if (argument.Type != parameter) {
+                                       //
+                                       // Do full equality check after quick path
+                                       //
+                                       if (!TypeSpecComparer.IsEqual (argument.Type, parameter))
+                                               return 2;
                                }
                        } else {
+                               //
+                               // Deploy custom error reporting for lambda methods. When probing lambda methods
+                               // keep all errors reported in separate set and once we are done and no best
+                               // candidate found, this set is used to report more details about what was wrong
+                               // with lambda body
+                               //
+                               if (argument.Expr.Type == InternalType.AnonymousMethod) {
+                                       if (lambda_conv_msgs == null) {
+                                               lambda_conv_msgs = new SessionReportPrinter ();
+                                               prev_recorder = ec.Report.SetPrinter (lambda_conv_msgs);
+                                       }
+                               }
+
                                if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) {
-                                       if (argument.Type == InternalType.Dynamic)
-                                               return 0;
+                                       if (lambda_conv_msgs != null) {
+                                               lambda_conv_msgs.EndSession ();
+                                       }
 
                                        return 2;
                                }
                        }
 
-                       if (arg_mod != param_mod)
+                       if (argument.Modifier != param_mod)
                                return 1;
 
                        return 0;
                }
 
-               public static MethodGroupExpr MakeUnionSet (MethodGroupExpr mg1, MethodGroupExpr mg2, Location loc)
-               {
-                       if (mg1 == null) {
-                               if (mg2 == null)
-                                       return null;
-                               return mg2;
-                       }
-
-                       if (mg2 == null)
-                               return mg1;
-
-                       var all = new List<MemberSpec> (mg1.Methods);
-                       foreach (MethodSpec m in mg2.Methods){
-                               if (!TypeManager.ArrayContainsMethod (all, m, false))
-                                       all.Add (m);
-                       }
-
-                       return new MethodGroupExpr (all, null, loc);
-               }               
-
                static TypeSpec MoreSpecific (TypeSpec p, TypeSpec q)
                {
                        if (TypeManager.IsGenericParameter (p) && !TypeManager.IsGenericParameter (q))
@@ -3717,7 +3837,7 @@ namespace Mono.CSharp {
                        var ac_p = p as ArrayContainer;
                        if (ac_p != null) {
                                var ac_q = ((ArrayContainer) q);
-                               TypeSpec specific = MoreSpecific (ac_p.Element, (ac_q.Element));
+                               TypeSpec specific = MoreSpecific (ac_p.Element, ac_q.Element);
                                if (specific == ac_p.Element)
                                        return p;
                                if (specific == ac_q.Element)
@@ -3746,224 +3866,183 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               /// <summary>
-               ///   Find the Applicable Function Members (7.4.2.1)
-               ///
-               ///   me: Method Group expression with the members to select.
-               ///       it might contain constructors or methods (or anything
-               ///       that maps to a method).
-               ///
-               ///   Arguments: ArrayList containing resolved Argument objects.
-               ///
-               ///   loc: The location if we want an error to be reported, or a Null
-               ///        location for "probing" purposes.
-               ///
-               ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
-               ///            that is the best match of me on Arguments.
-               ///
-               /// </summary>
-               public virtual MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments Arguments,
-                       bool may_fail, Location loc)
+               //
+               // Find the best method from candidate list
+               //
+               public T ResolveMember<T> (ResolveContext rc, ref Arguments args) where T : MemberSpec, IParametersMember
                {
-                       var candidates = new List<MethodSpec> (2);
-                       List<MethodSpec> params_candidates = null;
-
-                       int arg_count = Arguments != null ? Arguments.Count : 0;
-                       Dictionary<MethodSpec, Arguments> candidates_expanded = null;
-                       Arguments candidate_args = Arguments;
-
-                       if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
-                               if (!may_fail)
-                                       ec.Report.Error (1533, loc, "Invoke cannot be called directly on a delegate");
-                               return null;
-                       }
+                       List<AmbiguousCandidate> ambiguous_candidates = null;
 
-                       //
-                       // Enable message recording, it's used mainly by lambda expressions
-                       //
-                       var msg_recorder = new SessionReportPrinter ();
-                       var prev_recorder = ec.Report.SetPrinter (msg_recorder);
+                       MemberSpec best_candidate;
+                       Arguments best_candidate_args = null;
+                       bool best_candidate_params = false;
+                       int best_candidate_rate;
 
-                       do {
-                               //
-                               // Methods in a base class are not candidates if any method in a derived
-                               // class is applicable
-                               //
-                               int best_candidate_rate = int.MaxValue;
-
-                               foreach (var member in Methods) {
-                                       var m = member as MethodSpec;
-                                       if (m == null) {
-                                               // TODO: It's wrong when non-member is before applicable method
-                                               // TODO: Should report only when at least 1 from the batch is applicable
-                                               if (candidates.Count != 0) {
-                                                       ec.Report.SymbolRelatedToPreviousError (candidates [0]);
-                                                       ec.Report.SymbolRelatedToPreviousError (member);
-                                                       ec.Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and non-method `{1}'. Using method `{0}'",
-                                                               candidates[0].GetSignatureForError (), member.GetSignatureForError ());
-                                               }
-                                               continue;
-                                       }
+                       int args_count = args != null ? args.Count : 0;
+                       Arguments candidate_args = args;
+                       bool error_mode = false;
+                       var current_type = rc.CurrentType;
+                       MemberSpec invocable_member = null;
 
-                                       //
-                                       // Check if candidate is applicable (section 14.4.2.1)
-                                       //
-                                       bool params_expanded_form = false;
-                                       int candidate_rate = IsApplicable (ec, ref candidate_args, arg_count, ref m, ref params_expanded_form);
+                       // Be careful, cannot return until error reporter is restored
+                       while (true) {
+                               best_candidate = null;
+                               best_candidate_rate = int.MaxValue;
 
-                                       if (candidate_rate < best_candidate_rate) {
-                                               best_candidate_rate = candidate_rate;
-                                               best_candidate = m;
-                                       }
+                               var type_members = members;
+                               try {
 
-                                       if (params_expanded_form) {
-                                               if (params_candidates == null)
-                                                       params_candidates = new List<MethodSpec> (2);
-                                               params_candidates.Add (m);
-                                       }
+                                       do {
+                                               for (int i = 0; i < type_members.Count; ++i) {
+                                                       var member = type_members[i];
 
-                                       if (candidate_args != Arguments) {
-                                               if (candidates_expanded == null)
-                                                       candidates_expanded = new Dictionary<MethodSpec, Arguments> (2);
+                                                       //
+                                                       // Methods in a base class are not candidates if any method in a derived
+                                                       // class is applicable
+                                                       //
+                                                       if ((member.Modifiers & Modifiers.OVERRIDE) != 0)
+                                                               continue;
 
-                                               candidates_expanded.Add (m, candidate_args);
-                                               candidate_args = Arguments;
-                                       }
+                                                       if (!member.IsAccessible (current_type) && !error_mode)
+                                                               continue;
 
-                                       if (candidate_rate != 0 || has_inaccessible_candidates_only) {
-                                               if (msg_recorder != null)
-                                                       msg_recorder.EndSession ();
-                                               continue;
-                                       }
+                                                       if (!(member is IParametersMember)) {
+                                                               //
+                                                               // Will use it later to report ambiguity between best method and invocable member
+                                                               //
+                                                               if (Invocation.IsMemberInvocable (member))
+                                                                       invocable_member = member;
 
-                                       msg_recorder = null;
-                                       candidates.Add (m);
-                               }
-                       } while (candidates.Count == 0 && GetBaseTypeMethods (ec));
+                                                               continue;
+                                                       }
 
-                       ec.Report.SetPrinter (prev_recorder);
-                       if (msg_recorder != null && !msg_recorder.IsEmpty) {
-                               if (!may_fail)
-                                       msg_recorder.Merge (prev_recorder);
+                                                       //
+                                                       // Check if candidate is applicable
+                                                       //
+                                                       bool params_expanded_form = false;
+                                                       int candidate_rate = IsApplicable (rc, ref candidate_args, args_count, ref member, ref params_expanded_form);
+
+                                                       //
+                                                       // How does it score compare to others
+                                                       //
+                                                       if (candidate_rate < best_candidate_rate) {
+                                                               best_candidate_rate = candidate_rate;
+                                                               best_candidate = member;
+                                                               best_candidate_args = candidate_args;
+                                                               best_candidate_params = params_expanded_form;
+                                                       } else if (candidate_rate == 0) {
+                                                               //
+                                                               // The member look is done per type for most operations but sometimes
+                                                               // it's not possible like for binary operators overload because they
+                                                               // are unioned between 2 sides
+                                                               //
+                                                               if ((restrictions & Restrictions.BaseMembersIncluded) != 0) {
+                                                                       if (TypeSpec.IsBaseClass (best_candidate.DeclaringType, member.DeclaringType, true))
+                                                                               continue;
+                                                               }
 
-                               return null;
-                       }
+                                                               // Is new candidate better
+                                                               if (BetterFunction (rc, candidate_args, member, params_expanded_form, best_candidate, best_candidate_params)) {
+                                                                       best_candidate = member;
+                                                                       best_candidate_args = candidate_args;
+                                                                       best_candidate_params = params_expanded_form;
+                                                               } else {
+                                                                       // It's not better but any other found later could be but we are not sure yet
+                                                                       if (ambiguous_candidates == null)
+                                                                               ambiguous_candidates = new List<AmbiguousCandidate> ();
+
+                                                                       ambiguous_candidates.Add (new AmbiguousCandidate (member, params_expanded_form));
+                                                               }
+                                                       }
 
-                       int candidate_top = candidates.Count;
-                       if (candidate_top == 0) {
-                               //
-                               // When we found a top level method which does not match and it's 
-                               // not an extension method. We start extension methods lookup from here
-                               //
-                               if (InstanceExpression != null) {
-                                       var first = Methods.First ();
-                                       var arity = type_arguments == null ? -1 : type_arguments.Count;
-                                       ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (type, first.Name, arity, loc);
-                                       if (ex_method_lookup != null) {
-                                               ex_method_lookup.ExtensionExpression = InstanceExpression;
-                                               ex_method_lookup.SetTypeArguments (ec, type_arguments);
-                                               return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc);
-                                       }
+                                                       // Restore expanded arguments
+                                                       if (candidate_args != args)
+                                                               candidate_args = args;
+                                               }
+                                       } while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType.BaseType)) != null);
+                               } finally {
+                                       if (prev_recorder != null)
+                                               rc.Report.SetPrinter (prev_recorder);
                                }
-                               
-                               if (may_fail)
-                                       return null;
 
                                //
-                               // Okay so we have failed to find exact match so we
-                               // return error info about the closest match
+                               // We've found exact match
                                //
-                               if (best_candidate != null) {
-                                       if (CustomErrorHandler != null && !has_inaccessible_candidates_only && CustomErrorHandler.NoExactMatch (ec, best_candidate))
-                                               return null;
-
-                                       bool params_expanded = params_candidates != null && params_candidates.Contains (best_candidate);
-                                       if (NoExactMatch (ec, ref Arguments, params_expanded))
-                                               return null;
-                               }
+                               if (best_candidate_rate == 0)
+                                       break;
 
                                //
-                               // We failed to find any method with correct argument count
+                               // Try extension methods lookup when no ordinary method match was found and provider enables it
                                //
-                               if (Methods.First ().Kind == MemberKind.Constructor) {
-                                       ec.Report.SymbolRelatedToPreviousError (queried_type);
-                                       ec.Report.Error (1729, loc,
-                                               "The type `{0}' does not contain a constructor that takes `{1}' arguments",
-                                               TypeManager.CSharpName (queried_type), arg_count.ToString ());
-                               } else {
-                                       Error_ArgumentCountWrong (ec, arg_count);
+                               if (!error_mode) {
+                                       var emg = base_provider.LookupExtensionMethod (rc);
+                                       if (emg != null) {
+                                               emg = emg.OverloadResolve (rc, ref args, null, restrictions);
+                                               if (emg != null) {
+                                                       best_candidate_extension_group = emg;
+                                                       return (T) (MemberSpec) emg.BestCandidate;
+                                               }
+                                       }
                                }
-                                
-                               return null;
-                       }
 
-                       if (arg_count != 0 && Arguments.HasDynamic) {
-                               best_candidate = null;
-                               return this;
+                               // Don't run expensive error reporting mode for probing
+                               if (IsProbingOnly)
+                                       return null;
+
+                               if (error_mode)
+                                       break;
+
+                               lambda_conv_msgs = null;
+                               error_mode = true;
                        }
 
                        //
-                       // Now we actually find the best method
+                       // No best member match found, report an error
                        //
-                       best_candidate = candidates [0];
-                       bool method_params = params_candidates != null && params_candidates.Contains (best_candidate);
-
-                       for (int ix = 1; ix < candidate_top; ix++) {
-                               var candidate = candidates [ix];
-
-                               if (candidate == best_candidate)
-                                       continue;
-
-                               bool cand_params = params_candidates != null && params_candidates.Contains (candidate);
-
-                               if (candidates_expanded != null && candidates_expanded.ContainsKey (candidate)) {
-                                       candidate_args = candidates_expanded[candidate];
-                                       arg_count = candidate_args.Count;
-                               }
-
-                               if (BetterFunction (ec, candidate_args, arg_count, 
-                                       candidate, cand_params,
-                                       best_candidate, method_params)) {
-                                       best_candidate = candidate;
-                                       method_params = cand_params;
-                               }
+                       if (best_candidate_rate != 0 || error_mode) {
+                               ReportOverloadError (rc, best_candidate, best_candidate_args, best_candidate_params);
+                               return null;
+                       }
 
-                               if (candidate_args != Arguments) {
-                                       candidate_args = Arguments;
-                                       arg_count = candidate_args != null ? candidate_args.Count : 0;
+                       // TODO: HasDynamic is quite slow
+                       if (args_count != 0 && (restrictions & Restrictions.CovariantDelegate) == 0 && args.HasDynamic) {
+                               if (args [0].ArgType == Argument.AType.ExtensionType) {
+                                       rc.Report.Error (1973, loc,
+                                               "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",
+                                               args [0].Type.GetSignatureForError (), best_candidate.Name, best_candidate.GetSignatureForError());
                                }
-                       }
 
-                       if (candidates_expanded != null && candidates_expanded.ContainsKey (best_candidate)) {
-                               candidate_args = candidates_expanded[best_candidate];
-                               arg_count = candidate_args.Count;
+                               BestCandidateIsDynamic = true;
+                               return null;
                        }
 
-                       //
-                       // Now check that there are no ambiguities i.e the selected method
-                       // should be better than all the others
-                       //
-                       MethodSpec ambiguous = null;
-                       for (int ix = 1; ix < candidate_top; ix++) {
-                               var candidate = candidates [ix];
-
-                               if (candidate == best_candidate)
-                                       continue;
+                       if (ambiguous_candidates != null) {
+                               //
+                               // Now check that there are no ambiguities i.e the selected method
+                               // should be better than all the others
+                               //
+                               for (int ix = 0; ix < ambiguous_candidates.Count; ix++) {
+                                       var candidate = ambiguous_candidates [ix];
+
+                                       if (!BetterFunction (rc, candidate_args, best_candidate, best_candidate_params, candidate.Member, candidate.Expanded)) {
+                                               var ambiguous = candidate.Member;
+                                               if (custom_errors == null || !custom_errors.AmbiguousCandidates (rc, best_candidate, ambiguous)) {
+                                                       rc.Report.SymbolRelatedToPreviousError (best_candidate);
+                                                       rc.Report.SymbolRelatedToPreviousError (ambiguous);
+                                                       rc.Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'",
+                                                               best_candidate.GetSignatureForError (), ambiguous.GetSignatureForError ());
+                                               }
 
-                               bool cand_params = params_candidates != null && params_candidates.Contains (candidate);
-                               if (!BetterFunction (ec, candidate_args, arg_count,
-                                       best_candidate, method_params,
-                                       candidate, cand_params)) 
-                               {
-                                       if (!may_fail)
-                                               ec.Report.SymbolRelatedToPreviousError (candidate);
-                                       ambiguous = candidate;
+                                               return (T) best_candidate;
+                                       }
                                }
                        }
 
-                       if (ambiguous != null) {
-                               Error_AmbiguousCall (ec, ambiguous);
-                               return this;
+                       if (invocable_member != null) {
+                               rc.Report.SymbolRelatedToPreviousError (best_candidate);
+                               rc.Report.SymbolRelatedToPreviousError (invocable_member);
+                               rc.Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and invocable non-method `{1}'. Using method group",
+                                       best_candidate.GetSignatureForError (), invocable_member.GetSignatureForError ());
                        }
 
                        //
@@ -3972,102 +4051,177 @@ namespace Mono.CSharp {
                        // necessary etc. and return if everything is
                        // all right
                        //
-                       if (!VerifyArgumentsCompat (ec, ref candidate_args, arg_count, best_candidate,
-                               method_params, may_fail, loc))
+                       if (!VerifyArguments (rc, ref best_candidate_args, best_candidate, best_candidate_params))
                                return null;
 
                        if (best_candidate == null)
                                return null;
 
-                       if (best_candidate.IsGeneric) {
-                               ConstraintChecker.CheckAll (best_candidate.GetGenericMethodDefinition (), best_candidate.TypeArguments,
-                                       best_candidate.Constraints, loc, ec.Report);
-                       }
-
                        //
                        // Check ObsoleteAttribute on the best method
                        //
                        ObsoleteAttribute oa = best_candidate.GetAttributeObsolete ();
-                       if (oa != null && !ec.IsObsolete)
-                               AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
+                       if (oa != null && !rc.IsObsolete)
+                               AttributeTester.Report_ObsoleteMessage (oa, best_candidate.GetSignatureForError (), loc, rc.Report);
 
                        best_candidate.MemberDefinition.SetIsUsed ();
 
-                       Arguments = candidate_args;
-                       return this;
+                       args = best_candidate_args;
+                       return (T) best_candidate;
                }
 
-               bool NoExactMatch (ResolveContext ec, ref Arguments Arguments, bool params_expanded)
+               public MethodSpec ResolveOperator (ResolveContext rc, ref Arguments args)
                {
-                       AParametersCollection pd = best_candidate.Parameters;
-                       int arg_count = Arguments == null ? 0 : Arguments.Count;
+                       return ResolveMember<MethodSpec> (rc, ref args);
+               }
 
-                       if (arg_count == pd.Count || pd.HasParams) {
-                               if (best_candidate.IsGeneric) {
-                                       if (type_arguments == null) {
-                                               ec.Report.Error (411, loc,
-                                                       "The type arguments for method `{0}' cannot be inferred from the usage. Try specifying the type arguments explicitly",
-                                                       best_candidate.GetGenericMethodDefinition().GetSignatureForError ());
-                                               return true;
-                                       }
+               void ReportArgumentMismatch (ResolveContext ec, int idx, MemberSpec method,
+                                                                                                       Argument a, AParametersCollection expected_par, TypeSpec paramType)
+               {
+                       if (custom_errors != null && custom_errors.ArgumentMismatch (ec, method, a, idx))
+                               return;
+
+                       if (a is CollectionElementInitializer.ElementInitializerArgument) {
+                               ec.Report.SymbolRelatedToPreviousError (method);
+                               if ((expected_par.FixedParameters[idx].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
+                                       ec.Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier",
+                                               TypeManager.CSharpSignature (method));
+                                       return;
                                }
+                               ec.Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments",
+                                         TypeManager.CSharpSignature (method));
+                       } else if (IsDelegateInvoke) {
+                               ec.Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments",
+                                       DelegateType.GetSignatureForError ());
+                       } else {
+                               ec.Report.SymbolRelatedToPreviousError (method);
+                               ec.Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments",
+                                       method.GetSignatureForError ());
+                       }
 
-                               var ta = type_arguments == null ? 0 : type_arguments.Count;
-                               if (ta != best_candidate.Arity) {
-                                       Error_TypeArgumentsCannotBeUsed (ec.Report, loc, best_candidate, type_arguments.Count);
-                                       return true;
+                       Parameter.Modifier mod = idx >= expected_par.Count ? 0 : expected_par.FixedParameters[idx].ModFlags;
+
+                       string index = (idx + 1).ToString ();
+                       if (((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) ^
+                               (a.Modifier & (Parameter.Modifier.REF | Parameter.Modifier.OUT))) != 0) {
+                               if ((mod & Parameter.Modifier.ISBYREF) == 0)
+                                       ec.Report.Error (1615, loc, "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' modifier",
+                                               index, Parameter.GetModifierSignature (a.Modifier));
+                               else
+                                       ec.Report.Error (1620, loc, "Argument `#{0}' is missing `{1}' modifier",
+                                               index, Parameter.GetModifierSignature (mod));
+                       } else {
+                               string p1 = a.GetSignatureForError ();
+                               string p2 = TypeManager.CSharpName (paramType);
+
+                               if (p1 == p2) {
+                                       ec.Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous ");
+                                       ec.Report.SymbolRelatedToPreviousError (a.Expr.Type);
+                                       ec.Report.SymbolRelatedToPreviousError (paramType);
                                }
 
-                               if (has_inaccessible_candidates_only) {
-                                       if (InstanceExpression != null && type != ec.CurrentType && TypeManager.IsNestedFamilyAccessible (ec.CurrentType, best_candidate.DeclaringType)) {
-                                               // Although a derived class can access protected members of
-                                               // its base class it cannot do so through an instance of the
-                                               // base class (CS1540).  If the qualifier_type is a base of the
-                                               // ec.CurrentType and the lookup succeeds with the latter one,
-                                               // then we are in this situation.
-                                               Error_CannotAccessProtected (ec, loc, best_candidate, queried_type, ec.CurrentType);
-                                       } else {
-                                               ec.Report.SymbolRelatedToPreviousError (best_candidate);
-                                               ErrorIsInaccesible (loc, GetSignatureForError (), ec.Report);
+                               ec.Report.Error (1503, loc,
+                                       "Argument `#{0}' cannot convert `{1}' expression to type `{2}'", index, p1, p2);
+                       }
+               }
+
+               //
+               // We have failed to find exact match so we return error info about the closest match
+               //
+               void ReportOverloadError (ResolveContext rc, MemberSpec best_candidate, Arguments args, bool params_expanded)
+               {
+                       int ta_count = type_arguments == null ? 0 : type_arguments.Count;
+                       int arg_count = args == null ? 0 : args.Count;
+
+                       if (ta_count != best_candidate.Arity && (ta_count > 0 || ((IParametersMember) best_candidate).Parameters.IsEmpty)) {
+                               var mg = new MethodGroupExpr (new [] { best_candidate }, best_candidate.DeclaringType, loc);
+                               mg.Error_TypeArgumentsCannotBeUsed (rc.Report, loc, best_candidate, ta_count);
+                               return;
+                       }
+
+                       if (lambda_conv_msgs != null) {
+                               if (lambda_conv_msgs.Merge (rc.Report.Printer))
+                                       return;
+                       }
+
+                       //
+                       // For candidates which match on parameters count report more details about incorrect arguments
+                       //
+                       var pm = best_candidate as IParametersMember;
+                       if (pm != null) {
+                               int unexpanded_count = pm.Parameters.HasParams ? pm.Parameters.Count - 1 : pm.Parameters.Count;
+                               if (pm.Parameters.Count == arg_count || params_expanded || unexpanded_count == arg_count) {
+                                       // Reject any inaccessible member
+                                       if (!best_candidate.IsAccessible (rc.CurrentType)) {
+                                               rc.Report.SymbolRelatedToPreviousError (best_candidate);
+                                               Expression.ErrorIsInaccesible (rc, best_candidate.GetSignatureForError (), loc);
+                                               return;
+                                       }
+
+                                       var ms = best_candidate as MethodSpec;
+                                       if (ms != null && ms.IsGeneric) {
+                                               bool constr_ok = true;
+                                               if (ms.TypeArguments != null)
+                                                       constr_ok = new ConstraintChecker (rc.MemberContext).CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc);
+
+                                               if (ta_count == 0) {
+                                                       if (custom_errors != null && custom_errors.TypeInferenceFailed (rc, best_candidate))
+                                                               return;
+
+                                                       if (constr_ok) {
+                                                               rc.Report.Error (411, loc,
+                                                                       "The type arguments for method `{0}' cannot be inferred from the usage. Try specifying the type arguments explicitly",
+                                                                       ms.GetGenericMethodDefinition ().GetSignatureForError ());
+                                                       }
+
+                                                       return;
+                                               }
                                        }
+
+                                       VerifyArguments (rc, ref args, best_candidate, params_expanded);
+                                       return;
                                }
+                       }
 
-                               if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, params_expanded, false, loc))
-                                       return true;
+                       //
+                       // We failed to find any method with correct argument count, report best candidate
+                       //
+                       if (custom_errors != null && custom_errors.NoArgumentMatch (rc, best_candidate))
+                               return;
 
-                               if (has_inaccessible_candidates_only)
-                                       return true;
+                       if (best_candidate.Kind == MemberKind.Constructor) {
+                               rc.Report.SymbolRelatedToPreviousError (best_candidate);
+                               Error_ConstructorMismatch (rc, best_candidate.DeclaringType, arg_count, loc);
+                       } else if (IsDelegateInvoke) {
+                               rc.Report.SymbolRelatedToPreviousError (DelegateType);
+                               rc.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",
+                                       DelegateType.GetSignatureForError (), arg_count.ToString ());
+                       } else {
+                               string name = best_candidate.Kind == MemberKind.Indexer ? "this" : best_candidate.Name;
+                               rc.Report.SymbolRelatedToPreviousError (best_candidate);
+                               rc.Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments",
+                                       name, arg_count.ToString ());
                        }
-
-                       return false;
-               }
-               
-               public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
-               {
-                       type_arguments = ta;
                }
 
-               public bool VerifyArgumentsCompat (ResolveContext ec, ref Arguments arguments,
-                                                         int arg_count, MethodSpec method,
-                                                         bool chose_params_expanded,
-                                                         bool may_fail, Location loc)
+               bool VerifyArguments (ResolveContext ec, ref Arguments args, MemberSpec member, bool chose_params_expanded)
                {
-                       AParametersCollection pd = method.Parameters;
-                       int param_count = GetApplicableParametersCount (method, pd);
+                       var pm = member as IParametersMember;
+                       var pd = pm.Parameters;
 
-                       int errors = ec.Report.Errors;
                        Parameter.Modifier p_mod = 0;
                        TypeSpec pt = null;
                        int a_idx = 0, a_pos = 0;
                        Argument a = null;
                        ArrayInitializer params_initializers = null;
-                       bool has_unsafe_arg = method.ReturnType.IsPointer;
+                       bool has_unsafe_arg = pm.MemberType.IsPointer;
+                       int arg_count = args == null ? 0 : args.Count;
 
                        for (; a_idx < arg_count; a_idx++, ++a_pos) {
-                               a = arguments [a_idx];
+                               a = args[a_idx];
                                if (p_mod != Parameter.Modifier.PARAMS) {
-                                       p_mod = pd.FixedParameters [a_idx].ModFlags;
-                                       pt = pd.Types [a_idx];
+                                       p_mod = pd.FixedParameters[a_idx].ModFlags;
+                                       pt = pd.Types[a_idx];
                                        has_unsafe_arg |= pt.IsPointer;
 
                                        if (p_mod == Parameter.Modifier.PARAMS) {
@@ -4085,44 +4239,46 @@ namespace Mono.CSharp {
                                        if ((p_mod & ~Parameter.Modifier.PARAMS) != a.Modifier)
                                                break;
 
-                                       if (!TypeManager.IsEqual (a.Expr.Type, pt))
-                                               break;
+                                       if (a.Expr.Type == pt || TypeSpecComparer.IsEqual (a.Expr.Type, pt))
+                                               continue;
 
-                                       continue;
-                               } else {
-                                       NamedArgument na = a as NamedArgument;
-                                       if (na != null) {
-                                               int name_index = pd.GetParameterIndexByName (na.Name);
-                                               if (name_index < 0 || name_index >= param_count) {
-                                                       if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType)) {
-                                                               ec.Report.SymbolRelatedToPreviousError (DeclaringType);
-                                                               ec.Report.Error (1746, na.Location,
-                                                                       "The delegate `{0}' does not contain a parameter named `{1}'",
-                                                                       TypeManager.CSharpName (DeclaringType), na.Name);
-                                                       } else {
-                                                               ec.Report.SymbolRelatedToPreviousError (best_candidate);
-                                                               ec.Report.Error (1739, na.Location,
-                                                                       "The best overloaded method match for `{0}' does not contain a parameter named `{1}'",
-                                                                       TypeManager.CSharpSignature (method), na.Name);
-                                                       }
-                                               } else if (arguments[name_index] != a) {
-                                                       if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType))
-                                                               ec.Report.SymbolRelatedToPreviousError (DeclaringType);
-                                                       else
-                                                               ec.Report.SymbolRelatedToPreviousError (best_candidate);
-
-                                                       ec.Report.Error (1744, na.Location,
-                                                               "Named argument `{0}' cannot be used for a parameter which has positional argument specified",
-                                                               na.Name);
+                                       break;
+                               }
+
+                               NamedArgument na = a as NamedArgument;
+                               if (na != null) {
+                                       int name_index = pd.GetParameterIndexByName (na.Name);
+                                       if (name_index < 0 || name_index >= pd.Count) {
+                                               if (IsDelegateInvoke) {
+                                                       ec.Report.SymbolRelatedToPreviousError (DelegateType);
+                                                       ec.Report.Error (1746, na.Location,
+                                                               "The delegate `{0}' does not contain a parameter named `{1}'",
+                                                               DelegateType.GetSignatureForError (), na.Name);
+                                               } else {
+                                                       ec.Report.SymbolRelatedToPreviousError (member);
+                                                       ec.Report.Error (1739, na.Location,
+                                                               "The best overloaded method match for `{0}' does not contain a parameter named `{1}'",
+                                                               TypeManager.CSharpSignature (member), na.Name);
                                                }
+                                       } else if (args[name_index] != a) {
+                                               if (IsDelegateInvoke)
+                                                       ec.Report.SymbolRelatedToPreviousError (DelegateType);
+                                               else
+                                                       ec.Report.SymbolRelatedToPreviousError (member);
+
+                                               ec.Report.Error (1744, na.Location,
+                                                       "Named argument `{0}' cannot be used for a parameter which has positional argument specified",
+                                                       na.Name);
                                        }
                                }
-
+                               
                                if (a.Expr.Type == InternalType.Dynamic)
                                        continue;
 
-                               if (delegate_type != null && !Delegate.IsTypeCovariant (a.Expr, pt))
-                                       break;
+                               if ((restrictions & Restrictions.CovariantDelegate) != 0 && !Delegate.IsTypeCovariant (a.Expr, pt)) {
+                                       custom_errors.NoArgumentMatch (ec, member);
+                                       return false;
+                               }
 
                                Expression conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc);
                                if (conv == null)
@@ -4135,7 +4291,7 @@ namespace Mono.CSharp {
                                        // we choose to use 'a.Expr' rather than 'conv' so that
                                        // we don't hide the kind of expression we have (esp. CompoundAssign.Helper)
                                        params_initializers.Add (a.Expr);
-                                       arguments.RemoveAt (a_idx--);
+                                       args.RemoveAt (a_idx--);
                                        --arg_count;
                                        continue;
                                }
@@ -4145,23 +4301,18 @@ namespace Mono.CSharp {
                        }
 
                        if (a_idx != arg_count) {
-                               if (!may_fail && ec.Report.Errors == errors) {
-                                       if (CustomErrorHandler != null)
-                                               CustomErrorHandler.NoExactMatch (ec, best_candidate);
-                                       else
-                                               Error_InvalidArguments (ec, loc, a_pos, method, a, pd, pt);
-                               }
+                               ReportArgumentMismatch (ec, a_pos, member, a, pd, pt);
                                return false;
                        }
 
                        //
                        // Fill not provided arguments required by params modifier
                        //
-                       if (params_initializers == null && pd.HasParams && arg_count + 1 == param_count) {
-                               if (arguments == null)
-                                       arguments = new Arguments (1);
+                       if (params_initializers == null && pd.HasParams && arg_count + 1 == pd.Count) {
+                               if (args == null)
+                                       args = new Arguments (1);
 
-                               pt = pd.Types [param_count - 1];
+                               pt = pd.Types[pd.Count - 1];
                                pt = TypeManager.GetElementType (pt);
                                has_unsafe_arg |= pt.IsPointer;
                                params_initializers = new ArrayInitializer (0, loc);
@@ -4171,21 +4322,27 @@ namespace Mono.CSharp {
                        // Append an array argument with all params arguments
                        //
                        if (params_initializers != null) {
-                               arguments.Add (new Argument (
-                                       new ArrayCreation (new TypeExpression (pt, loc), "[]", params_initializers, loc).Resolve (ec)));
+                               args.Add (new Argument (
+                                       new ArrayCreation (new TypeExpression (pt, loc), params_initializers, loc).Resolve (ec)));
                                arg_count++;
                        }
 
-                       if (arg_count < param_count) {
-                               if (!may_fail)
-                                       Error_ArgumentCountWrong (ec, arg_count);
-                               return false;
+                       if (has_unsafe_arg && !ec.IsUnsafe) {
+                               Expression.UnsafeError (ec, loc);
                        }
 
-                       if (has_unsafe_arg && !ec.IsUnsafe) {
-                               if (!may_fail)
-                                       UnsafeError (ec, loc);
-                               return false;
+                       //
+                       // We could infer inaccesible type arguments
+                       //
+                       if (type_arguments == null && member.IsGeneric) {
+                               var ms = (MethodSpec) member;
+                               foreach (var ta in ms.TypeArguments) {
+                                       if (!ta.IsAccessible (ec.CurrentType)) {
+                                               ec.Report.SymbolRelatedToPreviousError (ta);
+                                               Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
+                                               break;
+                                       }
+                               }
                        }
 
                        return true;
@@ -4214,7 +4371,7 @@ namespace Mono.CSharp {
                        get { return true; }
                }
 
-               public override TypeSpec DeclaringType {
+               protected override TypeSpec DeclaringType {
                        get { return constant.DeclaringType; }
                }
 
@@ -4225,16 +4382,10 @@ namespace Mono.CSharp {
 
                protected override Expression DoResolve (ResolveContext rc)
                {
-                       constant.MemberDefinition.SetIsUsed ();
+                       ResolveInstanceExpression (rc);
+                       DoBestMemberChecks (rc, constant);
 
-                       if (!rc.IsObsolete) {
-                               var oa = constant.GetAttributeObsolete ();
-                               if (oa != null)
-                                       AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (constant), loc, rc.Report);
-                       }
-
-                       // Constants are resolved on-demand
-                       var c = constant.Value.Resolve (rc) as Constant;
+                       var c = constant.GetConstant (rc);
 
                        // Creates reference expression to the constant value
                        return Constant.CreateConstant (rc, constant.MemberType, c.GetValue (), loc);
@@ -4247,7 +4398,12 @@ namespace Mono.CSharp {
 
                public override string GetSignatureForError ()
                {
-                       return TypeManager.GetFullNameSignature (constant);
+                       return constant.GetSignatureForError ();
+               }
+
+               public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
+               {
+                       Error_TypeArgumentsCannotBeUsed (ec.Report, "constant", GetSignatureForError (), loc);
                }
        }
 
@@ -4277,15 +4433,23 @@ namespace Mono.CSharp {
                public FieldExpr (FieldBase fi, Location l)
                        : this (fi.Spec, l)
                {
-                       loc = l;
                }
 
+#region Properties
+
                public override string Name {
                        get {
                                return spec.Name;
                        }
                }
 
+               public bool IsHoisted {
+                       get {
+                               IVariableReference hv = InstanceExpression as IVariableReference;
+                               return hv != null && hv.IsHoisted;
+                       }
+               }
+
                public override bool IsInstance {
                        get {
                                return !spec.IsStatic;
@@ -4304,31 +4468,31 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override TypeSpec DeclaringType {
+               protected override TypeSpec DeclaringType {
                        get {
                                return spec.DeclaringType;
                        }
                }
 
-               public override string GetSignatureForError ()
-               {
-                       return TypeManager.GetFullNameSignature (spec);
-               }
-
                public VariableInfo VariableInfo {
                        get {
                                return variable_info;
                        }
                }
 
-               public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
-                                                               SimpleName original)
+#endregion
+
+               public override string GetSignatureForError ()
                {
-                       if (spec.MemberType.IsPointer && !ec.IsUnsafe) {
-                               UnsafeError (ec, loc);
-                       }
+                       return TypeManager.GetFullNameSignature (spec);
+               }
 
-                       return base.ResolveMemberAccess (ec, left, loc, original);
+               public bool IsMarshalByRefAccess ()
+               {
+                       // Checks possible ldflda of field access expression
+                       return !spec.IsStatic && TypeManager.IsValueType (spec.MemberType) &&
+                               TypeSpec.IsBaseClass (spec.DeclaringType, TypeManager.mbr_type, false) &&
+                               !(InstanceExpression is This);
                }
 
                public void SetHasAddressTaken ()
@@ -4366,16 +4530,7 @@ namespace Mono.CSharp {
 
                Expression DoResolve (ResolveContext ec, bool lvalue_instance, bool out_access)
                {
-                       if (!IsStatic){
-                               if (InstanceExpression == null){
-                                       //
-                                       // This can happen when referencing an instance field using
-                                       // a fully qualified type expression: TypeName.InstanceField = xxx
-                                       // 
-                                       SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
-                                       return null;
-                               }
-
+                       if (ResolveInstanceExpression (ec)) {
                                // Resolve the field's instance expression while flow analysis is turned
                                // off: when accessing a field "a.b", we must check whether the field
                                // "a.b" is initialized, not whether the whole struct "a" is initialized.
@@ -4385,14 +4540,11 @@ namespace Mono.CSharp {
                                                Expression right_side =
                                                        out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
 
-                                               if (InstanceExpression != EmptyExpression.Null)
-                                                       InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
+                                               InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
                                        }
                                } else {
-                                       if (InstanceExpression != EmptyExpression.Null) {
-                                               using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
-                                                       InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
-                                               }
+                                       using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
+                                               InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
                                        }
                                }
 
@@ -4404,14 +4556,14 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (!ec.IsObsolete) {
-                               ObsoleteAttribute oa = spec.GetAttributeObsolete ();
-                               if (oa != null)
-                                       AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (spec), loc, ec.Report);
-                       }
+                       DoBestMemberChecks (ec, spec);
 
                        var fb = spec as FixedFieldSpec;
                        IVariableReference var = InstanceExpression as IVariableReference;
+
+                       if (lvalue_instance && var != null && var.VariableInfo != null) {
+                               var.VariableInfo.SetFieldAssigned (ec, Name);
+                       }
                        
                        if (fb != null) {
                                IFixedExpression fe = InstanceExpression as IFixedExpression;
@@ -4483,11 +4635,7 @@ namespace Mono.CSharp {
                
                override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
                {
-                       IVariableReference var = InstanceExpression as IVariableReference;
-                       if (var != null && var.VariableInfo != null)
-                               var.VariableInfo.SetFieldAssigned (ec, Name);
-
-                       bool lvalue_instance = !spec.IsStatic && TypeManager.IsValueType (spec.DeclaringType);
+                       bool lvalue_instance = IsInstance && spec.DeclaringType.IsStruct;
                        bool out_access = right_side == EmptyExpression.OutAccess.Instance || right_side == EmptyExpression.LValueMemberOutAccess;
 
                        Expression e = DoResolve (ec, lvalue_instance, out_access);
@@ -4512,7 +4660,7 @@ namespace Mono.CSharp {
                                if (ec.HasSet (ResolveContext.Options.ConstructorScope)) {
 
                                        // InitOnly fields cannot be assigned-to in a different constructor from their declaring type
-                                       if (!TypeManager.IsEqual (ec.CurrentMemberDefinition.Parent.Definition, DeclaringType.GetDefinition ()))
+                                       if (ec.CurrentMemberDefinition.Parent.Definition != spec.DeclaringType.GetDefinition ())
                                                return Report_AssignToReadonly (ec, right_side);
                                        // static InitOnly fields cannot be assigned-to in an instance constructor
                                        if (IsStatic && !ec.IsStatic)
@@ -4524,8 +4672,8 @@ namespace Mono.CSharp {
                        }
 
                        if (right_side == EmptyExpression.OutAccess.Instance &&
-                           !IsStatic && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type)) {
-                               ec.Report.SymbolRelatedToPreviousError (DeclaringType);
+                               !IsStatic && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeSpec.IsBaseClass (spec.DeclaringType, TypeManager.mbr_type, false)) {
+                               ec.Report.SymbolRelatedToPreviousError (spec.DeclaringType);
                                ec.Report.Warning (197, 1, loc,
                                                "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",
                                                GetSignatureForError ());
@@ -4535,20 +4683,6 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               bool is_marshal_by_ref ()
-               {
-                       return !IsStatic && TypeManager.IsStruct (Type) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type);
-               }
-
-               public override void CheckMarshalByRefAccess (ResolveContext ec)
-               {
-                       if (is_marshal_by_ref () && !(InstanceExpression is This)) {
-                               ec.Report.SymbolRelatedToPreviousError (DeclaringType);
-                               ec.Report.Warning (1690, 1, loc, "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
-                                               GetSignatureForError ());
-                       }
-               }
-
                public override int GetHashCode ()
                {
                        return spec.GetHashCode ();
@@ -4568,13 +4702,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               public bool IsHoisted {
-                       get {
-                               IVariableReference hv = InstanceExpression as IVariableReference;
-                               return hv != null && hv.IsHoisted;
-                       }
-               }
-
                public override bool Equals (object obj)
                {
                        FieldExpr fe = obj as FieldExpr;
@@ -4609,7 +4736,7 @@ namespace Mono.CSharp {
                                        EmitInstance (ec, false);
 
                                // Optimization for build-in types
-                               if (TypeManager.IsStruct (type) && TypeManager.IsEqual (type, ec.MemberContext.CurrentType) && TypeManager.IsEqual (InstanceExpression.Type, type)) {
+                               if (TypeManager.IsStruct (type) && type == ec.MemberContext.CurrentType && InstanceExpression.Type == type) {
                                        ec.EmitLoadFromPtr (type);
                                } else {
                                        var ff = spec as FixedFieldSpec;
@@ -4636,8 +4763,9 @@ namespace Mono.CSharp {
 
                public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
-                       prepared = prepare_for_load;
-                       EmitInstance (ec, prepared);
+                       prepared = prepare_for_load && !(source is DynamicExpressionStatement);
+                       if (IsInstance)
+                               EmitInstance (ec, prepared);
 
                        source.Emit (ec);
                        if (leave_copy) {
@@ -4674,17 +4802,10 @@ namespace Mono.CSharp {
                {
                        bool is_volatile = (spec.Modifiers & Modifiers.VOLATILE) != 0;
 
-                       if (is_volatile || is_marshal_by_ref ())
+                       if (is_volatile) // || is_marshal_by_ref ())
                                base.EmitSideEffect (ec);
                }
 
-               public override void Error_VariableIsUsedBeforeItIsDeclared (Report r, string name)
-               {
-                       r.Error (844, loc,
-                               "A local variable `{0}' cannot be used before it is declared. Consider renaming the local variable when it hides the field `{1}'",
-                               name, GetSignatureForError ());
-               }
-
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        if ((mode & AddressOp.Store) != 0)
@@ -4728,7 +4849,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public SLE.Expression MakeAssignExpression (BuilderContext ctx)
+               public SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source)
                {
                        return MakeExpression (ctx);
                }
@@ -4737,6 +4858,11 @@ namespace Mono.CSharp {
                {
                        return SLE.Expression.Field (InstanceExpression.MakeExpression (ctx), spec.GetMetaInfo ());
                }
+
+               public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
+               {
+                       Error_TypeArgumentsCannotBeUsed (ec.Report, "field", GetSignatureForError (), loc);
+               }
        }
 
        
@@ -4747,27 +4873,26 @@ namespace Mono.CSharp {
        ///   This is not an LValue because we need to re-write the expression, we
        ///   can not take data from the stack and store it.  
        /// </summary>
-       public class PropertyExpr : MemberExpr, IDynamicAssign
+       class PropertyExpr : PropertyOrIndexerExpr<PropertySpec>
        {
-               PropertySpec spec;
-               TypeArguments targs;
-               
-               LocalTemporary temp;
-               bool prepared;
-
-               public PropertyExpr (TypeSpec container_type, PropertySpec spec, Location l)
+               public PropertyExpr (PropertySpec spec, Location l)
+                       : base (l)
                {
-                       this.spec = spec;
-                       loc = l;
-
+                       best_candidate = spec;
                        type = spec.MemberType;
                }
 
                #region Properties
 
+               protected override TypeSpec DeclaringType {
+                       get {
+                               return best_candidate.DeclaringType;
+                       }
+               }
+
                public override string Name {
                        get {
-                               return spec.Name;
+                               return best_candidate.Name;
                        }
                }
 
@@ -4779,7 +4904,13 @@ namespace Mono.CSharp {
 
                public override bool IsStatic {
                        get {
-                               return spec.IsStatic;
+                               return best_candidate.IsStatic;
+                       }
+               }
+
+               public PropertySpec PropertyInfo {
+                       get {
+                               return best_candidate;
                        }
                }
 
@@ -4794,238 +4925,52 @@ namespace Mono.CSharp {
                                return CreateExpressionFactoryCall (ec, "ArrayLength", args);
                        }
 
-                       if (is_base) {
-                               Error_BaseAccessInExpressionTree (ec, loc);
-                               return null;
-                       }
-
                        args = new Arguments (2);
                        if (InstanceExpression == null)
                                args.Add (new Argument (new NullLiteral (loc)));
                        else
                                args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
-                       args.Add (new Argument (new TypeOfMethod (spec.Get, loc)));
+                       args.Add (new Argument (new TypeOfMethod (Getter, loc)));
                        return CreateExpressionFactoryCall (ec, "Property", args);
                }
 
                public Expression CreateSetterTypeOfExpression ()
                {
-                       return new TypeOfMethod (spec.Set, loc);
-               }
-
-               public override TypeSpec DeclaringType {
-                       get {
-                               return spec.DeclaringType;
-                       }
+                       return new TypeOfMethod (Setter, loc);
                }
 
                public override string GetSignatureForError ()
                {
-                       return TypeManager.GetFullNameSignature (spec);
+                       return best_candidate.GetSignatureForError ();
                }
 
-               public SLE.Expression MakeAssignExpression (BuilderContext ctx)
+               public override SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source)
                {
-                       return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) spec.Set.GetMetaInfo ());
+                       return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) Setter.GetMetaInfo ());
                }
 
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
-                       return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) spec.Get.GetMetaInfo ());
-               }
-
-               public PropertySpec PropertyInfo {
-                       get {
-                               return spec;
-                       }
-               }
-
-               bool InstanceResolve (ResolveContext ec, bool lvalue_instance, bool must_do_cs1540_check)
-               {
-                       if (IsStatic) {
-                               InstanceExpression = null;
-                               return true;
-                       }
-
-                       if (InstanceExpression == null) {
-                               SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
-                               return false;
-                       }
-
-                       InstanceExpression = InstanceExpression.Resolve (ec);
-                       if (lvalue_instance && InstanceExpression != null)
-                               InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess);
-
-                       if (InstanceExpression == null)
-                               return false;
-
-                       InstanceExpression.CheckMarshalByRefAccess (ec);
-
-                       if (must_do_cs1540_check && (InstanceExpression != EmptyExpression.Null) &&
-                           !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.CurrentType) &&
-                           !TypeManager.IsNestedChildOf (ec.CurrentType, InstanceExpression.Type) &&
-                           !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.CurrentType)) {
-                               ec.Report.SymbolRelatedToPreviousError (spec);
-                               Error_CannotAccessProtected (ec, loc, spec, InstanceExpression.Type, ec.CurrentType);
-                               return false;
-                       }
-
-                       return true;
+                       return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) Getter.GetMetaInfo ());
                }
 
                void Error_PropertyNotValid (ResolveContext ec)
                {
-                       ec.Report.SymbolRelatedToPreviousError (spec);
+                       ec.Report.SymbolRelatedToPreviousError (best_candidate);
                        ec.Report.Error (1546, loc, "Property or event `{0}' is not supported by the C# language",
                                GetSignatureForError ());
                }
 
-               public bool IsAccessibleFrom (TypeSpec invocation_type, bool lvalue)
-               {
-                       bool dummy;
-                       var accessor = lvalue ? spec.Set : spec.Get;
-                       if (accessor == null && lvalue)
-                               accessor = spec.Get;
-                       return accessor != null && IsMemberAccessible (invocation_type, accessor, out dummy);
-               }
-
                bool IsSingleDimensionalArrayLength ()
                {
-                       if (DeclaringType != TypeManager.array_type || !spec.HasGet || Name != "Length")
+                       if (best_candidate.DeclaringType != TypeManager.array_type || !best_candidate.HasGet || Name != "Length")
                                return false;
 
                        ArrayContainer ac = InstanceExpression.Type as ArrayContainer;
                        return ac != null && ac.Rank == 1;
-               }
-
-               protected override Expression DoResolve (ResolveContext ec)
-               {
-                       eclass = ExprClass.PropertyAccess;
-
-                       bool must_do_cs1540_check = false;
-                       ec.Report.DisableReporting ();
-                       bool res = ResolveGetter (ec, ref must_do_cs1540_check);
-                       ec.Report.EnableReporting ();
-
-                       if (!res) {
-                               if (InstanceExpression != null) {
-                                       TypeSpec expr_type = InstanceExpression.Type;
-                                       ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (expr_type, Name, 0, loc);
-                                       if (ex_method_lookup != null) {
-                                               ex_method_lookup.ExtensionExpression = InstanceExpression;
-                                               ex_method_lookup.SetTypeArguments (ec, targs);
-                                               return ex_method_lookup.Resolve (ec);
-                                       }
-                               }
-
-                               ResolveGetter (ec, ref must_do_cs1540_check);
-                               return null;
-                       }
-
-                       if (!InstanceResolve (ec, false, must_do_cs1540_check))
-                               return null;
-
-                       //
-                       // Only base will allow this invocation to happen.
-                       //
-                       if (IsBase && spec.IsAbstract) {
-                               Error_CannotCallAbstractBase (ec, TypeManager.GetFullNameSignature (spec));
-                       }
-
-                       if (spec.MemberType.IsPointer && !ec.IsUnsafe){
-                               UnsafeError (ec, loc);
-                       }
-
-                       if (!ec.IsObsolete) {
-                               ObsoleteAttribute oa = spec.GetAttributeObsolete ();
-                               if (oa != null)
-                                       AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
-                       }
-
-                       return this;
-               }
-
-               override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
-               {
-                       eclass = ExprClass.PropertyAccess;
-
-                       if (right_side == EmptyExpression.OutAccess.Instance) {
-                               if (ec.CurrentBlock.Toplevel.GetParameterReference (spec.Name, loc) is MemberAccess) {
-                                       ec.Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter",
-                                           spec.Name);
-                               } else {
-                                       right_side.DoResolveLValue (ec, this);
-                               }
-                               return null;
-                       }
-
-                       if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) {
-                               Error_CannotModifyIntermediateExpressionValue (ec);
-                       }
-
-                       if (spec.IsNotRealProperty) {
-                               Error_PropertyNotValid (ec);
-                               return null;
-                       }
-
-                       if (!spec.HasSet){
-                               if (ec.CurrentBlock.Toplevel.GetParameterReference (spec.Name, loc) is MemberAccess) {
-                                       ec.Report.Error (1947, loc, "A range variable `{0}' cannot be assigned to. Consider using `let' clause to store the value",
-                                               spec.Name);
-                               } else {
-                                       ec.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read only)",
-                                               GetSignatureForError ());
-                               }
-                               return null;
-                       }
-
-                       if (targs != null) {
-                               base.SetTypeArguments (ec, targs);
-                               return null;
-                       }
-
-                       bool must_do_cs1540_check;
-                       if (!IsMemberAccessible (ec.CurrentType, spec.Set, out must_do_cs1540_check)) {
-                               if (spec.HasDifferentAccessibility) {
-                                       ec.Report.SymbolRelatedToPreviousError (spec.Set);
-                                       ec.Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
-                                               TypeManager.CSharpSignature (spec));
-                               } else {
-                                       ec.Report.SymbolRelatedToPreviousError (spec.Set);
-                                       ErrorIsInaccesible (loc, TypeManager.CSharpSignature (spec.Set), ec.Report);
-                               }
-                               return null;
-                       }
-                       
-                       if (!InstanceResolve (ec, TypeManager.IsStruct (spec.DeclaringType), must_do_cs1540_check))
-                               return null;
-                       
-                       //
-                       // Only base will allow this invocation to happen.
-                       //
-                       if (IsBase && spec.IsAbstract){
-                               Error_CannotCallAbstractBase (ec, TypeManager.GetFullNameSignature (spec));
-                       }
-
-                       if (spec.MemberType.IsPointer && !ec.IsUnsafe) {
-                               UnsafeError (ec, loc);
-                       }
-
-                       if (!ec.IsObsolete) {
-                               ObsoleteAttribute oa = spec.GetAttributeObsolete ();
-                               if (oa != null)
-                                       AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
-                       }
-
-                       return this;
-               }
-               
-               public override void Emit (EmitContext ec)
-               {
-                       Emit (ec, false);
-               }
-               
-               public void Emit (EmitContext ec, bool leave_copy)
+               }
+
+               public override void Emit (EmitContext ec, bool leave_copy)
                {
                        //
                        // Special case: length of single dimension array property is turned into ldlen
@@ -5038,7 +4983,7 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       Invocation.EmitCall (ec, IsBase, InstanceExpression, spec.Get, null, loc, prepared, false);
+                       Invocation.EmitCall (ec, InstanceExpression, Getter, null, loc, prepared, false);
                        
                        if (leave_copy) {
                                ec.Emit (OpCodes.Dup);
@@ -5049,14 +4994,12 @@ namespace Mono.CSharp {
                        }
                }
 
-               //
-               // Implements the IAssignMethod interface for assignments
-               //
-               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+               public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
-                       Expression my_source = source;
+                       Arguments args;
 
-                       if (prepare_for_load) {
+                       if (prepare_for_load && !(source is DynamicExpressionStatement)) {
+                               args = new Arguments (0);
                                prepared = true;
                                source.Emit (ec);
                                
@@ -5067,17 +5010,20 @@ namespace Mono.CSharp {
                                                temp.Store (ec);
                                        }
                                }
-                       } else if (leave_copy) {
-                               source.Emit (ec);
-                               temp = new LocalTemporary (this.Type);
-                               temp.Store (ec);
-                               my_source = temp;
+                       } else {
+                               args = new Arguments (1);
+
+                               if (leave_copy) {
+                                       source.Emit (ec);
+                                       temp = new LocalTemporary (this.Type);
+                                       temp.Store (ec);
+                                       args.Add (new Argument (temp));
+                               } else {
+                                       args.Add (new Argument (source));
+                               }
                        }
 
-                       Arguments args = new Arguments (1);
-                       args.Add (new Argument (my_source));
-                       
-                       Invocation.EmitCall (ec, IsBase, InstanceExpression, spec.Set, args, loc, false, prepared);
+                       Invocation.EmitCall (ec, InstanceExpression, Setter, args, loc, false, prepared);
                        
                        if (temp != null) {
                                temp.Emit (ec);
@@ -5085,55 +5031,196 @@ namespace Mono.CSharp {
                        }
                }
 
-               bool ResolveGetter (ResolveContext ec, ref bool must_do_cs1540_check)
+               protected override Expression OverloadResolve (ResolveContext rc, Expression right_side)
                {
-                       if (targs != null) {
-                               base.SetTypeArguments (ec, targs);
-                               return false;
+                       eclass = ExprClass.PropertyAccess;
+
+                       if (best_candidate.IsNotRealProperty) {
+                               Error_PropertyNotValid (rc);
                        }
 
-                       if (spec.IsNotRealProperty) {
-                               Error_PropertyNotValid (ec);
-                               return false;
+                       if (ResolveInstanceExpression (rc)) {
+                               if (right_side != null && best_candidate.DeclaringType.IsStruct)
+                                       InstanceExpression.DoResolveLValue (rc, EmptyExpression.LValueMemberAccess);
                        }
 
-                       if (!spec.HasGet) {
-                               if (InstanceExpression != EmptyExpression.Null) {
-                                       ec.Report.SymbolRelatedToPreviousError (spec);
-                                       ec.Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
-                                               spec.GetSignatureForError ());
-                                       return false;
+                       DoBestMemberChecks (rc, best_candidate);
+                       return this;
+               }
+
+               public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
+               {
+                       Error_TypeArgumentsCannotBeUsed (ec.Report, "property", GetSignatureForError (), loc);
+               }
+       }
+
+       abstract class PropertyOrIndexerExpr<T> : MemberExpr, IDynamicAssign where T : PropertySpec
+       {
+               // getter and setter can be different for base calls
+               MethodSpec getter, setter;
+               protected T best_candidate;
+
+               protected LocalTemporary temp;
+               protected bool prepared;
+
+               protected PropertyOrIndexerExpr (Location l)
+               {
+                       loc = l;
+               }
+
+               #region Properties
+
+               public MethodSpec Getter {
+                       get {
+                               return getter;
+                       }
+                       set {
+                               getter = value;
+                       }
+               }
+
+               public MethodSpec Setter {
+                       get {
+                               return setter;
+                       }
+                       set {
+                               setter = value;
+                       }
+               }
+
+               #endregion
+
+               protected override Expression DoResolve (ResolveContext ec)
+               {
+                       if (eclass == ExprClass.Unresolved) {
+                               var expr = OverloadResolve (ec, null);
+                               if (expr == null)
+                                       return null;
+
+                               if (InstanceExpression != null)
+                                       InstanceExpression.CheckMarshalByRefAccess (ec);
+
+                               if (expr != this)
+                                       return expr.Resolve (ec);
+                       }
+
+                       if (!ResolveGetter (ec))
+                               return null;
+
+                       return this;
+               }
+
+               public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
+               {
+                       if (right_side == EmptyExpression.OutAccess.Instance) {
+                               // TODO: best_candidate can be null at this point
+                               INamedBlockVariable variable = null;
+                               if (best_candidate != null && ec.CurrentBlock.ParametersBlock.TopBlock.GetLocalName (best_candidate.Name, ec.CurrentBlock, ref variable) && variable is Linq.RangeVariable) {
+                                       ec.Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter",
+                                               best_candidate.Name);
+                               } else {
+                                       right_side.DoResolveLValue (ec, this);
                                }
+                               return null;
+                       }
+
+                       // if the property/indexer returns a value type, and we try to set a field in it
+                       if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) {
+                               Error_CannotModifyIntermediateExpressionValue (ec);
+                       }
+
+                       if (eclass == ExprClass.Unresolved) {
+                               var expr = OverloadResolve (ec, right_side);
+                               if (expr == null)
+                                       return null;
+
+                               if (expr != this)
+                                       return expr.ResolveLValue (ec, right_side);
                        }
 
-                       if (spec.HasGet && !IsMemberAccessible (ec.CurrentType, spec.Get, out must_do_cs1540_check)) {
-                               if (spec.HasDifferentAccessibility) {
-                                       ec.Report.SymbolRelatedToPreviousError (spec.Get);
-                                       ec.Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
-                                               TypeManager.CSharpSignature (spec));
+                       if (!ResolveSetter (ec))
+                               return null;
+
+                       return this;
+               }
+
+               //
+               // Implements the IAssignMethod interface for assignments
+               //
+               public abstract void Emit (EmitContext ec, bool leave_copy);
+               public abstract void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load);
+
+               public override void Emit (EmitContext ec)
+               {
+                       Emit (ec, false);
+               }
+
+               public abstract SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source);
+
+               protected abstract Expression OverloadResolve (ResolveContext rc, Expression right_side);
+
+               bool ResolveGetter (ResolveContext rc)
+               {
+                       if (!best_candidate.HasGet) {
+                               if (InstanceExpression != EmptyExpression.Null) {
+                                       rc.Report.SymbolRelatedToPreviousError (best_candidate);
+                                       rc.Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
+                                               best_candidate.GetSignatureForError ());
+                                       return false;
+                               }
+                       } else if (!best_candidate.Get.IsAccessible (rc.CurrentType)) {
+                               if (best_candidate.HasDifferentAccessibility) {
+                                       rc.Report.SymbolRelatedToPreviousError (best_candidate.Get);
+                                       rc.Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
+                                               TypeManager.CSharpSignature (best_candidate));
                                } else {
-                                       ec.Report.SymbolRelatedToPreviousError (spec.Get);
-                                       ErrorIsInaccesible (loc, TypeManager.CSharpSignature (spec.Get), ec.Report);
+                                       rc.Report.SymbolRelatedToPreviousError (best_candidate.Get);
+                                       ErrorIsInaccesible (rc, best_candidate.Get.GetSignatureForError (), loc);
                                }
+                       }
 
-                               return false;
+                       if (best_candidate.HasDifferentAccessibility) {
+                               CheckProtectedMemberAccess (rc, best_candidate.Get);
                        }
 
+                       getter = CandidateToBaseOverride (rc, best_candidate.Get);
                        return true;
                }
 
-               public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
+               bool ResolveSetter (ResolveContext rc)
                {
-                       targs = ta;
+                       if (!best_candidate.HasSet) {
+                               rc.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read-only)",
+                                       GetSignatureForError ());
+                               return false;
+                       }
+
+                       if (!best_candidate.Set.IsAccessible (rc.CurrentType)) {
+                               if (best_candidate.HasDifferentAccessibility) {
+                                       rc.Report.SymbolRelatedToPreviousError (best_candidate.Set);
+                                       rc.Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
+                                               GetSignatureForError ());
+                               } else {
+                                       rc.Report.SymbolRelatedToPreviousError (best_candidate.Set);
+                                       ErrorIsInaccesible (rc, best_candidate.Set.GetSignatureForError (), loc);
+                               }
+                       }
+
+                       if (best_candidate.HasDifferentAccessibility)
+                               CheckProtectedMemberAccess (rc, best_candidate.Set);
+
+                       setter = CandidateToBaseOverride (rc, best_candidate.Set);
+                       return true;
                }
        }
 
        /// <summary>
        ///   Fully resolved expression that evaluates to an Event
        /// </summary>
-       public class EventExpr : MemberExpr
+       public class EventExpr : MemberExpr, IAssignMethod
        {
                readonly EventSpec spec;
+               MethodSpec op;
 
                public EventExpr (EventSpec spec, Location loc)
                {
@@ -5141,6 +5228,14 @@ namespace Mono.CSharp {
                        this.loc = loc;
                }
 
+               #region Properties
+
+               protected override TypeSpec DeclaringType {
+                       get {
+                               return spec.DeclaringType;
+                       }
+               }
+
                public override string Name {
                        get {
                                return spec.Name;
@@ -5159,97 +5254,45 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override TypeSpec DeclaringType {
+               public MethodSpec Operator {
                        get {
-                               return spec.DeclaringType;
+                               return op;
                        }
                }
-               
-               public void Error_AssignmentEventOnly (ResolveContext ec)
-               {
-                       ec.Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator",
-                               GetSignatureForError ());
-               }
 
-               public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
-                                                               SimpleName original)
+               #endregion
+
+               public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original)
                {
                        //
-                       // If the event is local to this class, we transform ourselves into a FieldExpr
+                       // If the event is local to this class and we are not lhs of +=/-= we transform ourselves into a FieldExpr
                        //
+                       if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) {
+                               if (spec.BackingField != null &&
+                                       (spec.DeclaringType == ec.CurrentType || TypeManager.IsNestedChildOf (ec.CurrentType, spec.DeclaringType))) {
 
-                       if (spec.DeclaringType == ec.CurrentType ||
-                           TypeManager.IsNestedChildOf(ec.CurrentType, spec.DeclaringType)) {
-                                       
-                               // TODO: Breaks dynamic binder as currect context fields are imported and not compiled
-                               EventField mi = spec.MemberDefinition as EventField;
+                                       spec.MemberDefinition.SetIsUsed ();
 
-                               if (mi != null && mi.HasBackingField) {
-                                       mi.SetIsUsed ();
-                                       if (!ec.IsObsolete)
-                                               mi.CheckObsoleteness (loc);
+                                       if (!ec.IsObsolete) {
+                                               ObsoleteAttribute oa = spec.GetAttributeObsolete ();
+                                               if (oa != null)
+                                                       AttributeTester.Report_ObsoleteMessage (oa, spec.GetSignatureForError (), loc, ec.Report);
+                                       }
 
-                                       if ((mi.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0 && !ec.HasSet (ResolveContext.Options.CompoundAssignmentScope))
+                                       if ((spec.Modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
                                                Error_AssignmentEventOnly (ec);
-                                       
-                                       FieldExpr ml = new FieldExpr (mi.BackingField, loc);
+
+                                       FieldExpr ml = new FieldExpr (spec.BackingField, loc);
 
                                        InstanceExpression = null;
-                               
-                                       return ml.ResolveMemberAccess (ec, left, loc, original);
+
+                                       return ml.ResolveMemberAccess (ec, left, original);
                                }
-                       }
 
-                       if (left is This && !ec.HasSet (ResolveContext.Options.CompoundAssignmentScope))                        
                                Error_AssignmentEventOnly (ec);
-
-                       return base.ResolveMemberAccess (ec, left, loc, original);
-               }
-
-               bool InstanceResolve (ResolveContext ec, bool must_do_cs1540_check)
-               {
-                       if (IsStatic) {
-                               InstanceExpression = null;
-                               return true;
-                       }
-
-                       if (InstanceExpression == null) {
-                               SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
-                               return false;
-                       }
-
-                       InstanceExpression = InstanceExpression.Resolve (ec);
-                       if (InstanceExpression == null)
-                               return false;
-
-                       if (IsBase && spec.IsAbstract) {
-                               Error_CannotCallAbstractBase (ec, TypeManager.CSharpSignature(spec));
-                               return false;
-                       }
-
-                       //
-                       // This is using the same mechanism as the CS1540 check in PropertyExpr.
-                       // However, in the Event case, we reported a CS0122 instead.
-                       //
-                       // TODO: Exact copy from PropertyExpr
-                       //
-                       if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
-                           !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.CurrentType) &&
-                           !TypeManager.IsNestedChildOf (ec.CurrentType, InstanceExpression.Type) &&
-                           !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.CurrentType)) {
-                               ec.Report.SymbolRelatedToPreviousError (spec);
-                               ErrorIsInaccesible (loc, TypeManager.CSharpSignature (spec), ec.Report);
-                               return false;
                        }
 
-                       return true;
-               }
-
-               public bool IsAccessibleFrom (TypeSpec invocation_type)
-               {
-                       bool dummy;
-                       return IsMemberAccessible (invocation_type, spec.AccessorAdd, out dummy) &&
-                               IsMemberAccessible (invocation_type, spec.AccessorRemove, out dummy);
+                       return base.ResolveMemberAccess (ec, left, original);
                }
 
                public override Expression CreateExpressionTree (ResolveContext ec)
@@ -5259,40 +5302,33 @@ namespace Mono.CSharp {
 
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
                {
-                       // contexts where an LValue is valid have already devolved to FieldExprs
-                       Error_CannotAssign (ec);
-                       return null;
+                       if (right_side == EmptyExpression.EventAddition) {
+                               op = spec.AccessorAdd;
+                       } else if (right_side == EmptyExpression.EventSubtraction) {
+                               op = spec.AccessorRemove;
+                       }
+
+                       if (op == null) {
+                               Error_AssignmentEventOnly (ec);
+                               return null;
+                       }
+
+                       op = CandidateToBaseOverride (ec, op);
+                       return this;
                }
 
                protected override Expression DoResolve (ResolveContext ec)
                {
                        eclass = ExprClass.EventAccess;
+                       type = spec.MemberType;
 
-                       bool must_do_cs1540_check;
-                       if (!(IsMemberAccessible (ec.CurrentType, spec.AccessorAdd, out must_do_cs1540_check) &&
-                             IsMemberAccessible (ec.CurrentType, spec.AccessorRemove, out must_do_cs1540_check))) {
-                               ec.Report.SymbolRelatedToPreviousError (spec);
-                               ErrorIsInaccesible (loc, TypeManager.CSharpSignature (spec), ec.Report);
-                               return null;
-                       }
-
-                       if (!InstanceResolve (ec, must_do_cs1540_check))
-                               return null;
+                       ResolveInstanceExpression (ec);
 
                        if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) {
                                Error_CannotAssign (ec);
-                               return null;
-                       }
-
-                       if (!ec.IsObsolete) {
-                               var oa = spec.GetAttributeObsolete ();
-                               if (oa != null)
-                                       AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
                        }
 
-                       spec.MemberDefinition.SetIsUsed ();
-                       type = spec.MemberType;
-                       
+                       DoBestMemberChecks (ec, spec);
                        return this;
                }               
 
@@ -5302,6 +5338,31 @@ namespace Mono.CSharp {
                        //Error_CannotAssign ();
                }
 
+               #region IAssignMethod Members
+
+               public void Emit (EmitContext ec, bool leave_copy)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+               {
+                       if (leave_copy || !prepare_for_load)
+                               throw new NotImplementedException ("EventExpr::EmitAssign");
+
+                       Arguments args = new Arguments (1);
+                       args.Add (new Argument (source));
+                       Invocation.EmitCall (ec, InstanceExpression, op, args, loc);
+               }
+
+               #endregion
+
+               void Error_AssignmentEventOnly (ResolveContext ec)
+               {
+                       ec.Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator",
+                               GetSignatureForError ());
+               }
+
                public void Error_CannotAssign (ResolveContext ec)
                {
                        ec.Report.Error (70, loc,
@@ -5309,31 +5370,67 @@ namespace Mono.CSharp {
                                GetSignatureForError (), TypeManager.CSharpName (spec.DeclaringType));
                }
 
+               protected override void Error_CannotCallAbstractBase (ResolveContext rc, string name)
+               {
+                       name = name.Substring (0, name.LastIndexOf ('.'));
+                       base.Error_CannotCallAbstractBase (rc, name);
+               }
+
                public override string GetSignatureForError ()
                {
                        return TypeManager.CSharpSignature (spec);
                }
 
-               public void EmitAddOrRemove (EmitContext ec, bool is_add, Expression source)
+               public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
                {
-                       Arguments args = new Arguments (1);
-                       args.Add (new Argument (source));
-                       Invocation.EmitCall (ec, IsBase, InstanceExpression,
-                               is_add ? spec.AccessorAdd : spec.AccessorRemove,
-                               args, loc);
+                       Error_TypeArgumentsCannotBeUsed (ec.Report, "event", GetSignatureForError (), loc);
                }
        }
 
-       public class TemporaryVariable : VariableReference
+       public class TemporaryVariableReference : VariableReference
        {
-               LocalInfo li;
+               public class Declarator : Statement
+               {
+                       TemporaryVariableReference variable;
+
+                       public Declarator (TemporaryVariableReference variable)
+                       {
+                               this.variable = variable;
+                               loc = variable.loc;
+                       }
+
+                       protected override void DoEmit (EmitContext ec)
+                       {
+                               variable.li.CreateBuilder (ec);
+                       }
+
+                       protected override void CloneTo (CloneContext clonectx, Statement target)
+                       {
+                               // Nothing
+                       }
+               }
+
+               LocalVariable li;
 
-               public TemporaryVariable (TypeSpec type, Location loc)
+               public TemporaryVariableReference (LocalVariable li, Location loc)
                {
-                       this.type = type;
+                       this.li = li;
+                       this.type = li.Type;
                        this.loc = loc;
                }
 
+               public LocalVariable LocalInfo {
+                   get {
+                       return li;
+                   }
+               }
+
+               public static TemporaryVariableReference Create (TypeSpec type, Block block, Location loc)
+               {
+                       var li = LocalVariable.CreateCompilerGenerated (type, block, loc);
+                       return new TemporaryVariableReference (li, loc);
+               }
+
                public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        throw new NotSupportedException ("ET");
@@ -5343,11 +5440,6 @@ namespace Mono.CSharp {
                {
                        eclass = ExprClass.Variable;
 
-                       TypeExpr te = new TypeExpression (type, loc);
-                       li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
-                       if (!li.Resolve (ec))
-                               return null;
-
                        //
                        // Don't capture temporary variables except when using
                        // iterator redirection
@@ -5367,11 +5459,15 @@ namespace Mono.CSharp {
                
                public override void Emit (EmitContext ec)
                {
+                       li.CreateBuilder (ec);
+
                        Emit (ec, false);
                }
 
                public void EmitAssign (EmitContext ec, Expression source)
                {
+                       li.CreateBuilder (ec);
+
                        EmitAssign (ec, source, false, false);
                }
 
@@ -5412,19 +5508,9 @@ namespace Mono.CSharp {
        /// 
        class VarExpr : SimpleName
        {
-               // Used for error reporting only
-               int initializers_count;
-
                public VarExpr (Location loc)
                        : base ("var", loc)
                {
-                       initializers_count = 1;
-               }
-
-               public int VariableInitializersCount {
-                       set {
-                               this.initializers_count = value;
-                       }
                }
 
                public bool InferType (ResolveContext ec, Expression right_side)
@@ -5433,9 +5519,10 @@ namespace Mono.CSharp {
                                throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
                        
                        type = right_side.Type;
-                       if (type == TypeManager.null_type || type == TypeManager.void_type || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) {
-                               ec.Report.Error (815, loc, "An implicitly typed local variable declaration cannot be initialized with `{0}'",
-                                             right_side.GetSignatureForError ());
+                       if (type == InternalType.Null || type == TypeManager.void_type || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) {
+                               ec.Report.Error (815, loc,
+                                       "An implicitly typed local variable declaration cannot be initialized with `{0}'",
+                                       type.GetSignatureForError ());
                                return false;
                        }
 
@@ -5450,32 +5537,5 @@ namespace Mono.CSharp {
                        else
                                ec.Compiler.Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration");
                }
-
-               public override TypeExpr ResolveAsContextualType (IMemberContext rc, bool silent)
-               {
-                       TypeExpr te = base.ResolveAsContextualType (rc, true);
-                       if (te != null)
-                               return te;
-
-                       if (RootContext.Version < LanguageVersion.V_3)
-                               rc.Compiler.Report.FeatureIsNotAvailable (loc, "implicitly typed local variable");
-
-                       if (initializers_count == 1)
-                               return null;
-
-                       if (initializers_count > 1) {
-                               rc.Compiler.Report.Error (819, loc, "An implicitly typed local variable declaration cannot include multiple declarators");
-                               initializers_count = 1;
-                               return null;
-                       }
-
-                       if (initializers_count == 0) {
-                               initializers_count = 1;
-                               rc.Compiler.Report.Error (818, loc, "An implicitly typed local variable declarator must include an initializer");
-                               return null;
-                       }
-
-                       return null;
-               }
        }
 }