2007-10-17 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / mcs / ecore.cs
index 3bf1577993a5f6c8fab9f2db82d83c5ba2d5326e..fbb5438040925c729862e2569ce71f4c88c8c59e 100644 (file)
@@ -228,6 +228,15 @@ 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 (IResolveContext 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
@@ -239,7 +248,7 @@ namespace Mono.CSharp {
                        if (te == null)
                                return null;
 
-                       if (!silent) {
+                       if (!silent) { // && !(te is TypeParameterExpr)) {
                                ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (te.Type);
                                if (obsolete_attr != null && !ec.IsInObsoleteScope) {
                                        AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location);
@@ -302,6 +311,17 @@ namespace Mono.CSharp {
 
                }
 
+               public static void Error_InvalidExpressionStatement (Location loc)
+               {
+                       Report.Error (201, loc, "Only assignment, call, increment, decrement, and new object " +
+                                      "expressions can be used as a statement");
+               }
+               
+               public void Error_InvalidExpressionStatement ()
+               {
+                       Error_InvalidExpressionStatement (loc);
+               }
+
                protected void Error_CannotAssign (string to, string roContext)
                {
                        Report.Error (1656, loc, "Cannot assign to `{0}' because it is a `{1}'",
@@ -313,8 +333,12 @@ namespace Mono.CSharp {
                        Report.Error (1547, loc, "Keyword `void' cannot be used in this context");
                }
 
-               public virtual void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
+               public virtual void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
                {
+                       // The error was already reported as CS1660
+                       if (type == TypeManager.anonymous_method_type)
+                               return;
+
                        if (Type.FullName == target.FullName){
                                Report.ExtraInformation (loc,
                                        String.Format (
@@ -325,16 +349,20 @@ namespace Mono.CSharp {
 
                        if (expl) {
                                Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
-                                       GetSignatureForError (), TypeManager.CSharpName (target));
+                                       TypeManager.CSharpName (type), TypeManager.CSharpName (target));
                                return;
                        }
                        
                        Expression e = (this is EnumConstant) ? ((EnumConstant)this).Child : this;
                        bool b = Convert.ExplicitNumericConversion (e, target) != null;
 
-                       if (b || Convert.ExplicitReferenceConversionExists (Type, target) ||
-                               Convert.ExplicitUnsafe (e, target) != null || Convert.UserDefinedConversion (null, this, target, Location.Null, true) != null) {
-                               Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
+                       if (b ||
+                           Convert.ExplicitReferenceConversionExists (Type, target) ||
+                           Convert.ExplicitUnsafe (e, target) != null ||
+                           (ec != null && Convert.UserDefinedConversion (ec, this, target, Location.Null, true) != null))
+                       {
+                               Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. " +
+                                             "An explicit conversion exists (are you missing a cast?)",
                                        TypeManager.CSharpName (Type), TypeManager.CSharpName (target));
                                return;
                        }
@@ -345,14 +373,25 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       Report.Error (29, loc, "Cannot implicitly convert type {0} to `{1}'",
-                               Type == TypeManager.anonymous_method_type ?
-                               "anonymous method" : "`" + GetSignatureForError () + "'",
+                       Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'",
+                               TypeManager.CSharpName (type),
                                TypeManager.CSharpName (target));
                }
 
-               protected static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name)
+               protected void Error_VariableIsUsedBeforeItIsDeclared (string name)
+               {
+                       Report.Error (841, loc, "The variable `{0}' cannot be used before it is declared",
+                               name);
+               }
+
+               protected virtual void Error_TypeDoesNotContainDefinition (Type type, string name)
+               {
+                       Error_TypeDoesNotContainDefinition (loc, type, name);
+               }
+
+               public static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name)
                {
+                       Report.SymbolRelatedToPreviousError (type);
                        Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
                                TypeManager.CSharpName (type), name);
                }
@@ -381,8 +420,7 @@ namespace Mono.CSharp {
                                                return ResolveFlags.VariableOrValue;
 
                                        default:
-                                               throw new Exception ("Expression " + GetType () +
-                                                       " ExprClass is Invalid after resolve");
+                                               throw new InternalErrorException (loc.ToString () + " " +  GetType () + " ExprClass is Invalid after resolve");
                                }
                        }
                }
@@ -613,8 +651,8 @@ namespace Mono.CSharp {
 
                        if (mi.Length > 1) {
                                bool is_interface = qualifier_type != null && qualifier_type.IsInterface;
-                               MemberInfo non_method = null;
                                ArrayList methods = new ArrayList (2);
+                               ArrayList non_methods = null;
 
                                foreach (MemberInfo m in mi) {
                                        if (m is MethodBase) {
@@ -622,24 +660,29 @@ namespace Mono.CSharp {
                                                continue;
                                        }
 
-                                       if (non_method == null) {
-                                               non_method = m;
+                                       if (non_methods == null) {
+                                               non_methods = new ArrayList (2);
+                                               non_methods.Add (m);
                                                continue;
                                        }
 
-                                       Report.SymbolRelatedToPreviousError (m);
-                                       Report.SymbolRelatedToPreviousError (non_method);
-                                       Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
-                                               TypeManager.GetFullNameSignature (m), TypeManager.GetFullNameSignature (non_method));
-                                       return null;
+                                       foreach (MemberInfo n_m in non_methods) {
+                                               if (m.DeclaringType.IsInterface && TypeManager.ImplementsInterface (m.DeclaringType, n_m.DeclaringType))
+                                                       continue;
+
+                                               Report.SymbolRelatedToPreviousError (m);
+                                               Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
+                                                       TypeManager.GetFullNameSignature (m), TypeManager.GetFullNameSignature (n_m));
+                                               return null;
+                                       }
                                }
 
                                if (methods.Count == 0)
-                                       return null;
+                                       return ExprClassFromMemberInfo (container_type, (MemberInfo)non_methods [0], loc);
 
-                               if (non_method != null) {
+                               if (non_methods != null) {
                                        MethodBase method = (MethodBase) methods [0];
-
+                                       MemberInfo non_method = (MemberInfo) non_methods [0];
                                        if (method.DeclaringType == non_method.DeclaringType) {
                                                // Cannot happen with C# code, but is valid in IL
                                                Report.SymbolRelatedToPreviousError (method);
@@ -658,11 +701,11 @@ namespace Mono.CSharp {
                                        }
                                }
 
-                               return new MethodGroupExpr (methods, loc);
+                               return new MethodGroupExpr (methods, queried_type, loc);
                        }
 
                        if (mi [0] is MethodBase)
-                               return new MethodGroupExpr (mi, loc);
+                               return new MethodGroupExpr (mi, queried_type, loc);
 
                        return ExprClassFromMemberInfo (container_type, mi [0], loc);
                }
@@ -694,10 +737,10 @@ namespace Mono.CSharp {
                                             name, AllMemberTypes, AllBindingFlags, loc);
                }
 
-               public static Expression MethodLookup (Type container_type, Type queried_type,
+               public static MethodGroupExpr MethodLookup (Type container_type, Type queried_type,
                                                       string name, Location loc)
                {
-                       return MemberLookup (container_type, null, queried_type, name,
+                       return (MethodGroupExpr)MemberLookup (container_type, null, queried_type, name,
                                             MemberTypes.Method, AllBindingFlags, loc);
                }
 
@@ -707,14 +750,7 @@ namespace Mono.CSharp {
                ///   look for private members and display a useful debugging message if we
                ///   find it.
                /// </summary>
-               public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
-                                                           Type queried_type, string name, Location loc)
-               {
-                       return MemberLookupFinal (ec, qualifier_type, queried_type, name,
-                                                 AllMemberTypes, AllBindingFlags, loc);
-               }
-
-               public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
+               protected Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
                                                            Type queried_type, string name,
                                                            MemberTypes mt, BindingFlags bf,
                                                            Location loc)
@@ -725,17 +761,17 @@ namespace Mono.CSharp {
 
                        e = MemberLookup (ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc);
 
-                       if (e == null && errors == Report.Errors)
-                               // No errors were reported by MemberLookup, but there was an error.
-                               MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type, name, null, true, loc);
+                       if (e != null || errors != Report.Errors)
+                               return e;
 
-                       return e;
+                       // No errors were reported by MemberLookup, but there was an error.
+                       return Error_MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type,
+                                       name, null, mt, bf);
                }
 
-               public static void MemberLookupFailed (Type container_type, Type qualifier_type,
-                                                      Type queried_type, string name,
-                                                      string class_name, bool complain_if_none_found, 
-                                                      Location loc)
+               protected virtual Expression Error_MemberLookupFailed (Type container_type, Type qualifier_type,
+                                                      Type queried_type, string name, string class_name,
+                                                          MemberTypes mt, BindingFlags bf)
                {
                        if (almostMatchedMembers.Count != 0) {
                                for (int i = 0; i < almostMatchedMembers.Count; ++i) {
@@ -770,7 +806,7 @@ namespace Mono.CSharp {
                                        }
                                }
                                almostMatchedMembers.Clear ();
-                               return;
+                               return null;
                        }
 
                        MemberInfo[] lookup = null;
@@ -778,20 +814,28 @@ namespace Mono.CSharp {
                                class_name = "global::";
                        } else {
                                lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
-                                       AllMemberTypes, AllBindingFlags |
-                                       BindingFlags.NonPublic, name, null);
+                                       mt, (bf & ~BindingFlags.Public) | BindingFlags.NonPublic,
+                                       name, null);
+
+                               if (lookup != null) {
+                                       Report.SymbolRelatedToPreviousError (lookup [0]);
+                                       ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0]));
+                                       return Error_MemberLookupFailed (lookup);
+                               }
+
+                               lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
+                                       AllMemberTypes, AllBindingFlags | BindingFlags.NonPublic,
+                                       name, null);
                        }
 
                        if (lookup == null) {
-                               if (!complain_if_none_found)
-                                       return;
-
-                               if (class_name != null)
-                                       Report.Error (103, loc, "The name `{0}' does not exist in the context of `{1}'",
-                                               name, class_name);
-                               else
-                                       Error_TypeDoesNotContainDefinition (loc, queried_type, name);
-                               return;
+                               if (class_name != null) {
+                                       Report.Error (103, loc, "The name `{0}' does not exist in the current context",
+                                               name);
+                               } else {
+                                       Error_TypeDoesNotContainDefinition (queried_type, name);
+                               }
+                               return null;
                        }
 
                        if (TypeManager.MemberLookup (queried_type, null, queried_type,
@@ -805,20 +849,22 @@ namespace Mono.CSharp {
                                                      "requires {1} type arguments",
                                                      TypeManager.CSharpName (t),
                                                      TypeManager.GetNumberOfTypeArguments (t).ToString ());
-                                       return;
+                                       return null;
                                }
                        }
 
-                       MemberList ml = TypeManager.FindMembers (queried_type, MemberTypes.Constructor,
-                                                                BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null);
-                       if (name == ".ctor" && ml.Count == 0)
-                       {
-                               Report.Error (143, loc, "The type `{0}' has no constructors defined", TypeManager.CSharpName (queried_type));
-                               return;
+                       return Error_MemberLookupFailed (lookup);
+               }
+
+               protected virtual Expression Error_MemberLookupFailed (MemberInfo[] members)
+               {
+                       for (int i = 0; i < members.Length; ++i) {
+                               if (!(members [i] is MethodBase))
+                                       return null;
                        }
 
-                       Report.SymbolRelatedToPreviousError (lookup [0]);
-                       ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0]));
+                       // By default propagate the closest candidates upwards
+                       return new MethodGroupExpr (members, type, loc);
                }
 
                /// <summary>
