2008-03-27 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / ecore.cs
index 10e4a0b626fc3667cacd489054a61f18e031177b..6beb5fab57d9b4711adb2684915f30f65b17a96f 100644 (file)
@@ -133,11 +133,11 @@ namespace Mono.CSharp {
                }
 
                // Not nice but we have broken hierarchy.
-               public virtual void CheckMarshalByRefAccess ()
+               public virtual void CheckMarshalByRefAccess (EmitContext ec)
                {
                }
 
-               public virtual bool GetAttributableValue (Type valueType, out object value)
+               public virtual bool GetAttributableValue (Type value_type, out object value)
                {
                        Attribute.Error_AttributeArgumentNotValid (loc);
                        value = null;
@@ -165,8 +165,7 @@ namespace Mono.CSharp {
                                return TypeManager.IsPrivateAccessible (invocation_type, mi.DeclaringType) ||
                                        TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
 
-                       if (mi.DeclaringType.Assembly == invocation_type.Assembly ||
-                                       TypeManager.IsFriendAssembly (mi.DeclaringType.Assembly)) {
+                       if (TypeManager.IsThisOrFriendAssembly (mi.DeclaringType.Assembly)) {
                                if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
                                        return true;
                        } else {
@@ -185,6 +184,12 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               public virtual bool IsNull {
+                       get {
+                               return false;
+                       }
+               }
+
                /// <summary>
                ///   Performs semantic analysis on the Expression
                /// </summary>
@@ -335,12 +340,28 @@ namespace Mono.CSharp {
 
                public virtual void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
                {
-                       if (Type.FullName == target.FullName){
+                       // The error was already reported as CS1660
+                       if (type == TypeManager.anonymous_method_type)
+                               return;
+
+                       if (TypeManager.IsGenericParameter (Type) && TypeManager.IsGenericParameter (target) && type.Name == target.Name) {
+#if GMCS_SOURCE
+                               string sig1 = type.DeclaringMethod == null ?
+                                       TypeManager.CSharpName (type.DeclaringType) :
+                                       TypeManager.CSharpSignature (type.DeclaringMethod);
+                               string sig2 = target.DeclaringMethod == null ?
+                                       TypeManager.CSharpName (target.DeclaringType) :
+                                       TypeManager.CSharpSignature (target.DeclaringMethod);
                                Report.ExtraInformation (loc,
                                        String.Format (
-                                       "The type {0} has two conflicting definitions, one comes from {1} and the other from {2}",
+                                               "The generic parameter `{0}' of `{1}' cannot be converted to the generic parameter `{0}' of `{2}' (in the previous ",
+                                               Type.Name, sig1, sig2));
+#endif
+                       } else if (Type.FullName == target.FullName){
+                               Report.ExtraInformation (loc,
+                                       String.Format (
+                                       "The type `{0}' has two conflicting definitions, one comes from `{1}' and the other from `{2}' (in the previous ",
                                        Type.FullName, Type.Assembly.FullName, target.Assembly.FullName));
-                                                        
                        }
 
                        if (expl) {
@@ -369,9 +390,8 @@ 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));
                }
 
@@ -381,6 +401,11 @@ namespace Mono.CSharp {
                                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);
@@ -551,10 +576,10 @@ namespace Mono.CSharp {
                /// </remarks>
                public abstract void Emit (EmitContext ec);
 
-               public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               public virtual void EmitBranchable (EmitContext ec, Label target, bool on_true)
                {
                        Emit (ec);
-                       ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+                       ec.ig.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
                }
 
                /// <summary>
@@ -572,22 +597,25 @@ namespace Mono.CSharp {
                ///   Returns a fully formed expression after a MemberLookup
                /// </summary>
                /// 
-               public static Expression ExprClassFromMemberInfo (Type containerType, MemberInfo mi, Location loc)
+               public static Expression ExprClassFromMemberInfo (Type container_type, MemberInfo mi, Location loc)
                {
                        if (mi is EventInfo)
                                return new EventExpr ((EventInfo) mi, loc);
-                       else if (mi is FieldInfo)
-                               return new FieldExpr ((FieldInfo) mi, loc);
-                       else if (mi is PropertyInfo)
-                               return new PropertyExpr (containerType, (PropertyInfo) mi, loc);
-                       else if (mi is Type){
+                       else if (mi is FieldInfo) {
+                               FieldInfo fi = (FieldInfo) mi;
+                               if (fi.IsLiteral || (fi.IsInitOnly && fi.FieldType == TypeManager.decimal_type))
+                                       return new ConstantExpr (fi, loc);
+                               return new FieldExpr (fi, loc);
+                       } else if (mi is PropertyInfo)
+                               return new PropertyExpr (container_type, (PropertyInfo) mi, loc);
+                       else if (mi is Type) {
                                return new TypeExpression ((System.Type) mi, loc);
                        }
 
                        return null;
                }
 
-               protected static ArrayList almostMatchedMembers = new ArrayList (4);
+               protected static ArrayList almost_matched_members = new ArrayList (4);
 
                //
                // FIXME: Probably implement a cache for (t,name,current_access_set)?
@@ -633,10 +661,10 @@ namespace Mono.CSharp {
                                                       string name, MemberTypes mt,
                                                       BindingFlags bf, Location loc)
                {
-                       almostMatchedMembers.Clear ();
+                       almost_matched_members.Clear ();
 
                        MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type,
-                                                                    queried_type, mt, bf, name, almostMatchedMembers);
+                                                                    queried_type, mt, bf, name, almost_matched_members);
 
                        if (mi == null)
                                return null;
@@ -758,18 +786,18 @@ namespace Mono.CSharp {
 
                        // No errors were reported by MemberLookup, but there was an error.
                        return Error_MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type,
-                                       name, null, mt, bf, loc);
+                                       name, null, mt, bf);
                }
 
-               protected Expression Error_MemberLookupFailed (Type container_type, Type qualifier_type,
+               protected virtual Expression Error_MemberLookupFailed (Type container_type, Type qualifier_type,
                                                       Type queried_type, string name, string class_name,
-                                                          MemberTypes mt, BindingFlags bf, Location loc)
+                                                          MemberTypes mt, BindingFlags bf)
                {
-                       if (almostMatchedMembers.Count != 0) {
-                               for (int i = 0; i < almostMatchedMembers.Count; ++i) {
-                                       MemberInfo m = (MemberInfo) almostMatchedMembers [i];
+                       if (almost_matched_members.Count != 0) {
+                               for (int i = 0; i < almost_matched_members.Count; ++i) {
+                                       MemberInfo m = (MemberInfo) almost_matched_members [i];
                                        for (int j = 0; j < i; ++j) {
-                                               if (m == almostMatchedMembers [j]) {
+                                               if (m == almost_matched_members [j]) {
                                                        m = null;
                                                        break;
                                                }
@@ -797,7 +825,7 @@ namespace Mono.CSharp {
                                                ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m));
                                        }
                                }
-                               almostMatchedMembers.Clear ();
+                               almost_matched_members.Clear ();
                                return null;
                        }
 
@@ -825,7 +853,7 @@ namespace Mono.CSharp {
                                        Report.Error (103, loc, "The name `{0}' does not exist in the current context",
                                                name);
                                } else {
-                                       Error_TypeDoesNotContainDefinition (loc, queried_type, name);
+                                       Error_TypeDoesNotContainDefinition (queried_type, name);
                                }
                                return null;
                        }
@@ -859,6 +887,11 @@ namespace Mono.CSharp {
                        return new MethodGroupExpr (members, type, loc);
                }
 
+               protected virtual void Error_NegativeArrayIndex (Location loc)
+               {
+                       throw new NotImplementedException ();
+               }
+
                /// <summary>
                ///   Returns an expression that can be used to invoke operator true
                ///   on the expression if it exists.
@@ -880,12 +913,6 @@ namespace Mono.CSharp {
                static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
                {
                        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) as MethodGroupExpr;
                        if (operator_group == null)
                                return null;
@@ -893,12 +920,12 @@ namespace Mono.CSharp {
                        ArrayList arguments = new ArrayList (1);
                        arguments.Add (new Argument (e, Argument.AType.Expression));
                        operator_group = operator_group.OverloadResolve (
-                               ec, arguments, false, loc);
+                               ec, ref arguments, false, loc);
 
                        if (operator_group == null)
                                return null;
 
-                       return new StaticCallExpr ((MethodInfo) operator_group, arguments, loc);
+                       return new UserOperatorCall (operator_group, arguments, null, loc);
                }
 
                /// <summary>
@@ -1050,7 +1077,7 @@ namespace Mono.CSharp {
                                if (t == TypeManager.enum_type)
                                        ig.Emit (OpCodes.Ldind_Ref);
                                else
-                                       LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
+                                       LoadFromPtr (ig, TypeManager.GetEnumUnderlyingType (t));
                        } else if (t.IsValueType || TypeManager.IsGenericParameter (t))
                                ig.Emit (OpCodes.Ldobj, t);
                        else if (t.IsPointer)
@@ -1065,7 +1092,7 @@ namespace Mono.CSharp {
                public static void StoreFromPtr (ILGenerator ig, Type type)
                {
                        if (TypeManager.IsEnumType (type))
-                               type = TypeManager.EnumToUnderlying (type);
+                               type = TypeManager.GetEnumUnderlyingType (type);
                        if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
                                ig.Emit (OpCodes.Stind_I4);
                        else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
@@ -1116,34 +1143,41 @@ namespace Mono.CSharp {
                                return 0;
                }
 
-               public static void Error_NegativeArrayIndex (Location loc)
-               {
-                       Report.Error (248, loc, "Cannot create an array with a negative size");
-               }
-
                protected void Error_CannotCallAbstractBase (string name)
                {
                        Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
                }
                
+               protected void Error_CannotModifyIntermediateExpressionValue (EmitContext ec)
+               {
+                       Report.SymbolRelatedToPreviousError (type);
+                       if (ec.CurrentInitializerVariable != null) {
+                               Report.Error (1918, loc, "Members of a value type property `{0}' cannot be assigned with an object initializer",
+                                       GetSignatureForError ());
+                       } else {
+                               Report.Error (1612, loc, "Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable",
+                                       GetSignatureForError ());
+                       }
+               }
+
                //
                // Converts `source' to an int, uint, long or ulong.
                //
-               public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc)
+               public Expression ConvertExpressionToArrayIndex (EmitContext ec, Expression source)
                {
-                       Expression target;
+                       Expression converted;
                        
                        using (ec.With (EmitContext.Flags.CheckState, true)) {
-                               target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
-                               if (target == null)
-                                       target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
-                               if (target == null)
-                                       target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
-                               if (target == null)
-                                       target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
-
-                               if (target == null) {
-                                       source.Error_ValueCannotBeConverted (ec, loc, TypeManager.int32_type, false);
+                               converted = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, source.loc);
+                               if (converted == null)
+                                       converted = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, source.loc);
+                               if (converted == null)
+                                       converted = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, source.loc);
+                               if (converted == null)
+                                       converted = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, source.loc);
+
+                               if (converted == null) {
+                                       source.Error_ValueCannotBeConverted (ec, source.loc, TypeManager.int32_type, false);
                                        return null;
                                }
                        }
@@ -1151,24 +1185,15 @@ namespace Mono.CSharp {
                        //
                        // Only positive constants are allowed at compile time
                        //
-                       if (target is Constant){
-                               if (target is IntConstant){
-                                       if (((IntConstant) target).Value < 0){
-                                               Error_NegativeArrayIndex (loc);
-                                               return null;
-                                       }
-                               }
-
-                               if (target is LongConstant){
-                                       if (((LongConstant) target).Value < 0){
-                                               Error_NegativeArrayIndex (loc);
-                                               return null;
-                                       }
+                       Constant c = converted as Constant;
+                       if (c != null) {
+                               if (c.IsNegative) {
+                                       Error_NegativeArrayIndex (source.loc);
                                }
-                               
+                               return c;
                        }
 
-                       return target;
+                       return new ArrayIndexCast (converted).Resolve (ec);
                }
 
                //
@@ -1203,6 +1228,36 @@ namespace Mono.CSharp {
 
                        return cloned;
                }
+
+               public virtual Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotImplementedException (
+                               "Expression tree conversion not implemented for " + GetType ());
+               }
+
+               protected Expression CreateExpressionFactoryCall (string name, ArrayList args)
+               {
+                       return CreateExpressionFactoryCall (name, null, args, loc);
+               }
+
+               protected Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, ArrayList args)
+               {
+                       return CreateExpressionFactoryCall (name, typeArguments, args, loc);
+               }
+
+               public static Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, ArrayList args, Location loc)
+               {
+                       TypeExpr texpr = TypeManager.expression_type_expr;
+                       if (texpr == null) {
+                               Type t = TypeManager.CoreLookupType ("System.Linq.Expressions", "Expression", Kind.Class, true);
+                               if (t == null)
+                                       return null;
+
+                               TypeManager.expression_type_expr = texpr = new TypeExpression (t, Location.Null);
+                       }
+
+                       return new Invocation (new MemberAccess (texpr, name, typeArguments, loc), args);
+               }
        }
 
        /// <summary>
@@ -1248,16 +1303,49 @@ namespace Mono.CSharp {
        ///   would be "unsigned int".
        ///
        /// </summary>
-       public class EmptyCast : Expression {
+       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);
+
+                       //
+                       // No double conversion required when wrapping nullable types
+                       //
+                       if (TypeManager.IsNullableType (type)) {
+                               EmptyCast empty_cast = child as EmptyCast;
+                               if (empty_cast != null) {
+                                       if (TypeManager.IsNullableTypeOf (empty_cast.type, type))
+                                               throw new InternalErrorException ("Missing nullable underlying type conversion {0} != {1}",
+                                                       TypeManager.CSharpName (empty_cast.type), TypeManager.CSharpName (type));
+
+                                       empty_cast.type = type;
+                                       return empty_cast;
+                               }
+                       }
+                       
+                       return new EmptyCast (child, type);
+               }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       ArrayList args = new ArrayList (2);
+                       args.Add (new Argument (child.CreateExpressionTree (ec)));
+                       args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+                       return CreateExpressionFactoryCall (ec.CheckState ? "ConvertChecked" : "Convert", args);
+               }
 
                public override Expression DoResolve (EmitContext ec)
                {
@@ -1272,9 +1360,9 @@ namespace Mono.CSharp {
                        child.Emit (ec);
                }
 
-               public override bool GetAttributableValue (Type valueType, out object value)
+               public override bool GetAttributableValue (Type value_type, out object value)
                {
-                       return child.GetAttributableValue (valueType, out value);
+                       return child.GetAttributableValue (value_type, out value);
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -1319,7 +1407,7 @@ namespace Mono.CSharp {
                        foreach (MethodInfo oper in mi) {
                                ParameterData pd = TypeManager.GetParameterData (oper);
 
-                               if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
+                               if (pd.ParameterType (0) == child.Type && TypeManager.TypeToCoreType (oper.ReturnType) == type)
                                        return oper;
                        }
 
@@ -1374,7 +1462,7 @@ namespace Mono.CSharp {
                        foreach (MethodInfo oper in mi) {
                                ParameterData pd = TypeManager.GetParameterData (oper);
 
-                               if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
+                               if (pd.ParameterType (0) == child.Type && TypeManager.TypeToCoreType (oper.ReturnType) == type)
                                        return oper;
                        }
 
@@ -1417,7 +1505,7 @@ namespace Mono.CSharp {
                                foreach (MethodInfo oper in all_oper) {
                                        ParameterData pd = TypeManager.GetParameterData (oper);
                                        if (pd.ParameterType (0) == TypeManager.decimal_type)
-                                               operators.Add (oper.ReturnType, oper);
+                                               operators.Add (TypeManager.TypeToCoreType (oper.ReturnType), oper);
                                }
                        }
 
@@ -1461,10 +1549,10 @@ namespace Mono.CSharp {
                        return child.GetValue ();
                }
 
-               public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
+               public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
                {
                        // FIXME: check that 'type' can be converted to 'target_type' first
-                       return child.ConvertExplicitly (inCheckedContext, target_type);
+                       return child.ConvertExplicitly (in_checked_context, target_type);
                }
 
                public override Constant Increment ()
@@ -1480,6 +1568,14 @@ namespace Mono.CSharp {
                        get { return child.IsNegative; }
                }
 
+               public override bool IsNull {
+                       get { return child.IsNull; }
+               }
+
+               public override bool IsZeroInteger {
+                       get { return child.IsZeroInteger; }
+               }               
+               
                public override void Emit (EmitContext ec)
                {
                        child.Emit (ec);
@@ -1522,7 +1618,7 @@ namespace Mono.CSharp {
                        Child.Emit (ec);
                }
 
-               public override bool GetAttributableValue (Type valueType, out object value)
+               public override bool GetAttributableValue (Type value_type, out object value)
                {
                        value = GetTypedValue ();
                        return true;
@@ -1574,12 +1670,12 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override Constant ConvertExplicitly(bool inCheckedContext, Type target_type)
+               public override Constant ConvertExplicitly(bool in_checked_context, Type target_type)
                {
                        if (Child.Type == target_type)
                                return Child;
 
-                       return Child.ConvertExplicitly (inCheckedContext, target_type);
+                       return Child.ConvertExplicitly (in_checked_context, target_type);
                }
 
                public override Constant ConvertImplicitly (Type type)
@@ -1913,6 +2009,12 @@ namespace Mono.CSharp {
                        second_valid = true;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       // A cast has no expresion tree representation
+                       return child.CreateExpressionTree (ec);
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        // This should never be invoked, we are born in fully
@@ -1928,7 +2030,11 @@ namespace Mono.CSharp {
 
                        if (second_valid)
                                ec.ig.Emit (op2);
-               }                       
+               }
+
+               public Type UnderlyingType {
+                       get { return child.Type; }
+               }
        }
 
        /// <summary>
@@ -1965,6 +2071,114 @@ namespace Mono.CSharp {
                                ec.ig.Emit (OpCodes.Castclass, type);
                }
        }
+
+       //
+       // Used when resolved expression has different representations for
+       // expression trees and emit phase
+       //
+       public class ReducedExpression : Expression
+       {
+               class ReducedConstantExpression : Constant
+               {
+                       readonly Constant expr;
+                       readonly Expression orig_expr;
+
+                       public ReducedConstantExpression (Constant expr, Expression orig_expr)
+                               : base (expr.Location)
+                       {
+                               this.expr = expr;
+                               this.orig_expr = orig_expr;
+                       }
+
+                       public override string AsString ()
+                       {
+                               return expr.AsString ();
+                       }
+
+                       public override Expression CreateExpressionTree (EmitContext ec)
+                       {
+                               return orig_expr.CreateExpressionTree (ec);
+                       }
+
+                       public override object GetValue ()
+                       {
+                               return expr.GetValue ();
+                       }
+
+                       public override Constant ConvertExplicitly (bool in_checked_context, Type target_type)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public override Expression DoResolve (EmitContext ec)
+                       {
+                               eclass = expr.eclass;
+                               type = expr.Type;
+                               return this;
+                       }
+
+                       public override Constant Increment ()
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       public override bool IsDefaultValue {
+                               get {
+                                       return expr.IsDefaultValue;
+                               }
+                       }
+
+                       public override bool IsNegative {
+                               get {
+                                       return expr.IsNegative;
+                               }
+                       }
+
+                       public override void Emit (EmitContext ec)
+                       {
+                               expr.Emit (ec);
+                       }
+               }
+
+               readonly Expression expr, orig_expr;
+
+               private ReducedExpression (Expression expr, Expression orig_expr)
+               {
+                       this.expr = expr;
+                       this.orig_expr = orig_expr;
+               }
+
+               public static Expression Create (Constant expr, Expression original_expr)
+               {
+                       return new ReducedConstantExpression (expr, original_expr);
+               }
+
+               public static Expression Create (Expression expr, Expression original_expr)
+               {
+                       Constant c = expr as Constant;
+                       if (c != null)
+                               return Create (c, original_expr);
+
+                       return new ReducedExpression (expr, original_expr);
+               }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       return orig_expr.CreateExpressionTree (ec);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       eclass = expr.eclass;
+                       type = expr.Type;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       expr.Emit (ec);
+               }
+       }
        
        /// <summary>
        ///   SimpleName expressions are formed of a single word and only happen at the beginning 
@@ -2033,7 +2247,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);
@@ -2066,14 +2280,10 @@ namespace Mono.CSharp {
                        return SimpleNameResolve (ec, null, intermediate);
                }
 
-               private bool IsNestedChild (Type t, Type parent)
+               static bool IsNestedChild (Type t, Type parent)
                {
-                       if (parent == null)
-                               return false;
-
                        while (parent != null) {
-                               parent = TypeManager.DropGenericTypeArguments (parent);
-                               if (TypeManager.IsNestedChildOf (t, parent))
+                               if (TypeManager.IsNestedChildOf (t, TypeManager.DropGenericTypeArguments (parent)))
                                        return true;
 
                                parent = parent.BaseType;
@@ -2088,12 +2298,8 @@ namespace Mono.CSharp {
                                return null;
 
                        DeclSpace ds = ec.DeclContainer;
-                       while (ds != null) {
-                               if (IsNestedChild (t, ds.TypeBuilder))
-                                       break;
-
+                       while (ds != null && !IsNestedChild (t, ds.TypeBuilder))
                                ds = ds.Parent;
-                       }
 
                        if (ds == null)
                                return null;
@@ -2178,7 +2384,7 @@ namespace Mono.CSharp {
                        if (Arguments != null) {
                                FullNamedExpression retval = ec.DeclContainer.LookupNamespaceOrType (SimpleName.RemoveGenericArity (Name), loc, true);
                                if (retval != null) {
-                                       Namespace.Error_TypeArgumentsCannotBeUsed (retval.Type, loc, "type");
+                                       Namespace.Error_TypeArgumentsCannotBeUsed (retval.Type, loc);
                                        return;
                                }
                        }
@@ -2284,38 +2490,52 @@ 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) {
+                               if (almost_matched == null && almost_matched_members.Count > 0) {
                                        almost_matched_type = lookup_ds.TypeBuilder;
-                                       almost_matched = (ArrayList) almostMatchedMembers.Clone ();
+                                       almost_matched = (ArrayList) almost_matched_members.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) {
+                               if (almost_matched == null && almost_matched_members.Count > 0) {
                                        almost_matched_type = ec.ContainerType;
-                                       almost_matched = (ArrayList) almostMatchedMembers.Clone ();
+                                       almost_matched = (ArrayList) almost_matched_members.Clone ();
                                }
                                e = ResolveAsTypeStep (ec, true);
                        }
@@ -2335,11 +2555,11 @@ namespace Mono.CSharp {
                                }
 
                                if (almost_matched != null)
-                                       almostMatchedMembers = almost_matched;
+                                       almost_matched_members = almost_matched;
                                if (almost_matched_type == null)
                                        almost_matched_type = ec.ContainerType;
                                Error_MemberLookupFailed (ec.ContainerType, null, almost_matched_type, Name,
-                                       ec.DeclContainer.Name, AllMemberTypes, AllBindingFlags, loc);
+                                       ec.DeclContainer.Name, AllMemberTypes, AllBindingFlags);
                                return null;
                        }
 
@@ -2357,7 +2577,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
@@ -2368,7 +2588,7 @@ namespace Mono.CSharp {
                                                if (!me.IsStatic &&
                                                    (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
                                                        Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
-                                                       return EmptyExpression.Null;
+                                                       return null;
                                                }
 
                                                //
@@ -2382,20 +2602,13 @@ namespace Mono.CSharp {
                                        left = new TypeExpression (ec.ContainerType, loc);
                                }
 
-                               e = me.ResolveMemberAccess (ec, left, loc, null);
-                               if (e == null)
-                                       return null;
-
-                               me = e as MemberExpr;
+                               me = me.ResolveMemberAccess (ec, left, loc, null);
                                if (me == null)
-                                       return e;
+                                       return null;
 
                                if (Arguments != null) {
-                                       MethodGroupExpr mg = me as MethodGroupExpr;
-                                       if (mg == null)
-                                               return null;
-
-                                       return mg.ResolveGeneric (ec, Arguments);
+                                       Arguments.Resolve (ec);
+                                       me.SetTypeArguments (Arguments);
                                }
 
                                if (!me.IsStatic && (me.InstanceExpression != null) &&
@@ -2486,9 +2699,9 @@ namespace Mono.CSharp {
                        return ds.CheckAccessLevel (Type);
                }
 
-               public virtual bool AsAccessible (DeclSpace ds, int flags)
+               public virtual bool AsAccessible (DeclSpace ds)
                {
-                       return ds.AsAccessible (Type, flags);
+                       return ds.IsAccessibleAs (Type);
                }
 
                public virtual bool IsClass {
@@ -2832,9 +3045,9 @@ namespace Mono.CSharp {
                        return texpr.CheckAccessLevel (ds);
                }
 
-               public override bool AsAccessible (DeclSpace ds, int flags)
+               public override bool AsAccessible (DeclSpace ds)
                {
-                       return texpr.AsAccessible (ds, flags);
+                       return texpr.AsAccessible (ds);
                }
 
                public override bool IsClass {
@@ -2860,6 +3073,8 @@ namespace Mono.CSharp {
        /// </summary>
        public abstract class MemberExpr : Expression
        {
+               protected bool is_base;
+
                /// <summary>
                ///   The name of this member.
                /// </summary>
@@ -2867,6 +3082,14 @@ namespace Mono.CSharp {
                        get;
                }
 
+               //
+               // When base.member is used
+               //
+               public bool IsBase {
+                       get { return is_base; }
+                       set { is_base = value; }
+               }
+
                /// <summary>
                ///   Whether this is an instance member.
                /// </summary>
@@ -2902,7 +3125,7 @@ namespace Mono.CSharp {
 
                // TODO: possible optimalization
                // Cache resolved constant result in FieldBuilder <-> expression map
-               public virtual Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
+               public virtual MemberExpr ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
                                                               SimpleName original)
                {
                        //
@@ -2927,12 +3150,16 @@ namespace Mono.CSharp {
                                if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
                                        return this;
 
-                               error176 (loc, GetSignatureForError ());
-                               return null;
+                               return ResolveExtensionMemberAccess (left);
                        }
 
                        InstanceExpression = left;
+                       return this;
+               }
 
+               protected virtual MemberExpr ResolveExtensionMemberAccess (Expression left)
+               {
+                       error176 (loc, GetSignatureForError ());
                        return this;
                }
 
@@ -2961,6 +3188,13 @@ namespace Mono.CSharp {
                        if (prepare_for_load)
                                ec.ig.Emit (OpCodes.Dup);
                }
+
+               public virtual void SetTypeArguments (TypeArguments ta)
+               {
+                       // TODO: need to get correct member type
+                       Report.Error (307, loc, "The property `{0}' cannot be used with type arguments",
+                               GetSignatureForError ());
+               }
        }
 
        /// 
@@ -2968,17 +3202,14 @@ namespace Mono.CSharp {
        /// 
        public class ExtensionMethodGroupExpr : MethodGroupExpr
        {
-               readonly NamespaceEntry namespaceEntry;
+               readonly NamespaceEntry namespace_entry;
                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; }
+                       this.namespace_entry = n;
                }
 
                public override bool IsStatic {
@@ -2986,14 +3217,14 @@ namespace Mono.CSharp {
                }
 
                public bool IsTopLevel {
-                       get { return namespaceEntry == null; }
+                       get { return namespace_entry == null; }
                }
 
                public override void EmitArguments (EmitContext ec, ArrayList arguments)
                {
                        if (arguments == null)
                                arguments = new ArrayList (1);                  
-                       arguments.Insert (0, new Argument (ExtensionExpression));
+                       arguments.Insert (0, extension_argument);
                        base.EmitArguments (ec, arguments);
                }
 
@@ -3001,37 +3232,30 @@ namespace Mono.CSharp {
                {
                        if (arguments == null)
                                arguments = new ArrayList (1);
-                       arguments.Insert (0, new Argument (ExtensionExpression));
+                       arguments.Insert (0, extension_argument);
                        base.EmitCall (ec, arguments);
                }
 
-               public override MethodGroupExpr OverloadResolve (EmitContext ec, ArrayList arguments, bool may_fail, Location loc)
+               public override MethodGroupExpr OverloadResolve (EmitContext ec, ref 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);
-
-                       // Restore original arguments
-                       arguments.RemoveAt (0);
+                       MethodGroupExpr mg = ResolveOverloadExtensions (ec, arguments, namespace_entry, loc);
 
+                       // Store resolved argument and restore original arguments
                        if (mg != null)
-                               return mg;
-                       
-                       if (!may_fail)
-                               return base.OverloadResolve (ec, arguments, may_fail, loc);
+                               ((ExtensionMethodGroupExpr)mg).extension_argument = (Argument)arguments [0];
+                       arguments.RemoveAt (0);
 
-                       return null;
+                       return mg;
                }
 
                MethodGroupExpr ResolveOverloadExtensions (EmitContext ec, ArrayList arguments, NamespaceEntry ns, Location loc)
                {
                        // Use normal resolve rules
-                       MethodGroupExpr mg = base.OverloadResolve (ec, arguments, true, loc);
+                       MethodGroupExpr mg = base.OverloadResolve (ec, ref arguments, ns != null, loc);
                        if (mg != null)
                                return mg;
 
@@ -3041,10 +3265,10 @@ namespace Mono.CSharp {
                        // Search continues
                        ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, null, Name);
                        if (e == null)
-                               return null;
+                               return base.OverloadResolve (ec, ref arguments, false, loc);
 
                        e.ExtensionExpression = ExtensionExpression;
-                       return e.ResolveOverloadExtensions (ec, arguments, e.namespaceEntry, loc);
+                       return e.ResolveOverloadExtensions (ec, arguments, e.namespace_entry, loc);
                }               
        }
 
@@ -3052,23 +3276,30 @@ namespace Mono.CSharp {
        ///   MethodGroupExpr represents a group of method candidates which
        ///   can be resolved to the best method overload
        /// </summary>
-       public class MethodGroupExpr : MemberExpr {
-               public readonly MethodBase [] Methods;
+       public class MethodGroupExpr : MemberExpr
+       {
+               public interface IErrorHandler
+               {
+                       bool NoExactMatch (EmitContext ec, MethodBase method);
+               }
+
+               public IErrorHandler CustomErrorHandler;                
+               public MethodBase [] Methods;
                MethodBase best_candidate;
-               bool has_type_arguments;
+               // TODO: make private
+               public TypeArguments type_arguments;
                bool identical_type_name;
-               bool is_base;
+               Type delegate_type;
                
                public MethodGroupExpr (MemberInfo [] mi, Type type, Location l)
+                       : this (type, l)
                {
                        Methods = new MethodBase [mi.Length];
                        mi.CopyTo (Methods, 0);
-                       eclass = ExprClass.MethodGroup;
-                       this.type = type;
-                       loc = l;
                }
 
                public MethodGroupExpr (ArrayList list, Type type, Location l)
+                       : this (type, l)
                {
                        try {
                                Methods = (MethodBase[])list.ToArray (typeof (MethodBase));
@@ -3082,28 +3313,29 @@ namespace Mono.CSharp {
                                throw;
                        }
 
-                       loc = l;
+
+               }
+
+               protected MethodGroupExpr (Type type, Location loc)
+               {
+                       this.loc = loc;
                        eclass = ExprClass.MethodGroup;
                        this.type = type;
                }
 
                public override Type DeclaringType {
                        get {
-                                //
-                                // We assume that the top-level type is in the end
-                                //
+                               //
+                               // We assume that the top-level type is in the end
+                               //
                                return Methods [Methods.Length - 1].DeclaringType;
-                                //return Methods [0].DeclaringType;
+                               //return Methods [0].DeclaringType;
                        }
                }
 
-               public bool HasTypeArguments {
-                       get {
-                               return has_type_arguments;
-                       }
-
+               public Type DelegateType {
                        set {
-                               has_type_arguments = value;
+                               delegate_type = value;
                        }
                }
 
@@ -3117,15 +3349,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               public virtual bool IsBase {
-                       get {
-                               return is_base;
-                       }
-                       set {
-                               is_base = value;
-                       }
-               }
-
                public override string GetSignatureForError ()
                {
                        if (best_candidate != null)
@@ -3142,6 +3365,9 @@ namespace Mono.CSharp {
 
                public override bool IsInstance {
                        get {
+                               if (best_candidate != null)
+                                       return !best_candidate.IsStatic;
+
                                foreach (MethodBase mb in Methods)
                                        if (!mb.IsStatic)
                                                return true;
@@ -3152,6 +3378,9 @@ namespace Mono.CSharp {
 
                public override bool IsStatic {
                        get {
+                               if (best_candidate != null)
+                                       return best_candidate.IsStatic;
+
                                foreach (MethodBase mb in Methods)
                                        if (mb.IsStatic)
                                                return true;
@@ -3170,102 +3399,90 @@ namespace Mono.CSharp {
                        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)
+               //
+               //  7.4.3.3  Better conversion from expression
+               //  Returns :   1    if a->p is better,
+               //              2    if a->q is better,
+               //              0 if neither is better
+               //
+               static int BetterExpressionConversion (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.
+                       if (argument_type == TypeManager.anonymous_method_type && RootContext.Version > LanguageVersion.ISO_2) {
                                //
-                               // 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'
+                               // Uwrap delegate from Expression<T>
                                //
-                               //  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;
+                               if (TypeManager.DropGenericTypeArguments (p) == TypeManager.expression_type) {
+                                       p = TypeManager.GetTypeArguments (p) [0];
+                                       q = TypeManager.GetTypeArguments (q) [0];
+                               }
+                               p = Delegate.GetInvokeMethod (null, p).ReturnType;
+                               q = Delegate.GetInvokeMethod (null, q).ReturnType;
+                       } else {
+                               if (argument_type == p)
+                                       return 1;
 
-                       Expression p_tmp = new EmptyExpression (p);
-                       Expression q_tmp = new EmptyExpression (q);
+                               if (argument_type == q)
+                                       return 2;
+                       }
 
-                       bool p_to_q = Convert.ImplicitConversionExists (ec, p_tmp, q);
-                       bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p);
+                       return BetterTypeConversion (ec, p, q);
+               }
 
-                       if (p_to_q && !q_to_p)
-                               return p;
+               //
+               // 7.4.3.4  Better conversion from type
+               //
+               public static int BetterTypeConversion (EmitContext ec, Type p, Type q)
+               {
+                       if (p == null || q == null)
+                               throw new InternalErrorException ("BetterTypeConversion got a null conversion");
 
-                       if (q_to_p && !p_to_q)
-                               return q;
-
-                       if (p == TypeManager.sbyte_type)
+                       if (p == TypeManager.int32_type) {
+                               if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
+                                       return 1;
+                       } else if (p == TypeManager.int64_type) {
+                               if (q == TypeManager.uint64_type)
+                                       return 1;
+                       } else 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)
+                                       return 1;
+                       } else 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)
+                                       return 1;
+                       }
+
+                       if (q == TypeManager.int32_type) {
+                               if (p == TypeManager.uint32_type || p == TypeManager.uint64_type)
+                                       return 2;
+                       } if (q == TypeManager.int64_type) {
+                               if (p == TypeManager.uint64_type)
+                                       return 2;
+                       } else if (q == TypeManager.sbyte_type) {
+                               if (p == TypeManager.byte_type || p == TypeManager.ushort_type ||
+                                       p == TypeManager.uint32_type || p == TypeManager.uint64_type)
+                                       return 2;
+                       } if (q == TypeManager.short_type) {
                                if (p == TypeManager.ushort_type || p == TypeManager.uint32_type ||
                                        p == TypeManager.uint64_type)
-                                       return q;
+                                       return 2;
+                       }
 
-                       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;
+                       // TODO: this is expensive
+                       Expression p_tmp = new EmptyExpression (p);
+                       Expression q_tmp = new EmptyExpression (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;
+                       bool p_to_q = Convert.ImplicitConversionExists (ec, p_tmp, q);
+                       bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p);
 
-                       return null;
+                       if (p_to_q && !q_to_p)
+                               return 1;
+
+                       if (q_to_p && !p_to_q)
+                               return 2;
+
+                       return 0;
                }
 
                /// <summary>
@@ -3309,16 +3526,16 @@ namespace Mono.CSharp {
                                        continue;
 
                                same = false;
-                               Type better = BetterConversion (ec, a, ct, bt);
+                               int result = BetterExpressionConversion (ec, a, ct, bt);
 
                                // for each argument, the conversion to 'ct' should be no worse than 
                                // the conversion to 'bt'.
-                               if (better == bt)
+                               if (result == 2)
                                        return false;
 
                                // for at least one argument, the conversion to 'ct' should be better than 
                                // the conversion to 'bt'.
-                               if (better == ct)
+                               if (result != 0)
                                        better_at_least_one = true;
                        }
 
@@ -3399,7 +3616,20 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
+               protected override MemberExpr ResolveExtensionMemberAccess (Expression left)
+               {
+                       if (!IsStatic)
+                               return base.ResolveExtensionMemberAccess (left);
+
+                       //
+                       // When left side is an expression and at least one candidate method is 
+                       // static, it can be extension method
+                       //
+                       InstanceExpression = left;
+                       return this;
+               }
+
+               public override MemberExpr ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
                                                                SimpleName original)
                {
                        if (!(left is TypeExpr) &&
@@ -3408,6 +3638,12 @@ namespace Mono.CSharp {
 
                        return base.ResolveMemberAccess (ec, left, loc, original);
                }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       return new Cast (new TypeExpression (typeof (MethodInfo), loc),
+                               new TypeOfMethod ((MethodInfo)best_candidate, loc));
+               }
                
                override public Expression DoResolve (EmitContext ec)
                {
@@ -3433,7 +3669,7 @@ namespace Mono.CSharp {
                
                public virtual void EmitArguments (EmitContext ec, ArrayList arguments)
                {
-                       Invocation.EmitArguments (ec, best_candidate, arguments, false, null);  
+                       Invocation.EmitArguments (ec, arguments, false, null);  
                }
                
                public virtual void EmitCall (EmitContext ec, ArrayList arguments)
@@ -3441,12 +3677,201 @@ namespace Mono.CSharp {
                        Invocation.EmitCall (ec, IsBase, InstanceExpression, best_candidate, arguments, loc);                   
                }
 
+               protected virtual void Error_InvalidArguments (EmitContext ec, Location loc, int idx, MethodBase method,
+                                                                                                       Argument a, ParameterData expected_par, Type paramType)
+               {
+                       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.REF | Parameter.Modifier.OUT)) ^
+                               (a.Modifier & (Parameter.Modifier.REF | Parameter.Modifier.OUT))) != 0) {
+                               if ((mod & Parameter.Modifier.ISBYREF) == 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 = a.GetSignatureForError ();
+                               string p2 = TypeManager.CSharpName (paramType);
+
+                               if (p1 == p2) {
+                                       Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous ");
+                                       Report.SymbolRelatedToPreviousError (a.Expr.Type);
+                                       Report.SymbolRelatedToPreviousError (paramType);
+                               }
+                               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;
+               }               
+
                public static bool IsAncestralType (Type first_type, Type second_type)
                {
                        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, ref bool params_expanded_form)
+               {
+                       MethodBase candidate = method;
+
+                       ParameterData pd = TypeManager.GetParameterData (candidate);
+                       int param_count = GetApplicableParametersCount (candidate, pd);
+
+                       if (arg_count != param_count) {
+                               if (!pd.HasParams)
+                                       return int.MaxValue - 10000 + Math.Abs (arg_count - param_count);
+                               if (arg_count < param_count - 1)
+                                       return int.MaxValue - 10000 + Math.Abs (arg_count - param_count);
+                       }
+
+#if GMCS_SOURCE
+                       //
+                       // 1. Handle generic method using type arguments when specified or type inference
+                       //
+                       if (TypeManager.IsGenericMethod (candidate)) {
+                               if (type_arguments != null) {
+                                       Type [] g_args = candidate.GetGenericArguments ();
+                                       if (g_args.Length != type_arguments.Count)
+                                               return int.MaxValue - 20000 + Math.Abs (type_arguments.Count - g_args.Length);
+
+                                       // TODO: Don't create new method, create Parameters only
+                                       method = ((MethodInfo) candidate).MakeGenericMethod (type_arguments.Arguments);
+                                       candidate = method;
+                                       pd = TypeManager.GetParameterData (candidate);
+                               } else {
+                                       int score = TypeManager.InferTypeArguments (ec, arguments, ref candidate);
+                                       if (score != 0)
+                                               return score - 20000;
+
+                                       if (TypeManager.IsGenericMethodDefinition (candidate))
+                                               throw new InternalErrorException ("A generic method `{0}' definition took part in overload resolution",
+                                                       TypeManager.CSharpSignature (candidate));
+
+                                       pd = TypeManager.GetParameterData (candidate);
+                               }
+                       } else {
+                               if (type_arguments != null)
+                                       return int.MaxValue - 15000;
+                       }
+#endif                 
+
+                       //
+                       // 2. Each argument has to be implicitly convertible to method parameter
+                       //
+                       method = candidate;
+                       Parameter.Modifier p_mod = 0;
+                       Type pt = null;
+                       for (int i = 0; i < arg_count; i++) {
+                               Argument a = (Argument) arguments [i];
+                               Parameter.Modifier a_mod = a.Modifier &
+                                       ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
+
+                               if (p_mod != Parameter.Modifier.PARAMS) {
+                                       p_mod = pd.ParameterModifier (i) & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
+
+                                       if (p_mod == Parameter.Modifier.ARGLIST) {
+                                               if (a.Type == TypeManager.runtime_argument_handle_type)
+                                                       continue;
+
+                                               p_mod = 0;
+                                       }
+
+                                       pt = pd.ParameterType (i);
+                               } else {
+                                       params_expanded_form = true;
+                               }
+
+                               int score = 1;
+                               if (!params_expanded_form)
+                                       score = IsArgumentCompatible (ec, a_mod, a, p_mod & ~Parameter.Modifier.PARAMS, pt);
+
+                               if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0) {
+                                       // It can be applicable in expanded form
+                                       score = IsArgumentCompatible (ec, a_mod, a, 0, pt.GetElementType ());
+                                       if (score == 0)
+                                               params_expanded_form = true;
+                               }
+
+                               if (score != 0) {
+                                       if (params_expanded_form)
+                                               ++score;
+                                       return (arg_count - i) * 2 + score;
+                               }
+                       }
+                       
+                       if (arg_count != param_count)
+                               params_expanded_form = true;                    
+                       
+                       return 0;
+               }
+
+               int IsArgumentCompatible (EmitContext ec, Parameter.Modifier arg_mod, Argument argument, Parameter.Modifier param_mod, Type parameter)
+               {
+                       //
+                       // Types have to be identical when ref or out modifer is used 
+                       //
+                       if (arg_mod != 0 || param_mod != 0) {
+                               if (TypeManager.HasElementType (parameter))
+                                       parameter = parameter.GetElementType ();
+
+                               Type a_type = argument.Type;
+                               if (TypeManager.HasElementType (a_type))
+                                       a_type = a_type.GetElementType ();
+
+                               if (a_type != parameter)
+                                       return 2;
+
+                               return 0;
+                       }
+
+                       // FIXME: Kill this abomination (EmitContext.TempEc)
+                       EmitContext prevec = EmitContext.TempEc;
+                       EmitContext.TempEc = ec;
+                       try {
+                               if (delegate_type != null ?
+                                       !Delegate.IsTypeCovariant (argument.Expr, parameter) :
+                                       !Convert.ImplicitConversionExists (ec, argument.Expr, parameter))
+                                       return 2;
+
+                               if (arg_mod != param_mod)
+                                       return 1;
+
+                       } finally {
+                               EmitContext.TempEc = prevec;
+                       }
+
+                       return 0;
+               }
 
                public static bool IsOverride (MethodBase cand_method, MethodBase base_method)
                {
@@ -3577,7 +4002,7 @@ namespace Mono.CSharp {
                ///            that is the best match of me on Arguments.
                ///
                /// </summary>
-               public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ArrayList Arguments,
+               public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ref ArrayList Arguments,
                        bool may_fail, Location loc)
                {
                        bool method_params = false;
@@ -3620,23 +4045,11 @@ namespace Mono.CSharp {
                                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;
@@ -3644,12 +4057,17 @@ namespace Mono.CSharp {
                                nmethods = j;
                        }
 
-                       int applicable_errors = Report.Errors;
-                       
+                       //
+                       // 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;
 
@@ -3662,22 +4080,29 @@ namespace Mono.CSharp {
 
                                //
                                // Check if candidate is applicable (section 14.4.2.1)
-                               //   Is candidate applicable in normal form?
                                //
-                               bool is_applicable = Invocation.IsApplicable (ec, this, Arguments, arg_count, ref Methods [i]);
+                               bool params_expanded_form = false;
+                               int candidate_rate = IsApplicable (ec, Arguments, arg_count, ref Methods [i], ref params_expanded_form);
 
-                               if (!is_applicable && Invocation.IsParamsMethodApplicable (ec, this, Arguments, arg_count, ref Methods [i])) {
-                                       MethodBase candidate = Methods [i];
+                               if (candidate_rate < best_candidate_rate) {
+                                       best_candidate_rate = candidate_rate;
+                                       best_candidate = Methods [i];
+                               }
+                               
+                               if (params_expanded_form) {
                                        if (candidate_to_form == null)
                                                candidate_to_form = new PtrHashtable ();
+                                       MethodBase candidate = Methods [i];
                                        candidate_to_form [candidate] = candidate;
-                                       // Candidate is applicable in expanded form
-                                       is_applicable = true;
                                }
 
-                               if (!is_applicable)
+                               if (candidate_rate != 0) {
+                                       if (msg_recorder != null)
+                                               msg_recorder.EndSession ();
                                        continue;
+                               }
 
+                               msg_recorder = null;
                                candidates.Add (Methods [i]);
 
                                if (applicable_type == null)
@@ -3689,89 +4114,89 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (applicable_errors != Report.Errors)
+                       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)
-                                       return null;
-
                                //
-                               // Okay so we have failed to find anything so we
-                               // return by providing info about the closest match
+                               // When we found a top level method which does not match and it's 
+                               // not an extension method. We start extension methods lookup from here
                                //
-                               int errors = Report.Errors;
-                               for (int i = 0; i < nmethods; ++i) {
-                                       MethodBase c = Methods [i];
-                                       ParameterData pd = TypeManager.GetParameterData (c);
-
-                                       if (pd.Count != arg_count)
-                                               continue;
-
-#if GMCS_SOURCE
-                                       if (!TypeManager.InferTypeArguments (ec, Arguments, ref c))
-                                               continue;
-                                       if (TypeManager.IsGenericMethodDefinition (c))
-                                               continue;
-#endif
-
-                                       Invocation.VerifyArgumentsCompat (ec, Arguments, arg_count,
-                                               c, false, null, may_fail, loc);
-
-                                       if (!may_fail && errors == Report.Errors){
-                                               
-                                               throw new InternalErrorException (
-                                                       "VerifyArgumentsCompat and IsApplicable do not agree; " +
-                                                       "likely reason: ImplicitConversion and ImplicitConversionExists have gone out of sync");
+                               if (InstanceExpression != null) {
+                                       ExtensionMethodGroupExpr ex_method_lookup = ec.TypeContainer.LookupExtensionMethod (type, Name);
+                                       if (ex_method_lookup != null) {
+                                               ex_method_lookup.ExtensionExpression = InstanceExpression;
+                                               ex_method_lookup.SetTypeArguments (type_arguments);
+                                               return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc);
                                        }
-
-                                       break;
                                }
+                               
+                               if (may_fail)
+                                       return null;
 
-                               if (!may_fail && errors == Report.Errors) {
-                                       string report_name = Name;
-                                       if (report_name == ".ctor")
-                                               report_name = TypeManager.CSharpName (DeclaringType);
-                                        
-#if GMCS_SOURCE
-                                       //
-                                       // Type inference
-                                       //
-                                       for (int i = 0; i < Methods.Length; ++i) {
-                                               MethodBase c = Methods [i];
-                                               ParameterData pd = TypeManager.GetParameterData (c);
-
-                                               if (pd.Count != arg_count)
-                                                       continue;
-
-                                               if (TypeManager.InferTypeArguments (ec, Arguments, ref c))
-                                                       continue;
-
-                                               Report.Error (
-                                                       411, loc, "The type arguments for " +
-                                                       "method `{0}' cannot be inferred from " +
-                                                       "the usage. Try specifying the type " +
-                                                       "arguments explicitly", TypeManager.CSharpSignature (c));
-                                               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;
                                        }
-#endif
 
-                                       if (Name == ConstructorInfo.ConstructorName) {
-                                               if (almostMatchedMembers.Count != 0) {
-                                                       Error_MemberLookupFailed (ec.ContainerType, type, type, ".ctor",
-                                                               null, MemberTypes.Constructor, AllBindingFlags, loc);
+                                       ParameterData pd = TypeManager.GetParameterData (best_candidate);
+                                       bool cand_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
+                                       if (arg_count == pd.Count || pd.HasParams) {
+                                               if (TypeManager.IsGenericMethodDefinition (best_candidate)) {
+                                                       if (type_arguments == null) {
+                                                               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));
+                                                               return null;
+                                                       }
+                                                               
+                                                       Type [] g_args = TypeManager.GetGenericArguments (best_candidate);
+                                                       if (type_arguments.Count != g_args.Length) {
+                                                               Report.SymbolRelatedToPreviousError (best_candidate);
+                                                               Report.Error (305, loc, "Using the generic method `{0}' requires `{1}' type argument(s)",
+                                                                       TypeManager.CSharpSignature (best_candidate),
+                                                                       g_args.Length.ToString ());
+                                                               return null;
+                                                       }
                                                } else {
-                                                       Report.SymbolRelatedToPreviousError (type);
-                                                       Report.Error (1729, loc,
-                                                               "The type `{0}' does not contain a constructor that takes `{1}' arguments",
-                                                               TypeManager.CSharpName (type), arg_count);
+                                                       if (type_arguments != null && !TypeManager.IsGenericMethod (best_candidate)) {
+                                                               Namespace.Error_TypeArgumentsCannotBeUsed (best_candidate, loc);
+                                                               return null;
+                                                       }
                                                }
-                                       } else {
-                                               Invocation.Error_WrongNumArguments (loc, report_name, arg_count);
+                                               
+                                               if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, cand_params, may_fail, loc))
+                                                       return null;
                                        }
                                }
+
+                               if (almost_matched_members.Count != 0) {
+                                       Error_MemberLookupFailed (ec.ContainerType, type, type, ".ctor",
+                                       null, MemberTypes.Constructor, AllBindingFlags);
+                                       return null;
+                               }
+                               
+                               //
+                               // We failed to find any method with correct argument count
+                               //
+                               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 {
+                                       Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments",
+                                               Name, arg_count.ToString ());
+                               }
                                 
                                return null;
                        }
@@ -3832,7 +4257,9 @@ namespace Mono.CSharp {
                        //
 
                        best_candidate = (MethodBase) candidates [0];
-                       method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
+                       if (delegate_type == null)
+                               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];
 
@@ -3853,7 +4280,7 @@ namespace Mono.CSharp {
                        // should be better than all the others
                        //
                        MethodBase ambiguous = null;
-                       for (int ix = 0; ix < candidate_top; ix++) {
+                       for (int ix = 1; ix < candidate_top; ix++) {
                                MethodBase candidate = (MethodBase) candidates [ix];
 
                                if (candidate == best_candidate)
@@ -3885,16 +4312,37 @@ namespace Mono.CSharp {
                                        throw new InternalErrorException (
                                                "Should not happen.  An 'override' method took part in overload resolution: " + best_candidate);
 
-                               if (candidate_overrides != null)
+                               if (candidate_overrides != null) {
+                                       Type[] gen_args = null;
+                                       bool gen_override = false;
+                                       if (TypeManager.IsGenericMethod (best_candidate))
+                                               gen_args = TypeManager.GetGenericArguments (best_candidate);
+
                                        foreach (MethodBase candidate in candidate_overrides) {
-                                               if (IsOverride (candidate, best_candidate))
+                                               if (TypeManager.IsGenericMethod (candidate)) {
+                                                       if (gen_args == null)
+                                                               continue;
+
+                                                       if (gen_args.Length != TypeManager.GetGenericArguments (candidate).Length)
+                                                               continue;
+                                               } else {
+                                                       if (gen_args != null)
+                                                               continue;
+                                               }
+                                               
+                                               if (IsOverride (candidate, best_candidate)) {
+                                                       gen_override = true;
                                                        best_candidate = candidate;
+                                               }
                                        }
-                       }
 
-                       // We can stop here when probing is on
-                       if (ec.IsInProbingMode)
-                               return this;
+                                       if (gen_override && gen_args != null) {
+#if GMCS_SOURCE
+                                               best_candidate = ((MethodInfo) best_candidate).MakeGenericMethod (gen_args);
+#endif                                         
+                                       }
+                               }
+                       }
 
                        //
                        // And now check if the arguments are all
@@ -3902,8 +4350,8 @@ namespace Mono.CSharp {
                        // necessary etc. and return if everything is
                        // all right
                        //
-                       if (!Invocation.VerifyArgumentsCompat (ec, Arguments, arg_count, best_candidate,
-                               method_params, null, may_fail, loc))
+                       if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate,
+                               method_params, may_fail, loc))
                                return null;
 
                        if (best_candidate == null)
@@ -3923,70 +4371,189 @@ namespace Mono.CSharp {
                        return this;
                }
                
-               public Expression ResolveGeneric (EmitContext ec, TypeArguments args)
+               public override void SetTypeArguments (TypeArguments ta)
                {
-#if GMCS_SOURCE
-                       if (!args.Resolve (ec))
-                               return null;
+                       type_arguments = ta;
+               }
 
-                       Type[] atypes = args.Arguments;
+               public bool VerifyArgumentsCompat (EmitContext ec, ref ArrayList arguments,
+                                                         int arg_count, MethodBase method,
+                                                         bool chose_params_expanded,
+                                                         bool may_fail, Location loc)
+               {
+                       ParameterData pd = TypeManager.GetParameterData (method);
 
-                       int first_count = 0;
-                       MethodInfo first = null;
+                       int errors = Report.Errors;
+                       Parameter.Modifier p_mod = 0;
+                       Type pt = null;
+                       int a_idx = 0, a_pos = 0;
+                       Argument a = null;
+                       ArrayList params_initializers = null;
+
+                       for (; a_idx < arg_count; a_idx++, ++a_pos) {
+                               a = (Argument) arguments [a_idx];
+                               if (p_mod != Parameter.Modifier.PARAMS) {
+                                       p_mod = pd.ParameterModifier (a_idx);
+                                       pt = pd.ParameterType (a_idx);
+
+                                       if (p_mod == Parameter.Modifier.ARGLIST) {
+                                               if (a.Type != TypeManager.runtime_argument_handle_type)
+                                                       break;
+                                               continue;
+                                       }
 
-                       ArrayList list = new ArrayList ();
-                       foreach (MethodBase mb in Methods) {
-                               MethodInfo mi = mb as MethodInfo;
-                               if ((mi == null) || !mb.IsGenericMethod)
-                                       continue;
+                                       if (pt.IsPointer && !ec.InUnsafe) {
+                                               if (may_fail)
+                                                       return false;
 
-                               Type[] gen_params = mb.GetGenericArguments ();
+                                               UnsafeError (loc);
+                                       }
 
-                               if (first == null) {
-                                       first = mi;
-                                       first_count = gen_params.Length;
+                                       if (p_mod == Parameter.Modifier.PARAMS) {
+                                               if (chose_params_expanded) {
+                                                       params_initializers = new ArrayList (arg_count - a_idx);
+                                                       pt = TypeManager.GetElementType (pt);
+                                               }
+                                       } else if (p_mod != 0) {
+                                               pt = TypeManager.GetElementType (pt);
+                                       }
                                }
 
-                               if (gen_params.Length != atypes.Length)
+                               //
+                               // Types have to be identical when ref or out modifer is used 
+                               //
+                               if (a.Modifier != 0 || (p_mod & ~Parameter.Modifier.PARAMS) != 0) {
+                                       if ((p_mod & ~Parameter.Modifier.PARAMS) != a.Modifier)
+                                               break;
+
+                                       if (!TypeManager.IsEqual (a.Expr.Type, pt))
+                                               break;
+
                                        continue;
+                               }
+               
+                               Expression conv;
+                               if (TypeManager.IsEqual (a.Type, pt)) {
+                                       conv = a.Expr;
+                               } else {
+                                       conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc);
+                                       if (conv == null)
+                                               break;
+                               }
 
-                               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);
+                               //
+                               // Convert params arguments to an array initializer
+                               //
+                               if (params_initializers != null) {
+                                       params_initializers.Add (conv);
+                                       arguments.RemoveAt (a_idx--);
+                                       --arg_count;
+                                       continue;
                                }
-#endif
+                               
+                               // Update the argument with the implicit conversion
+                               a.Expr = conv;
                        }
 
-                       if (list.Count > 0) {
-                               MethodGroupExpr new_mg = new MethodGroupExpr (list, type, Location);
-                               new_mg.InstanceExpression = InstanceExpression;
-                               new_mg.HasTypeArguments = true;
-                               new_mg.IsBase = IsBase;
-                               return new_mg;
+                       //
+                       // Fill not provided arguments required by params modifier
+                       //
+                       if (params_initializers == null && pd.HasParams && arg_count < pd.Count && a_idx + 1 == pd.Count) {
+                               if (arguments == null)
+                                       arguments = new ArrayList (1);
+
+                               pt = pd.Types [GetApplicableParametersCount (method, pd) - 1];
+                               pt = TypeManager.GetElementType (pt);
+                               params_initializers = new ArrayList (0);
                        }
 
-                       if (first != null) {
-                               Report.SymbolRelatedToPreviousError (first);
-                               Report.Error (
-                                       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);
+                       if (a_idx == arg_count) {
+                               //
+                               // Append an array argument with all params arguments
+                               //
+                               if (params_initializers != null) {
+                                       arguments.Add (new Argument (
+                                               new ArrayCreation (new TypeExpression (pt, loc), "[]",
+                                               params_initializers, loc).Resolve (ec)));
+                               }
+                               return true;
+                       }
 
-                       return null;
-#else
-                       throw new NotImplementedException ();
-#endif
+                       if (!may_fail && Report.Errors == errors) {
+                               if (CustomErrorHandler != null)
+                                       CustomErrorHandler.NoExactMatch (ec, best_candidate);
+                               else
+                                       Error_InvalidArguments (ec, loc, a_pos, method, a, pd, pt);
+                       }
+                       return false;
+               }
+       }
+
+       public class ConstantExpr : MemberExpr
+       {
+               FieldInfo constant;
+
+               public ConstantExpr (FieldInfo constant, Location loc)
+               {
+                       this.constant = constant;
+                       this.loc = loc;
+               }
+
+               public override string Name {
+                       get { throw new NotImplementedException (); }
+               }
+
+               public override bool IsInstance {
+                       get { return !IsStatic; }
+               }
+
+               public override bool IsStatic {
+                       get { return constant.IsStatic; }
+               }
+
+               public override Type DeclaringType {
+                       get { return constant.DeclaringType; }
+               }
+
+               public override MemberExpr ResolveMemberAccess (EmitContext ec, Expression left, Location loc, SimpleName original)
+               {
+                       constant = TypeManager.GetGenericFieldDefinition (constant);
+
+                       IConstant ic = TypeManager.GetConstant (constant);
+                       if (ic == null) {
+                               if (constant.IsLiteral) {
+                                       ic = new ExternalConstant (constant);
+                               } else {
+                                       ic = ExternalConstant.CreateDecimal (constant);
+                                       // HACK: decimal field was not resolved as constant
+                                       if (ic == null)
+                                               return new FieldExpr (constant, loc).ResolveMemberAccess (ec, left, loc, original);
+                               }
+                               TypeManager.RegisterConstant (constant, ic);
+                       }
+
+                       return base.ResolveMemberAccess (ec, left, loc, original);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       IConstant ic = TypeManager.GetConstant (constant);
+                       if (ic.ResolveValue ()) {
+                               if (!ec.IsInObsoleteScope)
+                                       ic.CheckObsoleteness (loc);
+                       }
+
+                       return ic.CreateConstantReference (loc);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       return TypeManager.GetFullNameSignature (constant);
                }
        }
 
@@ -4050,42 +4617,12 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
+               public override MemberExpr ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
                                                                SimpleName original)
                {
                        FieldInfo fi = TypeManager.GetGenericFieldDefinition (FieldInfo);
-
                        Type t = fi.FieldType;
 
-                       if (fi.IsLiteral || (fi.IsInitOnly && t == TypeManager.decimal_type)) {
-                               IConstant ic = TypeManager.GetConstant (fi);
-                               if (ic == null) {
-                                       if (fi.IsLiteral) {
-                                               ic = new ExternalConstant (fi);
-                                       } else {
-                                               ic = ExternalConstant.CreateDecimal (fi);
-                                               if (ic == null) {
-                                                       return base.ResolveMemberAccess (ec, left, loc, original);
-                                               }
-                                       }
-                                       TypeManager.RegisterConstant (fi, ic);
-                               }
-
-                               bool left_is_type = left is TypeExpr;
-                               if (!left_is_type && (original == null || !original.IdenticalNameAndTypeName (ec, left, loc))) {
-                                       Report.SymbolRelatedToPreviousError (FieldInfo);
-                                       error176 (loc, TypeManager.GetFullNameSignature (FieldInfo));
-                                       return null;
-                               }
-
-                               if (ic.ResolveValue ()) {
-                                       if (!ec.IsInObsoleteScope)
-                                               ic.CheckObsoleteness (loc);
-                               }
-
-                               return ic.CreateConstantReference (loc);
-                       }
-                       
                        if (t.IsPointer && !ec.InUnsafe) {
                                UnsafeError (loc);
                        }
@@ -4128,10 +4665,12 @@ namespace Mono.CSharp {
                                if (InstanceExpression == null)
                                        return null;
 
-                               InstanceExpression.CheckMarshalByRefAccess ();
+                               using (ec.Set (EmitContext.Flags.OmitStructFlowAnalysis)) {
+                                       InstanceExpression.CheckMarshalByRefAccess (ec);
+                               }
                        }
 
-                       if (!in_initializer && !ec.IsFieldInitializer) {
+                       if (!in_initializer && !ec.IsInFieldInitializer) {
                                ObsoleteAttribute oa;
                                FieldBase f = TypeManager.GetField (FieldInfo);
                                if (f != null) {
@@ -4164,8 +4703,7 @@ namespace Mono.CSharp {
                                        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)) {
+                               if (InstanceExpression.eclass != ExprClass.Variable) {
                                        Report.SymbolRelatedToPreviousError (FieldInfo);
                                        Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields",
                                                TypeManager.GetFullNameSignature (FieldInfo));
@@ -4244,7 +4782,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) {
@@ -4265,7 +4803,7 @@ namespace Mono.CSharp {
                        }
 
                        if (right_side == EmptyExpression.OutAccess &&
-                           !IsStatic && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
+                           !IsStatic && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type)) {
                                Report.SymbolRelatedToPreviousError (DeclaringType);
                                Report.Warning (197, 1, loc,
                                                "Passing `{0}' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class",
@@ -4275,9 +4813,9 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               public override void CheckMarshalByRefAccess ()
+               public override void CheckMarshalByRefAccess (EmitContext ec)
                {
-                       if (!IsStatic && Type.IsValueType && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
+                       if (!IsStatic && Type.IsValueType && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type)) {
                                Report.SymbolRelatedToPreviousError (DeclaringType);
                                Report.Warning (1690, 1, loc, "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
                                                GetSignatureForError ());
@@ -4362,16 +4900,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) {
@@ -4458,19 +4999,6 @@ namespace Mono.CSharp {
                }
        }
 
-       //
-       // A FieldExpr whose address can not be taken
-       //
-       public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
-               public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
-               {
-               }
-               
-               public new void AddressOf (EmitContext ec, AddressOp mode)
-               {
-                       Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
-               }
-       }
        
        /// <summary>
        ///   Expression that evaluates to a Property.  The Assign class
@@ -4481,11 +5009,6 @@ namespace Mono.CSharp {
        /// </summary>
        public class PropertyExpr : MemberExpr, IAssignMethod {
                public readonly PropertyInfo PropertyInfo;
-
-               //
-               // This is set externally by the  `BaseAccess' class
-               //
-               public bool IsBase;
                MethodInfo getter, setter;
                bool is_static;
 
@@ -4494,7 +5017,7 @@ namespace Mono.CSharp {
                LocalTemporary temp;
                bool prepared;
 
-               public PropertyExpr (Type containerType, PropertyInfo pi, Location l)
+               public PropertyExpr (Type container_type, PropertyInfo pi, Location l)
                {
                        PropertyInfo = pi;
                        eclass = ExprClass.PropertyAccess;
@@ -4503,7 +5026,7 @@ namespace Mono.CSharp {
 
                        type = TypeManager.TypeToCoreType (pi.PropertyType);
 
-                       ResolveAccessors (containerType);
+                       ResolveAccessors (container_type);
                }
 
                public override string Name {
@@ -4523,7 +5046,23 @@ namespace Mono.CSharp {
                                return is_static;
                        }
                }
-               
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       if (IsSingleDimensionalArrayLength ()) {
+                               ArrayList args = new ArrayList (1);
+                               args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
+                               return CreateExpressionFactoryCall ("ArrayLength", args);
+                       }
+
+                       // TODO: it's waiting for PropertyExpr refactoring
+                       //ArrayList args = new ArrayList (2);
+                       //args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
+                       //args.Add (getter expression);
+                       //return CreateExpressionFactoryCall ("Property", args);
+                       return base.CreateExpressionTree (ec);
+               }
+
                public override Type DeclaringType {
                        get {
                                return PropertyInfo.DeclaringType;
@@ -4574,9 +5113,9 @@ namespace Mono.CSharp {
                // hold the information for the accessibility of its setter/getter
                //
                // TODO: Refactor to use some kind of cache together with GetPropertyFromAccessor
-               void ResolveAccessors (Type containerType)
+               void ResolveAccessors (Type container_type)
                {
-                       FindAccessors (containerType);
+                       FindAccessors (container_type);
 
                        if (getter != null) {
                                MethodBase the_getter = TypeManager.DropGenericMethodArguments (getter);
@@ -4616,7 +5155,7 @@ namespace Mono.CSharp {
                        if (InstanceExpression == null)
                                return false;
 
-                       InstanceExpression.CheckMarshalByRefAccess ();
+                       InstanceExpression.CheckMarshalByRefAccess (ec);
 
                        if (must_do_cs1540_check && (InstanceExpression != EmptyExpression.Null) &&
                            !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.ContainerType) &&
@@ -4637,7 +5176,7 @@ namespace Mono.CSharp {
                                Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
                                return;
                        }
-
+                       
                        StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
                        sig.Append ('.');
                        ParameterData iparams = TypeManager.GetParameterData (mi);
@@ -4649,7 +5188,26 @@ 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);
+               }
+
+               bool IsSingleDimensionalArrayLength ()
+               {
+                       if (DeclaringType != TypeManager.array_type || getter == null || Name != "Length")
+                               return false;
+
+                       string t_name = InstanceExpression.Type.Name;
+                       int t_name_len = t_name.Length;
+                       return t_name_len > 2 && t_name [t_name_len - 2] == '[' && t_name [t_name_len - 3] != ']';
+               }
+
                override public Expression DoResolve (EmitContext ec)
                {
                        if (resolved)
@@ -4719,15 +5277,18 @@ 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;
                        }
 
                        if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) {
-                               Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable",
-                                             GetSignatureForError ());
-                               return null;
+                               Error_CannotModifyIntermediateExpressionValue (ec);
                        }
 
                        if (setter == null){
@@ -4788,21 +5349,12 @@ namespace Mono.CSharp {
                        //
                        // Special case: length of single dimension array property is turned into ldlen
                        //
-                       if ((getter == TypeManager.system_int_array_get_length) ||
-                           (getter == TypeManager.int_array_get_length)){
-                               Type iet = InstanceExpression.Type;
-
-                               //
-                               // System.Array.Length can be called, but the Type does not
-                               // support invoking GetArrayRank, so test for that case first
-                               //
-                               if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
-                                       if (!prepared)
-                                               EmitInstance (ec, false);
-                                       ec.ig.Emit (OpCodes.Ldlen);
-                                       ec.ig.Emit (OpCodes.Conv_I4);
-                                       return;
-                               }
+                       if (IsSingleDimensionalArrayLength ()) {
+                               if (!prepared)
+                                       EmitInstance (ec, false);
+                               ec.ig.Emit (OpCodes.Ldlen);
+                               ec.ig.Emit (OpCodes.Conv_I4);
+                               return;
                        }
 
                        Invocation.EmitCall (ec, IsBase, InstanceExpression, getter, null, loc, prepared, false);
@@ -4823,10 +5375,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) {
@@ -4836,13 +5393,11 @@ 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));
                        
@@ -4860,7 +5415,6 @@ namespace Mono.CSharp {
        /// </summary>
        public class EventExpr : MemberExpr {
                public readonly EventInfo EventInfo;
-               public bool IsBase;
 
                bool is_static;
                MethodInfo add_accessor, remove_accessor;
@@ -4907,8 +5461,14 @@ namespace Mono.CSharp {
                                return EventInfo.DeclaringType;
                        }
                }
+               
+               void Error_AssignmentEventOnly ()
+               {
+                       Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator",
+                               GetSignatureForError ());
+               }
 
-               public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
+               public override MemberExpr ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
                                                                SimpleName original)
                {
                        //
@@ -4923,6 +5483,9 @@ namespace Mono.CSharp {
                                        if (!ec.IsInObsoleteScope)
                                                mi.CheckObsoleteness (loc);
 
+                                       if ((mi.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0 && !ec.IsInCompoundAssignment)
+                                               Error_AssignmentEventOnly ();
+                                       
                                        FieldExpr ml = new FieldExpr (mi.FieldBuilder, loc);
 
                                        InstanceExpression = null;
@@ -4930,6 +5493,9 @@ namespace Mono.CSharp {
                                        return ml.ResolveMemberAccess (ec, left, loc, original);
                                }
                        }
+                       
+                       if (left is This && !ec.IsInCompoundAssignment)                 
+                               Error_AssignmentEventOnly ();
 
                        return base.ResolveMemberAccess (ec, left, loc, original);
                }
@@ -4962,7 +5528,7 @@ namespace Mono.CSharp {
                        //
                        if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
                            InstanceExpression.Type != ec.ContainerType &&
-                           ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
+                           TypeManager.IsSubclassOf (ec.ContainerType, InstanceExpression.Type)) {
                                Report.SymbolRelatedToPreviousError (EventInfo);
                                ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
                                return false;
@@ -4971,6 +5537,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);
@@ -4994,11 +5567,8 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       if (InstanceExpression is This)
-                               Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ());
-                       else
-                               Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
-                                             "(except on the defining type)", Name);
+                       Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
+                                     "(except on the defining type)", GetSignatureForError ());
                }
 
                public override string GetSignatureForError ()
@@ -5108,8 +5678,8 @@ namespace Mono.CSharp {
                // Used for error reporting only
                ArrayList initializer;
 
-               public VarExpr (string name, Location loc)
-                       : base (name, loc)
+               public VarExpr (Location loc)
+                       : base ("var", loc)
                {
                }
 
@@ -5137,12 +5707,7 @@ namespace Mono.CSharp {
 
                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);
+                       Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration");
                }
 
                public override TypeExpr ResolveAsContextualType (IResolveContext rc, bool silent)
@@ -5154,10 +5719,10 @@ namespace Mono.CSharp {
                        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");
+                               initializer = null;
                                return null;
                        }