@@ -841,27 +887,26 @@ namespace Mono.CSharp {
 
                static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
                {
-                       MethodBase method;
-                       Expression operator_group;
+                       MethodGroupExpr operator_group;
 
 #if GMCS_SOURCE
                        if (TypeManager.IsNullableType (e.Type))
                                return new Nullable.OperatorTrueOrFalse (e, is_true, loc).Resolve (ec);
 #endif
 
-                       operator_group = MethodLookup (ec.ContainerType, e.Type, is_true ? "op_True" : "op_False", loc);
+                       operator_group = MethodLookup (ec.ContainerType, e.Type, is_true ? "op_True" : "op_False", loc) as MethodGroupExpr;
                        if (operator_group == null)
                                return null;
 
-                       ArrayList arguments = new ArrayList ();
+                       ArrayList arguments = new ArrayList (1);
                        arguments.Add (new Argument (e, Argument.AType.Expression));
-                       method = Invocation.OverloadResolve (
-                               ec, (MethodGroupExpr) operator_group, arguments, false, loc);
+                       operator_group = operator_group.OverloadResolve (
+                               ec, arguments, false, loc);
 
-                       if (method == null)
+                       if (operator_group == null)
                                return null;
 
-                       return new StaticCallExpr ((MethodInfo) method, arguments, loc);
+                       return new StaticCallExpr ((MethodInfo) operator_group, arguments, loc);
                }
 
                /// <summary>
@@ -887,7 +932,7 @@ namespace Mono.CSharp {
                        //
                        converted = Expression.GetOperatorTrue (ec, e, loc);
                        if (converted == null){
-                               e.Error_ValueCannotBeConverted (loc, TypeManager.bool_type, false);
+                               e.Error_ValueCannotBeConverted (ec, loc, TypeManager.bool_type, false);
                                return null;
                        }
                        return converted;
@@ -1106,7 +1151,7 @@ namespace Mono.CSharp {
                                        target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
 
                                if (target == null) {
-                                       source.Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
+                                       source.Error_ValueCannotBeConverted (ec, loc, TypeManager.int32_type, false);
                                        return null;
                                }
                        }
@@ -1133,7 +1178,39 @@ namespace Mono.CSharp {
 
                        return target;
                }
-               
+
+               //
+               // Derived classes implement this method by cloning the fields that
+               // could become altered during the Resolve stage
+               //
+               // Only expressions that are created for the parser need to implement
+               // this.
+               //
+               protected virtual void CloneTo (CloneContext clonectx, Expression target)
+               {
+                       throw new NotImplementedException (
+                               String.Format (
+                                       "CloneTo not implemented for expression {0}", this.GetType ()));
+               }
+
+               //
+               // Clones an expression created by the parser.
+               //
+               // We only support expressions created by the parser so far, not
+               // expressions that have been resolved (many more classes would need
+               // to implement CloneTo).
+               //
+               // This infrastructure is here merely for Lambda expressions which
+               // compile the same code using different type values for the same
+               // arguments to find the correct overload
+               //
+               public Expression Clone (CloneContext clonectx)
+               {
+                       Expression cloned = (Expression) MemberwiseClone ();
+                       CloneTo (clonectx, cloned);
+
+                       return cloned;
+               }
        }
 
        /// <summary>
@@ -1153,8 +1230,7 @@ namespace Mono.CSharp {
 
                        ExpressionStatement es = e as ExpressionStatement;
                        if (es == null)
-                               Error (201, "Only assignment, call, increment, decrement and new object " +
-                                      "expressions can be used as a statement");
+                               Error_InvalidExpressionStatement ();
 
                        return es;
                }
@@ -1180,16 +1256,26 @@ namespace Mono.CSharp {
        ///   would be "unsigned int".
        ///
        /// </summary>
-       public class EmptyCast : Expression {
-               protected readonly Expression child;
+       public class EmptyCast : Expression
+       {
+               protected Expression child;
 
-               public EmptyCast (Expression child, Type return_type)
+               protected EmptyCast (Expression child, Type return_type)
                {
                        eclass = child.eclass;
                        loc = child.Location;
                        type = return_type;
                        this.child = child;
                }
+               
+               public static Expression Create (Expression child, Type type)
+               {
+                       Constant c = child as Constant;
+                       if (c != null)
+                               return new EmptyConstantCast (c, type);
+
+                       return new EmptyCast (child, type);
+               }               
 
                public override Expression DoResolve (EmitContext ec)
                {
@@ -1209,6 +1295,12 @@ namespace Mono.CSharp {
                        return child.GetAttributableValue (valueType, out value);
                }
 
+               protected override void CloneTo (CloneContext clonectx, Expression t)
+               {
+                       EmptyCast target = (EmptyCast) t;
+
+                       target.child = child.Clone (clonectx);
+               }
        }
 
        /// <summary>
@@ -1387,9 +1479,10 @@ namespace Mono.CSharp {
                        return child.GetValue ();
                }
 
-               public override Constant Reduce (bool inCheckedContext, Type target_type)
+               public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
                {
-                       return child.Reduce (inCheckedContext, target_type);
+                       // FIXME: check that 'type' can be converted to 'target_type' first
+                       return child.ConvertExplicitly (inCheckedContext, target_type);
                }
 
                public override Constant Increment ()
@@ -1397,24 +1490,29 @@ namespace Mono.CSharp {
                        return child.Increment ();
                }
 
-               public override bool IsDefaultValue
-               {
+               public override bool IsDefaultValue {
                        get { return child.IsDefaultValue; }
                }
 
-               public override bool IsNegative
-               {
+               public override bool IsNegative {
                        get { return child.IsNegative; }
                }
 
+               public override bool IsZeroInteger {
+                       get { return child.IsZeroInteger; }
+               }               
+               
                public override void Emit (EmitContext ec)
                {
                        child.Emit (ec);
                }
 
-               public override Constant ToType (Type type)
+               public override Constant ConvertImplicitly (Type target_type)
                {
-                       return child.ToType (type);
+                       // FIXME: Do we need to check user conversions?
+                       if (!Convert.ImplicitStandardConversionExists (this, target_type))
+                               return null;
+                       return child.ConvertImplicitly (target_type);
                }
        }
 
@@ -1474,37 +1572,7 @@ namespace Mono.CSharp {
                
                public override string AsString ()
                {
-                       return Child.AsString ();
-               }
-
-               public override DoubleConstant ConvertToDouble ()
-               {
-                       return Child.ConvertToDouble ();
-               }
-
-               public override FloatConstant ConvertToFloat ()
-               {
-                       return Child.ConvertToFloat ();
-               }
-
-               public override ULongConstant ConvertToULong ()
-               {
-                       return Child.ConvertToULong ();
-               }
-
-               public override LongConstant ConvertToLong ()
-               {
-                       return Child.ConvertToLong ();
-               }
-
-               public override UIntConstant ConvertToUInt ()
-               {
-                       return Child.ConvertToUInt ();
-               }
-
-               public override IntConstant ConvertToInt ()
-               {
-                       return Child.ConvertToInt ();
+                       return TypeManager.CSharpEnumValue (type, Child.GetValue ());
                }
 
                public override Constant Increment()
@@ -1528,23 +1596,27 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override Constant Reduce(bool inCheckedContext, Type target_type)
+               public override Constant ConvertExplicitly(bool inCheckedContext, Type target_type)
                {
                        if (Child.Type == target_type)
                                return Child;
 
-                       return Child.Reduce (inCheckedContext, target_type);
+                       return Child.ConvertExplicitly (inCheckedContext, target_type);
                }
 
-               public override Constant ToType (Type type)
+               public override Constant ConvertImplicitly (Type type)
                {
-                       if (Type == type) {
+                       Type this_type = TypeManager.DropGenericTypeArguments (Type);
+                       type = TypeManager.DropGenericTypeArguments (type);
+
+                       if (this_type == type) {
                                // This is workaround of mono bug. It can be removed when the latest corlib spreads enough
                                if (TypeManager.IsEnumType (type.UnderlyingSystemType))
                                        return this;
 
-                               if (type.UnderlyingSystemType != Child.Type)
-                                       Child = Child.ToType (type.UnderlyingSystemType);
+                               Type child_type = TypeManager.DropGenericTypeArguments (Child.Type);
+                               if (type.UnderlyingSystemType != child_type)
+                                       Child = Child.ConvertImplicitly (type.UnderlyingSystemType);
                                return this;
                        }
 
@@ -1552,7 +1624,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       return Child.ToType (type);
+                       return Child.ConvertImplicitly(type);
                }
 
        }
@@ -1921,7 +1993,7 @@ namespace Mono.CSharp {
        ///   of a dotted-name.
        /// </summary>
        public class SimpleName : Expression {
-               public string Name;
+               public readonly string Name;
                public readonly TypeArguments Arguments;
                bool in_transit;
 
@@ -1951,14 +2023,19 @@ namespace Mono.CSharp {
                public static string RemoveGenericArity (string name)
                {
                        int start = 0;
-                       StringBuilder sb = new StringBuilder ();
-                       while (start < name.Length) {
+                       StringBuilder sb = null;
+                       do {
                                int pos = name.IndexOf ('`', start);
                                if (pos < 0) {
+                                       if (start == 0)
+                                               return name;
+
                                        sb.Append (name.Substring (start));
                                        break;
                                }
 
+                               if (sb == null)
+                                       sb = new StringBuilder ();
                                sb.Append (name.Substring (start, pos-start));
 
                                pos++;
@@ -1966,7 +2043,7 @@ namespace Mono.CSharp {
                                        pos++;
 
                                start = pos;
-                       }
+                       } while (start < name.Length);
 
                        return sb.ToString ();
                }
@@ -1978,7 +2055,7 @@ namespace Mono.CSharp {
 
                public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
                {
-                       if (ec.IsFieldInitializer)
+                       if (ec.IsInFieldInitializer)
                                Report.Error (236, l,
                                        "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
                                        name);
@@ -1992,7 +2069,7 @@ namespace Mono.CSharp {
                {
                        return resolved_to != null && resolved_to.Type != null && 
                                resolved_to.Type.Name == Name &&
-                               (ec.DeclContainer.LookupType (Name, loc, /* ignore_cs0104 = */ true) != null);
+                               (ec.DeclContainer.LookupNamespaceOrType (Name, loc, /* ignore_cs0104 = */ true) != null);
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -2029,7 +2106,7 @@ namespace Mono.CSharp {
 
                FullNamedExpression ResolveNested (IResolveContext ec, Type t)
                {
-                       if (!TypeManager.IsGenericTypeDefinition (t))
+                       if (!TypeManager.IsGenericTypeDefinition (t) && !TypeManager.IsGenericType (t))
                                return null;
 
                        DeclSpace ds = ec.DeclContainer;
@@ -2070,7 +2147,7 @@ namespace Mono.CSharp {
                                return fne.ResolveAsTypeStep (ec, silent);
 
                        int errors = Report.Errors;
-                       fne = ec.DeclContainer.LookupType (Name, loc, /*ignore_cs0104=*/ false);
+                       fne = ec.DeclContainer.LookupNamespaceOrType (Name, loc, /*ignore_cs0104=*/ false);
 
                        if (fne != null) {
                                if (fne.Type == null)
@@ -2091,10 +2168,16 @@ namespace Mono.CSharp {
                        if (silent || errors != Report.Errors)
                                return null;
 
+                       Error_TypeOrNamespaceNotFound (ec);
+                       return null;
+               }
+
+               protected virtual void Error_TypeOrNamespaceNotFound (IResolveContext ec)
+               {
                        MemberCore mc = ec.DeclContainer.GetDefinition (Name);
                        if (mc != null) {
                                Error_UnexpectedKind (ec.DeclContainer, "type", GetMemberType (mc), loc);
-                               return null;
+                               return;
                        }
 
                        string ns = ec.DeclContainer.NamespaceEntry.NS.Name;
@@ -2103,26 +2186,33 @@ namespace Mono.CSharp {
                                Type type = a.GetType (fullname);
                                if (type != null) {
                                        Report.SymbolRelatedToPreviousError (type);
-                                       Expression.ErrorIsInaccesible (loc, fullname);
-                                       return null;
+                                       Expression.ErrorIsInaccesible (loc, TypeManager.CSharpName (type));
+                                       return;
                                }
                        }
 
-                       Type t = ec.DeclContainer.NamespaceEntry.NS.LookForAnyGenericType (Name);
+                       Type t = ec.DeclContainer.LookupAnyGeneric (Name);
                        if (t != null) {
                                Namespace.Error_InvalidNumberOfTypeArguments (t, loc);
-                               return null;
+                               return;
                        }
 
+                       if (Arguments != null) {
+                               FullNamedExpression retval = ec.DeclContainer.LookupNamespaceOrType (SimpleName.RemoveGenericArity (Name), loc, true);
+                               if (retval != null) {
+                                       Namespace.Error_TypeArgumentsCannotBeUsed (retval.Type, loc, "type");
+                                       return;
+                               }
+                       }
+                                               
                        NamespaceEntry.Error_NamespaceNotFound (loc, Name);
-                       return null;
                }
 
                // TODO: I am still not convinced about this. If someone else will need it
                // implement this as virtual property in MemberCore hierarchy
-               string GetMemberType (MemberCore mc)
+               public static string GetMemberType (MemberCore mc)
                {
-                       if (mc is PropertyBase)
+                       if (mc is Property)
                                return "property";
                        if (mc is Indexer)
                                return "indexer";
@@ -2132,6 +2222,8 @@ namespace Mono.CSharp {
                                return "method";
                        if (mc is EnumMember)
                                return "enum";
+                       if (mc is Event)
+                               return "event";
 
                        return "type";
                }
@@ -2140,9 +2232,11 @@ namespace Mono.CSharp {
                {
                        if (in_transit)
                                return null;
-                       in_transit = true;
 
+                       in_transit = true;
                        Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
+                       in_transit = false;
+
                        if (e == null)
                                return null;
 
@@ -2212,33 +2306,47 @@ namespace Mono.CSharp {
                                        else
                                                return pref.Resolve (ec);
                                }
+
+                               Expression expr = current_block.Toplevel.GetTransparentIdentifier (Name);
+                               if (expr != null) {
+                                       if (right_side != null)
+                                               return expr.ResolveLValue (ec, right_side, loc);
+                                       return expr.Resolve (ec);
+                               }
                        }
                        
                        //
                        // Stage 2: Lookup members 
                        //
 
-                       DeclSpace lookup_ds = ec.DeclContainer;
                        Type almost_matched_type = null;
                        ArrayList almost_matched = null;
-                       do {
+                       for (DeclSpace lookup_ds = ec.DeclContainer; lookup_ds != null; lookup_ds = lookup_ds.Parent) {
+                               // either RootDeclSpace or GenericMethod
                                if (lookup_ds.TypeBuilder == null)
-                                       break;
+                                       continue;
 
                                e = MemberLookup (ec.ContainerType, lookup_ds.TypeBuilder, Name, loc);
-                               if (e != null)
-                                       break;
+                               if (e != null) {
+                                       if (e is PropertyExpr) {
+                                               // 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 (((PropertyExpr) e).IsAccessibleFrom (ec.ContainerType, right_side != null))
+                                                       break;
+                                       } else if (e is EventExpr) {
+                                               if (((EventExpr) e).IsAccessibleFrom (ec.ContainerType))
+                                                       break;
+                                       } else {
+                                               break;
+                                       }
+                                       e = null;
+                               }
 
                                if (almost_matched == null && almostMatchedMembers.Count > 0) {
                                        almost_matched_type = lookup_ds.TypeBuilder;
                                        almost_matched = (ArrayList) almostMatchedMembers.Clone ();
                                }
-
-                               lookup_ds =lookup_ds.Parent;
-                       } while (lookup_ds != null);
-
-                       if (e == null && ec.ContainerType != null)
-                               e = MemberLookup (ec.ContainerType, ec.ContainerType, Name, loc);
+                       }
 
                        if (e == null) {
                                if (almost_matched == null && almostMatchedMembers.Count > 0) {
@@ -2249,11 +2357,25 @@ namespace Mono.CSharp {
                        }
 
                        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 (Name);
+                                               return null;
+                                       }
+                               }
+
                                if (almost_matched != null)
                                        almostMatchedMembers = almost_matched;
                                if (almost_matched_type == null)
                                        almost_matched_type = ec.ContainerType;
-                               MemberLookupFailed (ec.ContainerType, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclContainer.Name, true, loc);
+                               Error_MemberLookupFailed (ec.ContainerType, null, almost_matched_type, Name,
+                                       ec.DeclContainer.Name, AllMemberTypes, AllBindingFlags);
                                return null;
                        }
 
@@ -2271,7 +2393,7 @@ namespace Mono.CSharp {
 
                                Expression left;
                                if (me.IsInstance) {
-                                       if (ec.IsStatic || ec.IsFieldInitializer) {
+                                       if (ec.IsStatic || ec.IsInFieldInitializer) {
                                                //
                                                // Note that an MemberExpr can be both IsInstance and IsStatic.
                                                // An unresolved MethodGroupExpr can contain both kinds of methods
@@ -2332,14 +2454,7 @@ namespace Mono.CSharp {
                
                public override void Emit (EmitContext ec)
                {
-                       //
-                       // If this is ever reached, then we failed to
-                       // find the name as a namespace
-                       //
-
-                       Error (103, "The name `" + Name +
-                              "' does not exist in the class `" +
-                              ec.DeclContainer.Name + "'");
+                       throw new InternalErrorException ("The resolve phase was not executed");
                }
 
                public override string ToString ()
@@ -2349,8 +2464,18 @@ namespace Mono.CSharp {
 
                public override string GetSignatureForError ()
                {
+                       if (Arguments != null) {
+                               return TypeManager.RemoveGenericArity (Name) + "<" +
+                                       Arguments.GetSignatureForError () + ">";
+                       }
+
                        return Name;
                }
+
+               protected override void CloneTo (CloneContext clonectx, Expression target)
+               {
+                       // CloneTo: Nothing, we do not keep any state on this expression
+               }
        }
 
        /// <summary>
@@ -2509,61 +2634,111 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               static readonly char [] dot_array = { '.' };
-               protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
+               private class UnexpectedType
                {
-                       // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
-                       string rest = null;
-                       string lookup_name = name;
-                       int pos = name.IndexOf ('.');
-                       if (pos >= 0) {
-                               rest = name.Substring (pos + 1);
-                               lookup_name = name.Substring (0, pos);
-                       }
-
-                       FullNamedExpression resolved = RootNamespace.Global.Lookup (ec.DeclContainer, lookup_name, Location.Null);
-
-                       if (resolved != null && rest != null) {
-                               // Now handle the rest of the the name.
-                               string [] elements = rest.Split (dot_array);
-                               string element;
-                               int count = elements.Length;
-                               int i = 0;
-                               while (i < count && resolved != null && resolved is Namespace) {
-                                       Namespace ns = resolved as Namespace;
-                                       element = elements [i++];
-                                       lookup_name += "." + element;
-                                       resolved = ns.Lookup (ec.DeclContainer, element, Location.Null);
-                               }
+               }
 
-                               if (resolved != null && resolved is TypeExpr) {
-                                       Type t = ((TypeExpr) resolved).Type;
-                                       while (t != null) {
-                                               if (!ec.DeclContainer.CheckAccessLevel (t)) {
-                                                       resolved = null;
-                                                       lookup_name = t.FullName;
-                                                       break;
-                                               }
-                                               if (i == count) {
-                                                       type = t;
-                                                       return this;
-                                               }
-                                               t = TypeManager.GetNestedType (t, elements [i++]);
+               // This performes recursive type lookup, providing support for generic types.
+               // For example, given the type:
+               //
+               // System.Collections.Generic.KeyValuePair`2[[System.Int32],[System.String]]
+               //
+               // The types will be checked in the following order:
+               //                                                                             _
+               // System                                                                       |
+               // System.Collections                                                           |
+               // System.Collections.Generic                                                   |
+               //                        _                                                     |
+               //     System              | recursive call 1                                   |
+               //     System.Int32       _|                                                    | main method call
+               //                        _                                                     |
+               //     System              | recursive call 2                                   |
+               //     System.String      _|                                                    |
+               //                                                                              |
+               // System.Collections.Generic.KeyValuePair`2[[System.Int32],[System.String]]   _|
+               //
+               private Type TypeLookup (IResolveContext ec, string name)
+               {
+                       int index = 0;
+                       int dot = 0;
+                       bool done = false;
+                       FullNamedExpression resolved = null;
+                       Type type = null;
+                       Type recursive_type = null;
+                       while (index < name.Length) {
+                               if (name[index] == '[') {
+                                       int open = index;
+                                       int braces = 1;
+                                       do {
+                                               index++;
+                                               if (name[index] == '[')
+                                                       braces++;
+                                               else if (name[index] == ']')
+                                                       braces--;
+                                       } while (braces > 0);
+                                       recursive_type = TypeLookup (ec, name.Substring (open + 1, index - open - 1));
+                                       if (recursive_type == null || (recursive_type == typeof(UnexpectedType)))
+                                               return recursive_type;
+                               }
+                               else {
+                                       if (name[index] == ',')
+                                               done = true;
+                                       else if ((name[index] == '.' && !done) || (index == name.Length && name[0] != '[')) {
+                                               string substring = name.Substring(dot, index - dot);
+
+                                               if (resolved == null)
+                                                       resolved = RootNamespace.Global.Lookup (ec.DeclContainer, substring, Location.Null);
+                                               else if (resolved is Namespace)
+                                                   resolved = (resolved as Namespace).Lookup (ec.DeclContainer, substring, Location.Null);
+                                               else if (type != null)
+                                                       type = TypeManager.GetNestedType (type, substring);
+                                               else
+                                                       return null;
+
+                                               if (resolved == null)
+                                                       return null;
+                                               else if (type == null && resolved is TypeExpr)
+                                                       type = resolved.Type;
+
+                                               dot = index + 1;
                                        }
                                }
+                               index++;
                        }
+                       if (name[0] != '[') {
+                               string substring = name.Substring(dot, index - dot);
 
-                       if (resolved == null) {
-                               NamespaceEntry.Error_NamespaceNotFound (loc, lookup_name);
-                               return null;
+                               if (type != null)
+                                       return TypeManager.GetNestedType (type, substring);
+                               
+                               if (resolved != null) {
+                                       resolved = (resolved as Namespace).Lookup (ec.DeclContainer, substring, Location.Null);
+                                       if (resolved is TypeExpr)
+                                               return resolved.Type;
+                                       
+                                       if (resolved == null)
+                                               return null;
+                                       
+                                       resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc);
+                                       return typeof (UnexpectedType);
+                               }
+                               else
+                                       return null;
+                       }
+                       else
+                               return recursive_type;
                        }
 
-                       if (!(resolved is TypeExpr)) {
-                               resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc);
+               protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
+               {
+                       Type t = TypeLookup (ec, name);
+                       if (t == null) {
+                               NamespaceEntry.Error_NamespaceNotFound (loc, name);
                                return null;
                        }
-
-                       type = resolved.Type;
+                       if (t == typeof(UnexpectedType))
+                               return null;
+                       type = t;
                        return this;
                }
 
@@ -2574,6 +2749,19 @@ namespace Mono.CSharp {
                public override string FullName {
                        get { return name; }
                }
+
+               protected override void CloneTo (CloneContext clonectx, Expression target)
+               {
+                       // CloneTo: Nothing, we do not keep any state on this expression
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       if (type == null)
+                               return TypeManager.CSharpName (name);
+
+                       return base.GetSignatureForError ();
+               }
        }
 
        /// <summary>
@@ -2759,6 +2947,10 @@ namespace Mono.CSharp {
                        //
 
                        if (left is TypeExpr) {
+                               left = left.ResolveAsTypeTerminal (ec, true);
+                               if (left == null)
+                                       return null;
+
                                if (!IsStatic) {
                                        SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
                                        return null;
@@ -2807,32 +2999,118 @@ namespace Mono.CSharp {
                }
        }
 
+       /// 
+       /// Represents group of extension methods
+       /// 
+       public class ExtensionMethodGroupExpr : MethodGroupExpr
+       {
+               readonly NamespaceEntry namespaceEntry;
+               public Expression ExtensionExpression;
+               Argument extension_argument;
+
+               public ExtensionMethodGroupExpr (ArrayList list, NamespaceEntry n, Type extensionType, Location l)
+                       : base (list, extensionType, l)
+               {
+                       this.namespaceEntry = n;
+               }
+
+               public override bool IsBase {
+                       get { return true; }
+               }
+
+               public override bool IsStatic {
+                       get { return true; }
+               }
+
+               public bool IsTopLevel {
+                       get { return namespaceEntry == null; }
+               }
+
+               public override void EmitArguments (EmitContext ec, ArrayList arguments)
+               {
+                       if (arguments == null)
+                               arguments = new ArrayList (1);                  
+                       arguments.Insert (0, extension_argument);
+                       base.EmitArguments (ec, arguments);
+               }
+
+               public override void EmitCall (EmitContext ec, ArrayList arguments)
+               {
+                       if (arguments == null)
+                               arguments = new ArrayList (1);
+                       arguments.Insert (0, extension_argument);
+                       base.EmitCall (ec, arguments);
+               }
+
+               public override MethodGroupExpr OverloadResolve (EmitContext ec, ArrayList arguments, bool may_fail, Location loc)
+               {
+                       if ((ExtensionExpression.eclass & (ExprClass.Value | ExprClass.Variable)) == 0)
+                               return base.OverloadResolve (ec, arguments, may_fail, loc);
+
+                       if (arguments == null)
+                               arguments = new ArrayList (1);
+
+                       arguments.Insert (0, new Argument (ExtensionExpression));
+                       MethodGroupExpr mg = ResolveOverloadExtensions (ec, arguments, namespaceEntry, loc);
+
+                       // Store resolved argument and restore original arguments
+                       if (mg != null)
+                               ((ExtensionMethodGroupExpr)mg).extension_argument = (Argument)arguments [0];
+                       arguments.RemoveAt (0);
+
+                       return mg;
+               }
+
+               MethodGroupExpr ResolveOverloadExtensions (EmitContext ec, ArrayList arguments, NamespaceEntry ns, Location loc)
+               {
+                       // Use normal resolve rules
+                       MethodGroupExpr mg = base.OverloadResolve (ec, arguments, ns != null, loc);
+                       if (mg != null)
+                               return mg;
+
+                       if (ns == null)
+                               return null;
+
+                       // Search continues
+                       ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, null, Name);
+                       if (e == null)
+                               return base.OverloadResolve (ec, arguments, false, loc);
+
+                       e.ExtensionExpression = ExtensionExpression;
+                       return e.ResolveOverloadExtensions (ec, arguments, e.namespaceEntry, loc);
+               }               
+       }
+
        /// <summary>
-       ///   MethodGroup Expression.
-       ///  
-       ///   This is a fully resolved expression that evaluates to a type
+       ///   MethodGroupExpr represents a group of method candidates which
+       ///   can be resolved to the best method overload
        /// </summary>
-       public class MethodGroupExpr : MemberExpr {
+       public class MethodGroupExpr : MemberExpr
+       {
+               public interface IErrorHandler
+               {
+                       bool NoExactMatch (EmitContext ec, MethodBase method);
+               }
+
+               public static IErrorHandler CustomErrorHandler;         
                public MethodBase [] Methods;
-               bool has_type_arguments = false;
-               bool identical_type_name = false;
+               MethodBase best_candidate;
+               bool has_type_arguments;
+               bool identical_type_name;
                bool is_base;
                
-               public MethodGroupExpr (MemberInfo [] mi, Location l)
+               public MethodGroupExpr (MemberInfo [] mi, Type type, Location l)
+                       : this (type, l)
                {
                        Methods = new MethodBase [mi.Length];
                        mi.CopyTo (Methods, 0);
-                       eclass = ExprClass.MethodGroup;
-                       type = TypeManager.object_type;
-                       loc = l;
                }
 
-               public MethodGroupExpr (ArrayList list, Location l)
+               public MethodGroupExpr (ArrayList list, Type type, Location l)
+                       : this (type, l)
                {
-                       Methods = new MethodBase [list.Count];
-
                        try {
-                               list.CopyTo (Methods, 0);
+                               Methods = (MethodBase[])list.ToArray (typeof (MethodBase));
                        } catch {
                                foreach (MemberInfo m in list){
                                        if (!(m is MethodBase)){
@@ -2843,9 +3121,14 @@ namespace Mono.CSharp {
                                throw;
                        }
 
-                       loc = l;
+
+               }
+
+               protected MethodGroupExpr (Type type, Location loc)
+               {
+                       this.loc = loc;
                        eclass = ExprClass.MethodGroup;
-                       type = TypeManager.object_type;
+                       this.type = type;
                }
 
                public override Type DeclaringType {
@@ -2862,10 +3145,6 @@ namespace Mono.CSharp {
                        get {
                                return has_type_arguments;
                        }
-
-                       set {
-                               has_type_arguments = value;
-                       }
                }
 
                public bool IdenticalTypeName {
@@ -2878,7 +3157,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public bool IsBase {
+               public virtual bool IsBase {
                        get {
                                return is_base;
                        }
@@ -2889,6 +3168,9 @@ namespace Mono.CSharp {
 
                public override string GetSignatureForError ()
                {
+                       if (best_candidate != null)
+                               return TypeManager.CSharpSignature (best_candidate);
+                       
                        return TypeManager.CSharpSignature (Methods [0]);
                }
 
@@ -2917,22 +3199,258 @@ namespace Mono.CSharp {
                                return false;
                        }
                }
-
-               public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
-                                                               SimpleName original)
+               
+               public static explicit operator ConstructorInfo (MethodGroupExpr mg)
                {
-                       if (!(left is TypeExpr) &&
-                           original != null && original.IdenticalNameAndTypeName (ec, left, loc))
-                               IdenticalTypeName = true;
-
-                       return base.ResolveMemberAccess (ec, left, loc, original);
+                       return (ConstructorInfo)mg.best_candidate;
                }
-               
-               override public Expression DoResolve (EmitContext ec)
+
+               public static explicit operator MethodInfo (MethodGroupExpr mg)
                {
-                       if (!IsInstance)
-                               InstanceExpression = null;
+                       return (MethodInfo)mg.best_candidate;
+               }
+
+               /// <summary>
+               ///   Determines "better conversion" as specified in 14.4.2.3
+               ///
+               ///    Returns : p    if a->p is better,
+               ///              q    if a->q is better,
+               ///              null if neither is better
+               /// </summary>
+               static Type BetterConversion (EmitContext ec, Argument a, Type p, Type q)
+               {
+                       Type argument_type = TypeManager.TypeToCoreType (a.Type);
+                       Expression argument_expr = a.Expr;
+
+                       if (argument_type == null)
+                               throw new Exception ("Expression of type " + a.Expr +
+                                       " does not resolve its type");
+
+                       if (p == null || q == null)
+                               throw new InternalErrorException ("BetterConversion Got a null conversion");
+
+                       if (p == q)
+                               return null;
+
+                       if (argument_expr is NullLiteral) 
+                       {
+                               //
+                               // If the argument is null and one of the types to compare is 'object' and
+                               // the other is a reference type, we prefer the other.
+                               //
+                               // This follows from the usual rules:
+                               //   * There is an implicit conversion from 'null' to type 'object'
+                               //   * There is an implicit conversion from 'null' to any reference type
+                               //   * There is an implicit conversion from any reference type to type 'object'
+                               //   * There is no implicit conversion from type 'object' to other reference types
+                               //  => Conversion of 'null' to a reference type is better than conversion to 'object'
+                               //
+                               //  FIXME: This probably isn't necessary, since the type of a NullLiteral is the 
+                               //         null type. I think it used to be 'object' and thus needed a special 
+                               //         case to avoid the immediately following two checks.
+                               //
+                               if (!p.IsValueType && q == TypeManager.object_type)
+                                       return p;
+                               if (!q.IsValueType && p == TypeManager.object_type)
+                                       return q;
+                       }
+                                
+                       if (argument_type == p)
+                               return p;
+
+                       if (argument_type == q)
+                               return q;
+
+                       Expression p_tmp = new EmptyExpression (p);
+                       Expression q_tmp = new EmptyExpression (q);
+
+                       bool p_to_q = Convert.ImplicitConversionExists (ec, p_tmp, q);
+                       bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p);
+
+                       if (p_to_q && !q_to_p)
+                               return p;
+
+                       if (q_to_p && !p_to_q)
+                               return q;
+
+                       if (p == TypeManager.sbyte_type)
+                               if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
+                                       q == TypeManager.uint32_type || q == TypeManager.uint64_type)
+                                       return p;
+                       if (q == TypeManager.sbyte_type)
+                               if (p == TypeManager.byte_type || p == TypeManager.ushort_type ||
+                                       p == TypeManager.uint32_type || p == TypeManager.uint64_type)
+                                       return q;
+
+                       if (p == TypeManager.short_type)
+                               if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
+                                       q == TypeManager.uint64_type)
+                                       return p;
+                       if (q == TypeManager.short_type)
+                               if (p == TypeManager.ushort_type || p == TypeManager.uint32_type ||
+                                       p == TypeManager.uint64_type)
+                                       return q;
+
+                       if (p == TypeManager.int32_type)
+                               if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
+                                       return p;
+                       if (q == TypeManager.int32_type)
+                               if (p == TypeManager.uint32_type || p == TypeManager.uint64_type)
+                                       return q;
+
+                       if (p == TypeManager.int64_type)
+                               if (q == TypeManager.uint64_type)
+                                       return p;
+                       if (q == TypeManager.int64_type)
+                               if (p == TypeManager.uint64_type)
+                                       return q;
+
+                       return null;
+               }
+
+               /// <summary>
+               ///   Determines "Better function" between candidate
+               ///   and the current best match
+               /// </summary>
+               /// <remarks>
+               ///    Returns a boolean indicating :
+               ///     false if candidate ain't better
+               ///     true  if candidate is better than the current best match
+               /// </remarks>
+               static bool BetterFunction (EmitContext ec, ArrayList args, int argument_count,
+                       MethodBase candidate, bool candidate_params,
+                       MethodBase best, bool best_params)
+               {
+                       ParameterData candidate_pd = TypeManager.GetParameterData (candidate);
+                       ParameterData best_pd = TypeManager.GetParameterData (best);
+               
+                       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 = (Argument) args [j];
+
+                               Type ct = TypeManager.TypeToCoreType (candidate_pd.ParameterType (c_idx));
+                               Type bt = TypeManager.TypeToCoreType (best_pd.ParameterType (b_idx));
+
+                               if (candidate_params && candidate_pd.ParameterModifier (c_idx) == Parameter.Modifier.PARAMS) 
+                               {
+                                       ct = TypeManager.GetElementType (ct);
+                                       --c_idx;
+                               }
+
+                               if (best_params && best_pd.ParameterModifier (b_idx) == Parameter.Modifier.PARAMS) 
+                               {
+                                       bt = TypeManager.GetElementType (bt);
+                                       --b_idx;
+                               }
+
+                               if (ct.Equals (bt))
+                                       continue;
+
+                               same = false;
+                               Type better = BetterConversion (ec, a, ct, bt);
+
+                               // for each argument, the conversion to 'ct' should be no worse than 
+                               // the conversion to 'bt'.
+                               if (better == bt)
+                                       return false;
+
+                               // for at least one argument, the conversion to 'ct' should be better than 
+                               // the conversion to 'bt'.
+                               if (better == ct)
+                                       better_at_least_one = true;
+                       }
+
+                       if (better_at_least_one)
+                               return true;
+
+                       //
+                       // This handles the case
+                       //
+                       //   Add (float f1, float f2, float f3);
+                       //   Add (params decimal [] foo);
+                       //
+                       // The call Add (3, 4, 5) should be ambiguous.  Without this check, the
+                       // first candidate would've chosen as better.
+                       //
+                       if (!same)
+                               return false;
+
+                       //
+                       // The two methods have equal parameter types.  Now apply tie-breaking rules
+                       //
+                       if (TypeManager.IsGenericMethod (best) && !TypeManager.IsGenericMethod (candidate))
+                               return true;
+                       if (!TypeManager.IsGenericMethod (best) && TypeManager.IsGenericMethod (candidate))
+                               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;
+
+                       //
+                       // now, both methods have the same number of parameters, and the parameters have the same types
+                       // Pick the "more specific" signature
+                       //
+
+                       MethodBase orig_candidate = TypeManager.DropGenericMethodArguments (candidate);
+                       MethodBase orig_best = TypeManager.DropGenericMethodArguments (best);
+
+                       ParameterData orig_candidate_pd = TypeManager.GetParameterData (orig_candidate);
+                       ParameterData orig_best_pd = TypeManager.GetParameterData (orig_best);
+
+                       bool specific_at_least_once = false;
+                       for (int j = 0; j < candidate_param_count; ++j) 
+                       {
+                               Type ct = TypeManager.TypeToCoreType (orig_candidate_pd.ParameterType (j));
+                               Type bt = TypeManager.TypeToCoreType (orig_best_pd.ParameterType (j));
+                               if (ct.Equals (bt))
+                                       continue;
+                               Type specific = MoreSpecific (ct, bt);
+                               if (specific == bt)
+                                       return false;
+                               if (specific == ct)
+                                       specific_at_least_once = true;
+                       }
+
+                       if (specific_at_least_once)
+                               return true;
 
+                       // FIXME: handle lifted operators
+                       // ...
+
+                       return false;
+               }
+
+               public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
+                                                               SimpleName original)
+               {
+                       if (!(left is TypeExpr) &&
+                           original != null && original.IdenticalNameAndTypeName (ec, left, loc))
+                               IdenticalTypeName = true;
+
+                       return base.ResolveMemberAccess (ec, left, loc, original);
+               }
+               
+               override public Expression DoResolve (EmitContext ec)
+               {
                        if (InstanceExpression != null) {
                                InstanceExpression = InstanceExpression.DoResolve (ec);
                                if (InstanceExpression == null)
@@ -2952,47 +3470,727 @@ namespace Mono.CSharp {
                {
                        ReportUsageError ();
                }
+               
+               public virtual void EmitArguments (EmitContext ec, ArrayList arguments)
+               {
+                       Invocation.EmitArguments (ec, best_candidate, arguments, false, null);  
+               }
+               
+               public virtual void EmitCall (EmitContext ec, ArrayList arguments)
+               {
+                       Invocation.EmitCall (ec, IsBase, InstanceExpression, best_candidate, arguments, loc);                   
+               }
+
+               protected virtual void Error_InvalidArguments (EmitContext ec, Location loc, int idx, MethodBase method,
+                                                                                                       Type delegate_type, Argument a, ParameterData expected_par)
+               {
+                       if (a is CollectionElementInitializer.ElementInitializerArgument) {
+                               Report.SymbolRelatedToPreviousError (method);
+                               if ((expected_par.ParameterModifier (idx) & Parameter.Modifier.ISBYREF) != 0) {
+                                       Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier",
+                                               TypeManager.CSharpSignature (method));
+                                       return;
+                               }
+                               Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments",
+                                         TypeManager.CSharpSignature (method));
+                       } else if (delegate_type == null) {
+                               Report.SymbolRelatedToPreviousError (method);
+                               Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments",
+                                                 TypeManager.CSharpSignature (method));
+                       } else
+                               Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments",
+                                       TypeManager.CSharpName (delegate_type));
+
+                       Parameter.Modifier mod = expected_par.ParameterModifier (idx);
+
+                       string index = (idx + 1).ToString ();
+                       if ((mod & Parameter.Modifier.ISBYREF) != (a.Modifier & Parameter.Modifier.ISBYREF) ||
+                               (mod & Parameter.Modifier.ISBYREF) != 0) {
+                               if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) == 0)
+                                       Report.Error (1615, loc, "Argument `{0}' should not be passed with the `{1}' keyword",
+                                               index, Parameter.GetModifierSignature (a.Modifier));
+                               else
+                                       Report.Error (1620, loc, "Argument `{0}' must be passed with the `{1}' keyword",
+                                               index, Parameter.GetModifierSignature (mod));
+                       } else {
+                               string p1 = Argument.FullDesc (a);
+                               string p2 = TypeManager.CSharpName (expected_par.ParameterType (idx));
+
+                               if (p1 == p2) {
+                                       Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous ");
+                                       Report.SymbolRelatedToPreviousError (a.Expr.Type);
+                                       Report.SymbolRelatedToPreviousError (expected_par.ParameterType (idx));
+                               }
+                               Report.Error (1503, loc, "Argument {0}: Cannot convert type `{1}' to `{2}'", index, p1, p2);
+                       }
+               }
+               
+               protected virtual int GetApplicableParametersCount (MethodBase method, ParameterData parameters)
+               {
+                       return parameters.Count;
+               }               
 
-               bool RemoveMethods (bool keep_static)
+               public static bool IsAncestralType (Type first_type, Type second_type)
                {
-                       ArrayList smethods = new ArrayList ();
+                       return first_type != second_type &&
+                               (TypeManager.IsSubclassOf (second_type, first_type) ||
+                               TypeManager.ImplementsInterface (second_type, first_type));
+               }
+
+               ///
+               /// Determines if the candidate method is applicable (section 14.4.2.1)
+               /// to the given set of arguments
+               /// A return value rates candidate method compatibility,
+               /// 0 = the best, int.MaxValue = the worst
+               ///
+               public int IsApplicable (EmitContext ec,
+                                                ArrayList arguments, int arg_count, ref MethodBase method)
+               {
+                       MethodBase candidate = method;
+
+                       ParameterData pd = TypeManager.GetParameterData (candidate);
+                       int param_count = GetApplicableParametersCount (candidate, pd);
+
+                       if (arg_count != param_count)
+                               return int.MaxValue;
 
-                       foreach (MethodBase mb in Methods){
-                               if (mb.IsStatic == keep_static)
-                                       smethods.Add (mb);
+                       //
+                       // 1. Infer type arguments for generic method
+                       //
+#if GMCS_SOURCE                        
+                       if (!HasTypeArguments && TypeManager.IsGenericMethod (method)) {
+                               int score = TypeManager.InferTypeArguments (ec, arguments, ref candidate);
+                               if (score != 0)
+                                       return --score;
+                               
+                               if (TypeManager.IsGenericMethodDefinition (candidate))
+                                       throw new InternalErrorException ("a generic method definition took part in overload resolution");
+                               
+                               pd = TypeManager.GetParameterData (candidate);
                        }
+#endif                 
+
+                       //
+                       // 2. Each argument has to be implicitly converible to method parameter
+                       //
+                       for (int i = arg_count; i > 0; ) {
+                               i--;
+
+                               Argument a = (Argument) arguments [i];
 
-                       if (smethods.Count == 0)
+                               Parameter.Modifier a_mod = a.Modifier &
+                                       ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
+
+                               Parameter.Modifier p_mod = pd.ParameterModifier (i) &
+                                       ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK | Parameter.Modifier.PARAMS);
+
+                               Type pt = pd.ParameterType (i);
+
+                               // FIXME: Kill this abomination (EmitContext.TempEc)
+                               EmitContext prevec = EmitContext.TempEc;
+                               EmitContext.TempEc = ec;
+                               try {
+                                       if (pt.IsByRef)
+                                               pt = pt.GetElementType ();
+                                       
+                                       if (!Convert.ImplicitConversionExists (ec, a.Expr, pt))
+                                               return ++i * 2;
+
+                                       if (a_mod != p_mod)
+                                               return ++i * 2 - 1;
+
+                               } finally {
+                                       EmitContext.TempEc = prevec;
+                               }
+                       }
+
+                       method = candidate;                     
+                       return 0;
+               }
+
+               public static bool IsOverride (MethodBase cand_method, MethodBase base_method)
+               {
+                       if (!IsAncestralType (base_method.DeclaringType, cand_method.DeclaringType))
                                return false;
 
-                       Methods = new MethodBase [smethods.Count];
-                       smethods.CopyTo (Methods, 0);
+                       ParameterData cand_pd = TypeManager.GetParameterData (cand_method);
+                       ParameterData base_pd = TypeManager.GetParameterData (base_method);
+               
+                       if (cand_pd.Count != base_pd.Count)
+                               return false;
+
+                       for (int j = 0; j < cand_pd.Count; ++j) 
+                       {
+                               Parameter.Modifier cm = cand_pd.ParameterModifier (j);
+                               Parameter.Modifier bm = base_pd.ParameterModifier (j);
+                               Type ct = TypeManager.TypeToCoreType (cand_pd.ParameterType (j));
+                               Type bt = TypeManager.TypeToCoreType (base_pd.ParameterType (j));
+
+                               if (cm != bm || ct != bt)
+                                       return false;
+                       }
 
                        return true;
                }
                
+               public bool IsParamsMethodApplicable (EmitContext ec,
+                                                            ArrayList arguments, int arg_count,
+                                                            ref MethodBase candidate)
+               {
+                       return IsParamsMethodApplicable (
+                               ec, arguments, arg_count, false, ref candidate) ||
+                               IsParamsMethodApplicable (
+                                       ec, arguments, arg_count, true, ref candidate);
+
+
+               }
+
+               bool IsParamsMethodApplicable (EmitContext ec,
+                                                     ArrayList arguments, int arg_count,
+                                                     bool do_varargs, ref MethodBase candidate)
+               {
+#if GMCS_SOURCE
+                       if (!HasTypeArguments &&
+                           !TypeManager.InferParamsTypeArguments (ec, arguments, ref candidate))
+                               return false;
+
+                       if (TypeManager.IsGenericMethodDefinition (candidate))
+                               throw new InternalErrorException ("a generic method definition took part in overload resolution");
+#endif
+
+                       return IsParamsMethodApplicable (
+                               ec, arguments, arg_count, candidate, do_varargs);
+               }
+
                /// <summary>
-               ///   Removes any instance methods from the MethodGroup, returns
-               ///   false if the resulting set is empty.
+               ///   Determines if the candidate method, if a params method, is applicable
+               ///   in its expanded form to the given set of arguments
                /// </summary>
-               public bool RemoveInstanceMethods ()
+               bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments,
+                                                     int arg_count, MethodBase candidate,
+                                                     bool do_varargs)
+               {
+                       ParameterData pd = TypeManager.GetParameterData (candidate);
+                       int pd_count = GetApplicableParametersCount (candidate, pd);
+                       if (pd_count == 0)
+                               return false;
+
+                       int count = pd_count - 1;
+                       if (do_varargs) {
+                               if (pd.ParameterModifier (count) != Parameter.Modifier.ARGLIST)
+                                       return false;
+                               if (pd_count != arg_count)
+                                       return false;
+
+                               if (!(((Argument) arguments [count]).Expr is Arglist))
+                                       return false;
+                               --pd_count;
+                       } else {
+                               if (!pd.HasParams)
+                                       return false;
+                       }
+                       
+                       if (count > arg_count)
+                               return false;
+                       
+                       if (pd_count == 1 && arg_count == 0)
+                               return true;
+
+                       //
+                       // If we have come this far, the case which
+                       // remains is when the number of parameters is
+                       // less than or equal to the argument count.
+                       //
+                       int argument_index = 0;
+                       Argument a;
+                       for (int i = 0; i < pd_count; ++i) {
+
+                               if ((pd.ParameterModifier (i) & Parameter.Modifier.PARAMS) != 0) {
+                                       Type element_type = TypeManager.GetElementType (pd.ParameterType (i));
+                                       int params_args_count = arg_count - pd_count;
+                                       if (params_args_count < 0)
+                                               continue;
+
+                                       do {
+                                               a = (Argument) arguments [argument_index++];
+
+                                               if (!Convert.ImplicitConversionExists (ec, a.Expr, element_type))
+                                                       return false;
+                                       } while (params_args_count-- > 0);
+                                       continue;
+                               }
+
+                               a = (Argument) arguments [argument_index++];
+
+                               Parameter.Modifier a_mod = a.Modifier & 
+                                       (unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK)));
+                               Parameter.Modifier p_mod = pd.ParameterModifier (i) &
+                                       (unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK)));
+
+                               if (a_mod == p_mod) {
+
+                                       if (a_mod == Parameter.Modifier.NONE)
+                                               if (!Convert.ImplicitConversionExists (ec,
+                                                       a.Expr,
+                                                       pd.ParameterType (i)))
+                                                       return false;
+
+                                       if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
+                                               Type pt = pd.ParameterType (i);
+
+                                               if (!pt.IsByRef)
+                                                       pt = TypeManager.GetReferenceType (pt);
+                                               
+                                               if (pt != a.Type)
+                                                       return false;
+                                       }
+                               } else
+                                       return false;
+                               
+                       }
+
+                       return true;
+               }               
+               
+               public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2, Location loc)
                {
-                       return RemoveMethods (true);
+                       MemberInfo [] miset;
+                       MethodGroupExpr union;
+
+                       if (mg1 == null) {
+                               if (mg2 == null)
+                                       return null;
+                               return (MethodGroupExpr) mg2;
+                       } else {
+                               if (mg2 == null)
+                                       return (MethodGroupExpr) mg1;
+                       }
+                       
+                       MethodGroupExpr left_set = null, right_set = null;
+                       int length1 = 0, length2 = 0;
+                       
+                       left_set = (MethodGroupExpr) mg1;
+                       length1 = left_set.Methods.Length;
+                       
+                       right_set = (MethodGroupExpr) mg2;
+                       length2 = right_set.Methods.Length;
+                       
+                       ArrayList common = new ArrayList ();
+
+                       foreach (MethodBase r in right_set.Methods){
+                               if (TypeManager.ArrayContainsMethod (left_set.Methods, r))
+                                       common.Add (r);
+                       }
+
+                       miset = new MemberInfo [length1 + length2 - common.Count];
+                       left_set.Methods.CopyTo (miset, 0);
+                       
+                       int k = length1;
+
+                       foreach (MethodBase r in right_set.Methods) {
+                               if (!common.Contains (r))
+                                       miset [k++] = r;
+                       }
+
+                       union = new MethodGroupExpr (miset, mg1.Type, loc);
+                       
+                       return union;
+               }               
+
+               static Type MoreSpecific (Type p, Type q)
+               {
+                       if (TypeManager.IsGenericParameter (p) && !TypeManager.IsGenericParameter (q))
+                               return q;
+                       if (!TypeManager.IsGenericParameter (p) && TypeManager.IsGenericParameter (q))
+                               return p;
+
+                       if (TypeManager.HasElementType (p)) 
+                       {
+                               Type pe = TypeManager.GetElementType (p);
+                               Type qe = TypeManager.GetElementType (q);
+                               Type specific = MoreSpecific (pe, qe);
+                               if (specific == pe)
+                                       return p;
+                               if (specific == qe)
+                                       return q;
+                       } 
+                       else if (TypeManager.IsGenericType (p)) 
+                       {
+                               Type[] pargs = TypeManager.GetTypeArguments (p);
+                               Type[] qargs = TypeManager.GetTypeArguments (q);
+
+                               bool p_specific_at_least_once = false;
+                               bool q_specific_at_least_once = false;
+
+                               for (int i = 0; i < pargs.Length; i++) 
+                               {
+                                       Type specific = MoreSpecific (pargs [i], qargs [i]);
+                                       if (specific == pargs [i])
+                                               p_specific_at_least_once = true;
+                                       if (specific == qargs [i])
+                                               q_specific_at_least_once = true;
+                               }
+
+                               if (p_specific_at_least_once && !q_specific_at_least_once)
+                                       return p;
+                               if (!p_specific_at_least_once && q_specific_at_least_once)
+                                       return q;
+                       }
+
+                       return null;
                }
 
                /// <summary>
-               ///   Removes any static methods from the MethodGroup, returns
-               ///   false if the resulting set is empty.
+               ///   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 bool RemoveStaticMethods ()
+               public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ArrayList Arguments,
+                       bool may_fail, Location loc)
                {
-                       return RemoveMethods (false);
-               }
+                       bool method_params = false;
+                       Type applicable_type = null;
+                       int arg_count = 0;
+                       ArrayList candidates = new ArrayList (2);
+                       ArrayList candidate_overrides = null;
+
+                       //
+                       // Used to keep a map between the candidate
+                       // and whether it is being considered in its
+                       // normal or expanded form
+                       //
+                       // false is normal form, true is expanded form
+                       //
+                       Hashtable candidate_to_form = null;
+
+                       if (Arguments != null)
+                               arg_count = Arguments.Count;
+
+                       if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
+                               if (!may_fail)
+                                       Report.Error (1533, loc, "Invoke cannot be called directly on a delegate");
+                               return null;
+                       }
 
+                       int nmethods = Methods.Length;
+
+                       if (!IsBase) {
+                               //
+                               // Methods marked 'override' don't take part in 'applicable_type'
+                               // computation, nor in the actual overload resolution.
+                               // However, they still need to be emitted instead of a base virtual method.
+                               // So, we salt them away into the 'candidate_overrides' array.
+                               //
+                               // In case of reflected methods, we replace each overriding method with
+                               // its corresponding base virtual method.  This is to improve compatibility
+                               // with non-C# libraries which change the visibility of overrides (#75636)
+                               //
+                               int j = 0;
+                               for (int i = 0; i < Methods.Length; ++i) {
+                                       MethodBase m = Methods [i];
+#if GMCS_SOURCE
+                                       Type [] gen_args = null;
+                                       if (m.IsGenericMethod && !m.IsGenericMethodDefinition)
+                                               gen_args = m.GetGenericArguments ();
+#endif
+                                       if (TypeManager.IsOverride (m)) {
+                                               if (candidate_overrides == null)
+                                                       candidate_overrides = new ArrayList ();
+                                               candidate_overrides.Add (m);
+                                               m = TypeManager.TryGetBaseDefinition (m);
+#if GMCS_SOURCE
+                                               if (m != null && gen_args != null) {
+                                                       if (!m.IsGenericMethodDefinition)
+                                                               throw new InternalErrorException ("GetBaseDefinition didn't return a GenericMethodDefinition");
+                                                       m = ((MethodInfo) m).MakeGenericMethod (gen_args);
+                                               }
+#endif
+                                       }
+                                       if (m != null)
+                                               Methods [j++] = m;
+                               }
+                               nmethods = j;
+                       }
+
+                       //
+                       // Enable message recording, it's used mainly by lambda expressions
+                       //
+                       Report.IMessageRecorder msg_recorder = new Report.MessageRecorder ();
+                       Report.IMessageRecorder prev_recorder = Report.SetMessageRecorder (msg_recorder);
+
+                       //
+                       // First we construct the set of applicable methods
+                       //
+                       bool is_sorted = true;
+                       int best_candidate_rate = int.MaxValue;
+                       for (int i = 0; i < nmethods; i++) {
+                               Type decl_type = Methods [i].DeclaringType;
+
+                               //
+                               // If we have already found an applicable method
+                               // we eliminate all base types (Section 14.5.5.1)
+                               //
+                               if (applicable_type != null && IsAncestralType (decl_type, applicable_type))
+                                       continue;
+
+                               //
+                               // Check if candidate is applicable (section 14.4.2.1)
+                               //   Is candidate applicable in normal form?
+                               //
+                               int candidate_rate = IsApplicable (ec, Arguments, arg_count, ref Methods [i]);
+
+                               if (candidate_rate != 0 && IsParamsMethodApplicable (ec, Arguments, arg_count, ref Methods [i])) {
+                                       MethodBase candidate = Methods [i];
+                                       if (candidate_to_form == null)
+                                               candidate_to_form = new PtrHashtable ();
+                                       candidate_to_form [candidate] = candidate;
+                                       // Candidate is applicable in expanded form
+                                       candidate_rate = 0;
+                               }
+
+                               if (candidate_rate < best_candidate_rate) {
+                                       best_candidate_rate = candidate_rate;
+                                       best_candidate = Methods [i];
+                               }
+
+                               if (candidate_rate != 0) {
+                                       if (msg_recorder != null)
+                                               msg_recorder.EndSession ();
+                                       continue;
+                               }
+
+                               msg_recorder = null;
+
+                               candidates.Add (Methods [i]);
+
+                               if (applicable_type == null)
+                                       applicable_type = decl_type;
+                               else if (applicable_type != decl_type) {
+                                       is_sorted = false;
+                                       if (IsAncestralType (applicable_type, decl_type))
+                                               applicable_type = decl_type;
+                               }
+                       }
+
+                       Report.SetMessageRecorder (prev_recorder);
+                       if (msg_recorder != null && msg_recorder.PrintMessages ())
+                               return null;
+                       
+                       int candidate_top = candidates.Count;
+
+                       if (applicable_type == null) {
+                               if (ec.IsInProbingMode || may_fail)
+                                       return null;
+
+                               //
+                               // Okay so we have failed to find exact match so we
+                               // return error info about the closest match
+                               //
+                               if (best_candidate != null) {
+                                       if (CustomErrorHandler != null) {
+                                               if (CustomErrorHandler.NoExactMatch (ec, best_candidate))
+                                                       return null;
+                                       }
+                                       
+                                       if (TypeManager.IsGenericMethod (best_candidate)) {
+                                               Report.Error (411, loc,
+                                                       "The type arguments for method `{0}' cannot be inferred from " +
+                                                       "the usage. Try specifying the type arguments explicitly",
+                                                       TypeManager.CSharpSignature (best_candidate));
+                                       } else {
+                                               VerifyArgumentsCompat (ec, Arguments, arg_count, best_candidate, false, null, may_fail, loc);
+                                       }
+
+                                       return null;
+                               }
+
+                               if (almostMatchedMembers.Count != 0) {
+                                       Error_MemberLookupFailed (ec.ContainerType, type, type, ".ctor",
+                                       null, MemberTypes.Constructor, AllBindingFlags);
+                                       return null;
+                               }
+                               
+                               //
+                               // We failed to find any match
+                               //
+                               if (Name == ConstructorInfo.ConstructorName) {
+                                       Report.SymbolRelatedToPreviousError (type);
+                                       Report.Error (1729, loc,
+                                               "The type `{0}' does not contain a constructor that takes `{1}' arguments",
+                                               TypeManager.CSharpName (type), arg_count);
+                               } else {
+                                       string report_name = Name;
+                                       if (report_name == ConstructorInfo.ConstructorName)
+                                               report_name = TypeManager.CSharpName (DeclaringType);
+
+                                       Invocation.Error_WrongNumArguments (loc, report_name, arg_count);
+                               }
+                                
+                               return null;
+                       }
+
+                       if (!is_sorted) {
+                               //
+                               // At this point, applicable_type is _one_ of the most derived types
+                               // in the set of types containing the methods in this MethodGroup.
+                               // Filter the candidates so that they only contain methods from the
+                               // most derived types.
+                               //
+
+                               int finalized = 0; // Number of finalized candidates
+
+                               do {
+                                       // Invariant: applicable_type is a most derived type
+                                       
+                                       // We'll try to complete Section 14.5.5.1 for 'applicable_type' by 
+                                       // eliminating all it's base types.  At the same time, we'll also move
+                                       // every unrelated type to the end of the array, and pick the next
+                                       // 'applicable_type'.
+
+                                       Type next_applicable_type = null;
+                                       int j = finalized; // where to put the next finalized candidate
+                                       int k = finalized; // where to put the next undiscarded candidate
+                                       for (int i = finalized; i < candidate_top; ++i) {
+                                               MethodBase candidate = (MethodBase) candidates [i];
+                                               Type decl_type = candidate.DeclaringType;
+
+                                               if (decl_type == applicable_type) {
+                                                       candidates [k++] = candidates [j];
+                                                       candidates [j++] = candidates [i];
+                                                       continue;
+                                               }
+
+                                               if (IsAncestralType (decl_type, applicable_type))
+                                                       continue;
+
+                                               if (next_applicable_type != null &&
+                                                       IsAncestralType (decl_type, next_applicable_type))
+                                                       continue;
+
+                                               candidates [k++] = candidates [i];
+
+                                               if (next_applicable_type == null ||
+                                                       IsAncestralType (next_applicable_type, decl_type))
+                                                       next_applicable_type = decl_type;
+                                       }
+
+                                       applicable_type = next_applicable_type;
+                                       finalized = j;
+                                       candidate_top = k;
+                               } while (applicable_type != null);
+                       }
+
+                       //
+                       // Now we actually find the best method
+                       //
+
+                       best_candidate = (MethodBase) candidates [0];
+                       method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
+                       for (int ix = 1; ix < candidate_top; ix++) {
+                               MethodBase candidate = (MethodBase) candidates [ix];
+
+                               if (candidate == best_candidate)
+                                       continue;
+
+                               bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
+
+                               if (BetterFunction (ec, Arguments, arg_count, 
+                                       candidate, cand_params,
+                                       best_candidate, method_params)) {
+                                       best_candidate = candidate;
+                                       method_params = cand_params;
+                               }
+                       }
+                       //
+                       // Now check that there are no ambiguities i.e the selected method
+                       // should be better than all the others
+                       //
+                       MethodBase ambiguous = null;
+                       for (int ix = 0; ix < candidate_top; ix++) {
+                               MethodBase candidate = (MethodBase) candidates [ix];
+
+                               if (candidate == best_candidate)
+                                       continue;
+
+                               bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
+                               if (!BetterFunction (ec, Arguments, arg_count,
+                                       best_candidate, method_params,
+                                       candidate, cand_params)) 
+                               {
+                                       if (!may_fail)
+                                               Report.SymbolRelatedToPreviousError (candidate);
+                                       ambiguous = candidate;
+                               }
+                       }
+
+                       if (ambiguous != null) {
+                               Report.SymbolRelatedToPreviousError (best_candidate);
+                               Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'",
+                                       TypeManager.CSharpSignature (ambiguous), TypeManager.CSharpSignature (best_candidate));
+                               return this;
+                       }
+
+                       //
+                       // If the method is a virtual function, pick an override closer to the LHS type.
+                       //
+                       if (!IsBase && best_candidate.IsVirtual) {
+                               if (TypeManager.IsOverride (best_candidate))
+                                       throw new InternalErrorException (
+                                               "Should not happen.  An 'override' method took part in overload resolution: " + best_candidate);
+
+                               if (candidate_overrides != null)
+                                       foreach (MethodBase candidate in candidate_overrides) {
+                                               if (IsOverride (candidate, best_candidate))
+                                                       best_candidate = candidate;
+                                       }
+                       }
+
+                       // We can stop here when probing is on
+                       if (ec.IsInProbingMode)
+                               return this;
+
+                       //
+                       // And now check if the arguments are all
+                       // compatible, perform conversions if
+                       // necessary etc. and return if everything is
+                       // all right
+                       //
+                       if (!VerifyArgumentsCompat (ec, Arguments, arg_count, best_candidate,
+                               method_params, null, may_fail, loc))
+                               return null;
+
+                       if (best_candidate == null)
+                               return null;
+
+                       MethodBase the_method = TypeManager.DropGenericMethodArguments (best_candidate);
+#if GMCS_SOURCE
+                       if (the_method.IsGenericMethodDefinition &&
+                           !ConstraintChecker.CheckConstraints (ec, the_method, best_candidate, loc))
+                               return null;
+#endif
+
+                       IMethodData data = TypeManager.GetMethod (the_method);
+                       if (data != null)
+                               data.SetMemberIsUsed ();
+
+                       return this;
+               }
+               
                public Expression ResolveGeneric (EmitContext ec, TypeArguments args)
                {
 #if GMCS_SOURCE
-                       if (args.Resolve (ec) == false)
+                       if (!args.Resolve (ec))
                                return null;
 
                        Type[] atypes = args.Arguments;
@@ -3003,10 +4201,10 @@ namespace Mono.CSharp {
                        ArrayList list = new ArrayList ();
                        foreach (MethodBase mb in Methods) {
                                MethodInfo mi = mb as MethodInfo;
-                               if ((mi == null) || !mi.IsGenericMethod)
+                               if ((mi == null) || !mb.IsGenericMethod)
                                        continue;
 
-                               Type[] gen_params = mi.GetGenericArguments ();
+                               Type[] gen_params = mb.GetGenericArguments ();
 
                                if (first == null) {
                                        first = mi;
@@ -3016,23 +4214,33 @@ namespace Mono.CSharp {
                                if (gen_params.Length != atypes.Length)
                                        continue;
 
-                               list.Add (mi.MakeGenericMethod (atypes));
+                               mi = mi.MakeGenericMethod (atypes);
+                               list.Add (mi);
+
+#if MS_COMPATIBLE
+                               // MS implementation throws NotSupportedException for GetParameters
+                               // on unbaked generic method
+                               Parameters p = TypeManager.GetParameterData (mi) as Parameters;
+                               if (p != null) {
+                                       p = p.Clone ();
+                                       p.InflateTypes (gen_params, atypes);
+                                       TypeManager.RegisterMethod (mi, p);
+                               }
+#endif
                        }
 
                        if (list.Count > 0) {
-                               MethodGroupExpr new_mg = new MethodGroupExpr (list, Location);
-                               new_mg.InstanceExpression = InstanceExpression;
-                               new_mg.HasTypeArguments = true;
-                               new_mg.IsBase = IsBase;
-                               return new_mg;
+                               this.Methods = (MethodBase []) list.ToArray (typeof (MethodBase));
+                               has_type_arguments = true;
+                               return this;
                        }
 
-                       if (first != null)
+                       if (first != null) {
+                               Report.SymbolRelatedToPreviousError (first);
                                Report.Error (
-                                       305, loc, "Using the generic method `{0}' " +
-                                       "requires {1} type arguments", Name,
-                                       first_count.ToString ());
-                       else
+                                       305, loc, "Using the generic method `{0}' requires `{1}' type arguments",
+                                       TypeManager.CSharpSignature (first), first_count.ToString ());
+                       } else
                                Report.Error (
                                        308, loc, "The non-generic method `{0}' " +
                                        "cannot be used with type arguments", Name);
@@ -3042,6 +4250,77 @@ namespace Mono.CSharp {
                        throw new NotImplementedException ();
 #endif
                }
+
+               public bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments,
+                                                         int arg_count, MethodBase method,
+                                                         bool chose_params_expanded,
+                                                         Type delegate_type, bool may_fail, Location loc)
+               {
+                       ParameterData pd = TypeManager.GetParameterData (method);
+                       int param_count = GetApplicableParametersCount (method, pd);
+
+                       int j;
+                       int a_idx = 0;
+                       Argument a = null;
+                       int errors = Report.Errors;
+                       for (j = 0; j < param_count; j++) {
+                               Type parameter_type = pd.ParameterType (j);
+                               Parameter.Modifier pm = pd.ParameterModifier (j);
+
+                               if (pm == Parameter.Modifier.ARGLIST) {
+                                       a = (Argument) Arguments [a_idx];
+                                       if (!(a.Expr is Arglist))
+                                               break;
+                                       ++a_idx;
+                                       continue;
+                               }
+
+                               int params_arg_count = 1;
+                               if (pm == Parameter.Modifier.PARAMS) {
+                                       pm = Parameter.Modifier.NONE;
+                                       params_arg_count = arg_count - param_count + 1;
+                                       if (chose_params_expanded)
+                                               parameter_type = TypeManager.GetElementType (parameter_type);
+                               }
+
+                               while (params_arg_count > 0) {
+                                       a = (Argument) Arguments [a_idx];
+                                       if (pm != a.Modifier)
+                                               break;
+
+                                       if (!TypeManager.IsEqual (a.Type, parameter_type)) {
+                                               if (pm == Parameter.Modifier.OUT || pm == Parameter.Modifier.REF)
+                                                       break;
+
+                                               Expression conv = Convert.ImplicitConversion (ec, a.Expr, parameter_type, loc);
+                                               if (conv == null)
+                                                       break;
+
+                                               // Update the argument with the implicit conversion
+                                               if (a.Expr != conv)
+                                                       a.Expr = conv;
+                                       }
+
+                                       --params_arg_count;
+                                       ++a_idx;
+                               }
+                               if (params_arg_count > 0)
+                                       break;
+
+                               if (parameter_type.IsPointer && !ec.InUnsafe) {
+                                       if (!may_fail)
+                                               UnsafeError (loc);
+                                       return false;
+                               }
+                       }
+
+                       if (a_idx == arg_count)
+                               return true;
+
+                       if (!may_fail && Report.Errors == errors)
+                               Error_InvalidArguments (ec, loc, a_idx, method, delegate_type, a, pd);
+                       return false;
+               }
        }
 
        /// <summary>
@@ -3142,7 +4421,6 @@ namespace Mono.CSharp {
                        
                        if (t.IsPointer && !ec.InUnsafe) {
                                UnsafeError (loc);
-                               return null;
                        }
 
                        return base.ResolveMemberAccess (ec, left, loc, original);
@@ -3186,7 +4464,7 @@ namespace Mono.CSharp {
                                InstanceExpression.CheckMarshalByRefAccess ();
                        }
 
-                       if (!in_initializer && !ec.IsFieldInitializer) {
+                       if (!in_initializer && !ec.IsInFieldInitializer) {
                                ObsoleteAttribute oa;
                                FieldBase f = TypeManager.GetField (FieldInfo);
                                if (f != null) {
@@ -3212,7 +4490,23 @@ namespace Mono.CSharp {
                                        }
                                }
                        }
-                       
+
+                       IFixedBuffer fb = AttributeTester.GetFixedBuffer (FieldInfo);
+                       if (fb != null) {
+                               if (!ec.InFixedInitializer && ec.ContainerType.IsValueType) {
+                                       Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement");
+                               }
+
+                               if (!(InstanceExpression is LocalVariableReference) &&
+                                       !(InstanceExpression is This)) {
+                                       Report.SymbolRelatedToPreviousError (FieldInfo);
+                                       Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields",
+                                               TypeManager.GetFullNameSignature (FieldInfo));
+                               }
+                               
+                               return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec);
+                       }
+
                        // If the instance expression is a local variable or parameter.
                        IVariable var = InstanceExpression as IVariable;
                        if ((var == null) || (var.VariableInfo == null))
@@ -3283,7 +4577,7 @@ namespace Mono.CSharp {
 
                        if (FieldInfo.IsInitOnly) {
                                // InitOnly fields can only be assigned in constructors or initializers
-                               if (!ec.IsFieldInitializer && !ec.IsConstructor)
+                               if (!ec.IsInFieldInitializer && !ec.IsConstructor)
                                        return Report_AssignToReadonly (right_side);
 
                                if (ec.IsConstructor) {
@@ -3374,16 +4668,14 @@ namespace Mono.CSharp {
                                if (!prepared)
                                        EmitInstance (ec, false);
 
-                               if (is_volatile)
-                                       ig.Emit (OpCodes.Volatile);
-
                                IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
-                               if (ff != null)
-                               {
+                               if (ff != null) {
                                        ig.Emit (OpCodes.Ldflda, FieldInfo);
                                        ig.Emit (OpCodes.Ldflda, ff.Element);
-                               }
-                               else {
+                               } else {
+                                       if (is_volatile)
+                                               ig.Emit (OpCodes.Volatile);
+
                                        ig.Emit (OpCodes.Ldfld, FieldInfo);
                                }
                        }
@@ -3403,16 +4695,19 @@ namespace Mono.CSharp {
                        bool is_static = (fa & FieldAttributes.Static) != 0;
                        bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
                        ILGenerator ig = ec.ig;
-                       prepared = prepare_for_load;
 
                        if (is_readonly && !ec.IsConstructor){
                                Report_AssignToReadonly (source);
                                return;
                        }
 
-                       EmitInstance (ec, prepare_for_load);
+                       //
+                       // String concatenation creates a new string instance 
+                       //
+                       prepared = prepare_for_load && !(source is StringConcat);
+                       EmitInstance (ec, prepared);
 
-                       source.Emit (ec);
+                       source.Emit (ec);                       
                        if (leave_copy) {
                                ec.ig.Emit (OpCodes.Dup);
                                if (!FieldInfo.IsStatic) {
@@ -3452,9 +4747,8 @@ namespace Mono.CSharp {
                        FieldBase f = TypeManager.GetField (FieldInfo);
                        if (f != null){
                                if ((f.ModFlags & Modifiers.VOLATILE) != 0){
-                                       Report.Warning (420, 1, loc, "`{0}': A volatile fields cannot be passed using a ref or out parameter",
+                                       Report.Warning (420, 1, loc, "`{0}': A volatile field references will not be treated as volatile", 
                                                        f.GetSignatureForError ());
-                                       return;
                                }
                                        
                                if ((mode & AddressOp.Store) != 0)
@@ -3536,8 +4830,6 @@ namespace Mono.CSharp {
                LocalTemporary temp;
                bool prepared;
 
-               internal static PtrHashtable AccessorTable = new PtrHashtable (); 
-
                public PropertyExpr (Type containerType, PropertyInfo pi, Location l)
                {
                        PropertyInfo = pi;
@@ -3617,7 +4909,7 @@ namespace Mono.CSharp {
                // We also perform the permission checking here, as the PropertyInfo does not
                // hold the information for the accessibility of its setter/getter
                //
-               // TODO: can use TypeManager.GetProperty to boost performance
+               // TODO: Refactor to use some kind of cache together with GetPropertyFromAccessor
                void ResolveAccessors (Type containerType)
                {
                        FindAccessors (containerType);
@@ -3628,7 +4920,6 @@ namespace Mono.CSharp {
                                if (md != null)
                                        md.SetMemberIsUsed ();
 
-                               AccessorTable [getter] = PropertyInfo;
                                is_static = getter.IsStatic;
                        }
 
@@ -3638,7 +4929,6 @@ namespace Mono.CSharp {
                                if (md != null)
                                        md.SetMemberIsUsed ();
 
-                               AccessorTable [setter] = PropertyInfo;
                                is_static = setter.IsStatic;
                        }
                }
@@ -3695,7 +4985,16 @@ namespace Mono.CSharp {
                        Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
                                Name, sig.ToString ());
                }
-               
+
+               public bool IsAccessibleFrom (Type invocation_type, bool lvalue)
+               {
+                       bool dummy;
+                       MethodInfo accessor = lvalue ? setter : getter;
+                       if (accessor == null && lvalue)
+                               accessor = getter;
+                       return accessor != null && IsAccessorAccessible (invocation_type, accessor, out dummy);
+               }
+
                override public Expression DoResolve (EmitContext ec)
                {
                        if (resolved)
@@ -3765,8 +5064,13 @@ namespace Mono.CSharp {
                override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
                        if (right_side == EmptyExpression.OutAccess) {
-                               Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter",
+                               if (ec.CurrentBlock.Toplevel.GetTransparentIdentifier (PropertyInfo.Name) != null) {
+                                       Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter",
+                                           PropertyInfo.Name);
+                               } else {
+                                       Report.Error (206, loc, "A property or indexer `{0}' may not be passed as `ref' or `out' parameter",
                                              GetSignatureForError ());
+                               }
                                return null;
                        }
 
@@ -3851,7 +5155,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, getter, null, loc, prepared, false);
+                       Invocation.EmitCall (ec, IsBase, InstanceExpression, getter, null, loc, prepared, false);
                        
                        if (leave_copy) {
                                ec.ig.Emit (OpCodes.Dup);
@@ -3869,10 +5173,15 @@ namespace Mono.CSharp {
                {
                        Expression my_source = source;
 
-                       prepared = prepare_for_load;
-                       
-                       if (prepared) {
+                       if (prepare_for_load) {
+                               if (source is StringConcat)
+                                       EmitInstance (ec, false);
+                               else
+                                       prepared = true;                                        
+
                                source.Emit (ec);
+                               
+                               prepared = true;
                                if (leave_copy) {
                                        ec.ig.Emit (OpCodes.Dup);
                                        if (!is_static) {
@@ -3882,17 +5191,15 @@ namespace Mono.CSharp {
                                }
                        } else if (leave_copy) {
                                source.Emit (ec);
-                               if (!is_static) {
-                                       temp = new LocalTemporary (this.Type);
-                                       temp.Store (ec);
-                               }
+                               temp = new LocalTemporary (this.Type);
+                               temp.Store (ec);
                                my_source = temp;
                        }
-                       
+
                        ArrayList args = new ArrayList (1);
                        args.Add (new Argument (my_source, Argument.AType.Expression));
                        
-                       Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared);
+                       Invocation.EmitCall (ec, IsBase, InstanceExpression, setter, args, loc, false, prepared);
                        
                        if (temp != null) {
                                temp.Emit (ec);
@@ -3906,12 +5213,11 @@ namespace Mono.CSharp {
        /// </summary>
        public class EventExpr : MemberExpr {
                public readonly EventInfo EventInfo;
+               public bool IsBase;
 
                bool is_static;
                MethodInfo add_accessor, remove_accessor;
 
-               internal static PtrHashtable AccessorTable = new PtrHashtable (); 
-               
                public EventExpr (EventInfo ei, Location loc)
                {
                        EventInfo = ei;
@@ -3920,11 +5226,6 @@ namespace Mono.CSharp {
 
                        add_accessor = TypeManager.GetAddMethod (ei);
                        remove_accessor = TypeManager.GetRemoveMethod (ei);
-                       if (add_accessor != null)
-                               AccessorTable [add_accessor] = ei;
-                       if (remove_accessor != null)
-                               AccessorTable [remove_accessor] = ei;
-                       
                        if (add_accessor.IsStatic || remove_accessor.IsStatic)
                                is_static = true;
 
@@ -3969,15 +5270,13 @@ namespace Mono.CSharp {
 
                        if (EventInfo.DeclaringType == ec.ContainerType ||
                            TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
-                               MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo);
+                               EventField mi = TypeManager.GetEventField (EventInfo);
 
                                if (mi != null) {
-                                       MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec.ContainerType, mi, loc);
+                                       if (!ec.IsInObsoleteScope)
+                                               mi.CheckObsoleteness (loc);
 
-                                       if (ml == null) {
-                                               Report.Error (-200, loc, "Internal error!!");
-                                               return null;
-                                       }
+                                       FieldExpr ml = new FieldExpr (mi.FieldBuilder, loc);
 
                                        InstanceExpression = null;
                                
@@ -4005,6 +5304,11 @@ namespace Mono.CSharp {
                        if (InstanceExpression == null)
                                return false;
 
+                       if (IsBase && add_accessor.IsAbstract) {
+                               Error_CannotCallAbstractBase(TypeManager.CSharpSignature(add_accessor));
+                               return false;
+                       }
+
                        //
                        // This is using the same mechanism as the CS1540 check in PropertyExpr.
                        // However, in the Event case, we reported a CS0122 instead.
@@ -4020,6 +5324,13 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               public bool IsAccessibleFrom (Type invocation_type)
+               {
+                       bool dummy;
+                       return IsAccessorAccessible (invocation_type, add_accessor, out dummy) &&
+                               IsAccessorAccessible (invocation_type, remove_accessor, out dummy);
+               }
+
                public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
                        return DoResolve (ec);
@@ -4071,10 +5382,10 @@ namespace Mono.CSharp {
                        
                        if (source_del.IsAddition)
                                Invocation.EmitCall (
-                                       ec, false, IsStatic, InstanceExpression, add_accessor, args, loc);
+                                       ec, IsBase, InstanceExpression, add_accessor, args, loc);
                        else
                                Invocation.EmitCall (
-                                       ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc);
+                                       ec, IsBase, InstanceExpression, remove_accessor, args, loc);
                }
        }
 
@@ -4147,5 +5458,76 @@ namespace Mono.CSharp {
                        EmitLoadAddress (ec);
                }
        }
-       
+
+       /// 
+       /// Handles `var' contextual keyword; var becomes a keyword only
+       /// if no type called var exists in a variable scope
+       /// 
+       public class VarExpr : SimpleName
+       {
+               // Used for error reporting only
+               ArrayList initializer;
+
+               public VarExpr (string name, Location loc)
+                       : base (name, loc)
+               {
+               }
+
+               public ArrayList VariableInitializer {
+                       set {
+                               this.initializer = value;
+                       }
+               }
+
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       if (type != null)
+                               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 == TypeManager.anonymous_method_type) {
+                               Report.Error (815, loc, "An implicitly typed local variable declaration cannot be initialized with `{0}'",
+                                             right_side.GetSignatureForError ());
+                               return null;
+                       }
+
+                       eclass = ExprClass.Variable;
+                       return this;
+               }
+
+               protected override void Error_TypeOrNamespaceNotFound (IResolveContext ec)
+               {
+                       if (ec is FieldBase) {
+                               Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration");
+                               return;
+                       }
+
+                       base.Error_TypeOrNamespaceNotFound (ec);
+               }
+
+               public override TypeExpr ResolveAsContextualType (IResolveContext rc, bool silent)
+               {
+                       TypeExpr te = base.ResolveAsContextualType (rc, true);
+                       if (te != null)
+                               return te;
+
+                       if (initializer == null)
+                               return null;
+                       
+                       // TODO: refactor, the error is reported too many times
+                       if (initializer.Count > 1) {
+                               Location loc = ((Mono.CSharp.CSharpParser.VariableDeclaration)initializer [1]).Location;
+                               Report.Error (819, loc, "An implicitly typed local variable declaration cannot include multiple declarators");
+                               return null;
+                       }
+                               
+                       Expression variable_initializer = ((Mono.CSharp.CSharpParser.VariableDeclaration)initializer [0]).expression_or_array_initializer;
+                       if (variable_initializer == null) {
+                               Report.Error (818, loc, "An implicitly typed local variable declarator must include an initializer");
+                               return null;
+                       }
+                       
+                       return null;
+               }
+       }
 }