2007-12-06 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / mcs / expression.cs
index ed84394d381d69b860c7d44bbbdb19fb2673fbd0..7c9d1d1d7cbd95d4db5da190c744b021e1a9d2d2 100644 (file)
@@ -411,7 +411,7 @@ namespace Mono.CSharp {
                                        expr_type == TypeManager.char_type) 
                                {
                                        type = TypeManager.int32_type;
-                                       return new EmptyCast (this, type);
+                                       return EmptyCast.Create (this, type);
                                }
 
                                // Predefined operators
@@ -503,7 +503,7 @@ namespace Mono.CSharp {
                                        expr_type == TypeManager.short_type || expr_type == TypeManager.ushort_type ||
                                        expr_type == TypeManager.char_type) 
                                {
-                                       return new EmptyCast (Expr, TypeManager.int32_type);
+                                       return EmptyCast.Create (Expr, TypeManager.int32_type);
                                }
 
                                // Predefined operators
@@ -539,7 +539,7 @@ namespace Mono.CSharp {
                                        expr_type == TypeManager.char_type) 
                                {
                                        type = TypeManager.int32_type;
-                                       return new EmptyCast (this, type);
+                                       return EmptyCast.Create (this, type);
                                }
 
                                //
@@ -652,12 +652,12 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
                {
                        if (Oper == Operator.LogicalNot)
-                               Expr.EmitBranchable (ec, target, !onTrue);
+                               Expr.EmitBranchable (ec, target, !on_true);
                        else
-                               base.EmitBranchable (ec, target, onTrue);
+                               base.EmitBranchable (ec, target, on_true);
                }
 
                public override string ToString ()
@@ -891,11 +891,7 @@ namespace Mono.CSharp {
                                if (expr == null)
                                        return null;
                        } else {
-                               if (expr.eclass == ExprClass.Value) {
-                                       Error_ValueAssignment (loc);
-                               } else {
-                                       expr.Error_UnexpectedKind (ec.DeclContainer, "variable, indexer or property access", loc);
-                               }
+                               Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer");
                                return null;
                        }
 
@@ -1081,13 +1077,23 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return null;
                        
-                       if (expr.Type.IsPointer) {
-                               Report.Error (244, loc, "\"is\" or \"as\" are not valid on pointer types");
+                       if (expr.Type.IsPointer || probe_type_expr.Type.IsPointer) {
+                               Report.Error (244, loc, "The `{0}' operator cannot be applied to an operand of pointer type",
+                                       OperatorName);
+                               return null;
+                       }
+
+                       if (expr.Type == TypeManager.anonymous_method_type) {
+                               Report.Error (837, loc, "The `{0}' operator cannot be applied to a lambda expression or anonymous method",
+                                       OperatorName);
                                return null;
                        }
+
                        return this;
                }
 
+               protected abstract string OperatorName { get; }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        Probe target = (Probe) t;
@@ -1106,131 +1112,135 @@ namespace Mono.CSharp {
                        : base (expr, probe_type, l)
                {
                }
-
-               enum Action {
-                       AlwaysTrue, AlwaysNull, AlwaysFalse, LeaveOnStack, Probe
-               }
-
-               Action action;
                
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
 
                        expr.Emit (ec);
-
-                       switch (action){
-                       case Action.AlwaysFalse:
-                               ig.Emit (OpCodes.Pop);
-                               IntConstant.EmitInt (ig, 0);
-                               return;
-                       case Action.AlwaysTrue:
-                               ig.Emit (OpCodes.Pop);
-                               IntConstant.EmitInt (ig, 1);
-                               return;
-                       case Action.LeaveOnStack:
-                               // the `e != null' rule.
-                               ig.Emit (OpCodes.Ldnull);
-                               ig.Emit (OpCodes.Ceq);
-                               ig.Emit (OpCodes.Ldc_I4_0);
-                               ig.Emit (OpCodes.Ceq);
-                               return;
-                       case Action.Probe:
-                               ig.Emit (OpCodes.Isinst, probe_type_expr.Type);
-                               ig.Emit (OpCodes.Ldnull);
-                               ig.Emit (OpCodes.Cgt_Un);
-                               return;
-                       }
-                       throw new Exception ("never reached");
+                       ig.Emit (OpCodes.Isinst, probe_type_expr.Type);
+                       ig.Emit (OpCodes.Ldnull);
+                       ig.Emit (OpCodes.Cgt_Un);
                }
 
-               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
                {
                        ILGenerator ig = ec.ig;
 
-                       switch (action){
-                       case Action.AlwaysFalse:
-                               if (! onTrue)
-                                       ig.Emit (OpCodes.Br, target);
-                               
-                               return;
-                       case Action.AlwaysTrue:
-                               if (onTrue)
-                                       ig.Emit (OpCodes.Br, target);
-                               
-                               return;
-                       case Action.LeaveOnStack:
-                               // the `e != null' rule.
-                               expr.Emit (ec);
-                               ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
-                               return;
-                       case Action.Probe:
-                               expr.Emit (ec);
-                               ig.Emit (OpCodes.Isinst, probe_type_expr.Type);
-                               ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
-                               return;
-                       }
-                       throw new Exception ("never reached");
+                       expr.Emit (ec);
+                       ig.Emit (OpCodes.Isinst, probe_type_expr.Type);
+                       ig.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
                }
 
-               public override Expression DoResolve (EmitContext ec)
+               Expression CreateConstantResult (bool result)
                {
-                       Expression e = base.DoResolve (ec);
+                       if (result)
+                               Report.Warning (183, 1, loc, "The given expression is always of the provided (`{0}') type",
+                                       TypeManager.CSharpName (probe_type_expr.Type));
+                       else
+                               Report.Warning (184, 1, loc, "The given expression is never of the provided (`{0}') type",
+                                       TypeManager.CSharpName (probe_type_expr.Type));
+
+                       return new BoolConstant (result, loc);
+               }
 
-                       if ((e == null) || (expr == null))
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (base.DoResolve (ec) == null)
                                return null;
 
-                       Type etype = expr.Type;
+                       Type d = expr.Type;
+                       bool d_is_nullable = false;
+
+                       if (expr is Constant) {
+                               //
+                               // If E is a method group or the null literal, of if the type of E is a reference
+                               // type or a nullable type and the value of E is null, the result is false
+                               //
+                               if (((Constant) expr).GetValue () == null)
+                                       return CreateConstantResult (false);
+                       } else if (TypeManager.IsNullableType (d) && !TypeManager.ContainsGenericParameters (d)) {
+                               d = TypeManager.GetTypeArguments (d) [0];
+                               d_is_nullable = true;
+                       }
+
                        type = TypeManager.bool_type;
                        eclass = ExprClass.Value;
+                       Type t = probe_type_expr.Type;
+                       bool t_is_nullable = false;
+                       if (TypeManager.IsNullableType (t) && !TypeManager.ContainsGenericParameters (t)) {
+                               t = TypeManager.GetTypeArguments (t) [0];
+                               t_is_nullable = true;
+                       }
 
-                       //
-                       // First case, if at compile time, there is an implicit conversion
-                       // then e != null (objects) or true (value types)
-                       //
-                       Type probe_type = probe_type_expr.Type;
-                       e = Convert.ImplicitConversionStandard (ec, expr, probe_type, loc);
-                       if (e != null){
-                               expr = e;
-                               if (etype.IsValueType)
-                                       action = Action.AlwaysTrue;
-                               else
-                                       action = Action.LeaveOnStack;
-
-                               Constant c = e as Constant;
-                               if (c != null && c.GetValue () == null) {
-                                       action = Action.AlwaysFalse;
-                                       Report.Warning (184, 1, loc, "The given expression is never of the provided (`{0}') type",
-                                               TypeManager.CSharpName (probe_type));
-                               } else if (etype.IsValueType) {
-                                       Report.Warning (183, 1, loc, "The given expression is always of the provided (`{0}') type",
-                                               TypeManager.CSharpName (probe_type));
+                       if (t.IsValueType) {
+                               if (d == t) {
+                                       //
+                                       // D and T are the same value types but D can be null
+                                       //
+                                       if (d_is_nullable && !t_is_nullable)
+                                               return Nullable.HasValue.Create (expr, ec);
+                                       
+                                       //
+                                       // The result is true if D and T are the same value types
+                                       //
+                                       return CreateConstantResult (true);
                                }
-                               return this;
-                       }
-                       
-                       if (Convert.ExplicitReferenceConversionExists (etype, probe_type)){
-                               if (TypeManager.IsGenericParameter (etype))
-                                       expr = new BoxedCast (expr, etype);
+
+                               if (TypeManager.IsGenericParameter (d))
+                                       return ResolveGenericParameter (t, d);
 
                                //
-                               // Second case: explicit reference convresion
+                               // An unboxing conversion exists
                                //
-                               if (expr is NullLiteral)
-                                       action = Action.AlwaysFalse;
-                               else
-                                       action = Action.Probe;
-                       } else if (TypeManager.ContainsGenericParameters (etype) ||
-                                  TypeManager.ContainsGenericParameters (probe_type)) {
-                               expr = new BoxedCast (expr, etype);
-                               action = Action.Probe;
+                               if (Convert.ExplicitReferenceConversionExists (d, t))
+                                       return this;
                        } else {
-                               action = Action.AlwaysFalse;
-                               if (!(probe_type.IsInterface || expr.Type.IsInterface))
-                                       Report.Warning (184, 1, loc, "The given expression is never of the provided (`{0}') type", TypeManager.CSharpName (probe_type));
+                               if (TypeManager.IsGenericParameter (t))
+                                       return ResolveGenericParameter (d, t);
+
+                               if (d.IsValueType) {
+                                       bool temp;
+                                       if (Convert.ImplicitBoxingConversionExists (expr, t, out temp))
+                                               return CreateConstantResult (true);
+                               } else {
+                                       if (TypeManager.IsGenericParameter (d))
+                                               return ResolveGenericParameter (t, d);
+
+                                       if (TypeManager.ContainsGenericParameters (d))
+                                               return this;
+
+                                       if (Convert.ImplicitReferenceConversionExists (expr, t) ||
+                                               Convert.ExplicitReferenceConversionExists (d, t)) {
+                                               return this;
+                                       }
+                               }
+                       }
+
+                       return CreateConstantResult (false);
+               }
+
+               Expression ResolveGenericParameter (Type d, Type t)
+               {
+#if GMCS_SOURCE
+                       GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (t);
+                       if (constraints != null) {
+                               if (constraints.IsReferenceType && d.IsValueType)
+                                       return CreateConstantResult (false);
+
+                               if (constraints.IsValueType && !d.IsValueType)
+                                       return CreateConstantResult (false);
                        }
 
+                       expr = new BoxedCast (expr, d);
                        return this;
+#else
+                       return null;
+#endif
+               }
+               
+               protected override string OperatorName {
+                       get { return "is"; }
                }
        }
 
@@ -1339,10 +1349,14 @@ namespace Mono.CSharp {
                        Error_CannotConvertType (etype, type, loc);
                        return null;
                }
+
+               protected override string OperatorName {
+                       get { return "as"; }
+               }
        
-               public override bool GetAttributableValue (Type valueType, out object value)
+               public override bool GetAttributableValue (Type value_type, out object value)
                {
-                       return expr.GetAttributableValue (valueType, out value);
+                       return expr.GetAttributableValue (value_type, out value);
                }
        }
        
@@ -1426,6 +1440,68 @@ namespace Mono.CSharp {
                        target.expr = expr.Clone (clonectx);
                }
        }
+       
+       //
+       // C# 2.0 Default value expression
+       //
+       public class DefaultValueExpression : Expression
+       {
+               Expression expr;
+
+               public DefaultValueExpression (Expression expr, Location loc)
+               {
+                       this.expr = expr;
+                       this.loc = loc;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       TypeExpr texpr = expr.ResolveAsTypeTerminal (ec, false);
+                       if (texpr == null)
+                               return null;
+
+                       type = texpr.Type;
+
+                       if (type == TypeManager.void_type) {
+                               Error_VoidInvalidInTheContext (loc);
+                               return null;
+                       }
+
+                       if (TypeManager.IsGenericParameter (type))
+                       {
+                               GenericConstraints constraints = TypeManager.GetTypeParameterConstraints(type);
+                               if (constraints != null && constraints.IsReferenceType)
+                                       return new NullDefault (new NullLiteral (Location), type);
+                       }
+                       else
+                       {
+                               Constant c = New.Constantify(type);
+                               if (c != null)
+                                       return new NullDefault (c, type);
+
+                               if (!TypeManager.IsValueType (type))
+                                       return new NullDefault (new NullLiteral (Location), type);
+                       }
+                       eclass = ExprClass.Variable;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       LocalTemporary temp_storage = new LocalTemporary(type);
+
+                       temp_storage.AddressOf(ec, AddressOp.LoadStore);
+                       ec.ig.Emit(OpCodes.Initobj, type);
+                       temp_storage.Emit(ec);
+               }
+               
+               protected override void CloneTo (CloneContext clonectx, Expression t)
+               {
+                       DefaultValueExpression target = (DefaultValueExpression) t;
+                       
+                       target.expr = expr.Clone (clonectx);
+               }
+       }
 
        /// <summary>
        ///   Binary operators
@@ -1446,7 +1522,8 @@ namespace Mono.CSharp {
                }
 
                readonly Operator oper;
-               Expression left, right;
+               protected Expression left, right;
+               readonly bool is_compound;
 
                // This must be kept in sync with Operator!!!
                public static readonly string [] oper_names;
@@ -1475,6 +1552,12 @@ namespace Mono.CSharp {
                        oper_names [(int) Operator.LogicalAnd] = "op_LogicalAnd";
                }
 
+               public Binary (Operator oper, Expression left, Expression right, bool isCompound)
+                       : this (oper, left, right)
+               {
+                       this.is_compound = isCompound;
+               }
+
                public Binary (Operator oper, Expression left, Expression right)
                {
                        this.oper = oper;
@@ -1492,48 +1575,73 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Returns a stringified representation of the Operator
                /// </summary>
-               public static string OperName (Operator oper)
+               string OperName (Operator oper)
                {
+                       string s;
                        switch (oper){
                        case Operator.Multiply:
-                               return "*";
+                               s = "*";
+                               break;
                        case Operator.Division:
-                               return "/";
+                               s = "/";
+                               break;
                        case Operator.Modulus:
-                               return "%";
+                               s = "%";
+                               break;
                        case Operator.Addition:
-                               return "+";
+                               s = "+";
+                               break;
                        case Operator.Subtraction:
-                               return "-";
+                               s = "-";
+                               break;
                        case Operator.LeftShift:
-                               return "<<";
+                               s = "<<";
+                               break;
                        case Operator.RightShift:
-                               return ">>";
+                               s = ">>";
+                               break;
                        case Operator.LessThan:
-                               return "<";
+                               s = "<";
+                               break;
                        case Operator.GreaterThan:
-                               return ">";
+                               s = ">";
+                               break;
                        case Operator.LessThanOrEqual:
-                               return "<=";
+                               s = "<=";
+                               break;
                        case Operator.GreaterThanOrEqual:
-                               return ">=";
+                               s = ">=";
+                               break;
                        case Operator.Equality:
-                               return "==";
+                               s = "==";
+                               break;
                        case Operator.Inequality:
-                               return "!=";
+                               s = "!=";
+                               break;
                        case Operator.BitwiseAnd:
-                               return "&";
+                               s = "&";
+                               break;
                        case Operator.BitwiseOr:
-                               return "|";
+                               s = "|";
+                               break;
                        case Operator.ExclusiveOr:
-                               return "^";
+                               s = "^";
+                               break;
                        case Operator.LogicalOr:
-                               return "||";
+                               s = "||";
+                               break;
                        case Operator.LogicalAnd:
-                               return "&&";
+                               s = "&&";
+                               break;
+                       default:
+                               s = oper.ToString ();
+                               break;
                        }
 
-                       return oper.ToString ();
+                       if (is_compound)
+                               return s + "=";
+
+                       return s;
                }
 
                public override string ToString ()
@@ -1550,7 +1658,7 @@ namespace Mono.CSharp {
                        return Convert.ImplicitConversion (ec, expr, target_type, loc);
                }
 
-               public static void Error_OperatorAmbiguous (Location loc, Operator oper, Type l, Type r)
+               void Error_OperatorAmbiguous (Location loc, Operator oper, Type l, Type r)
                {
                        Report.Error (
                                34, loc, "Operator `" + OperName (oper) 
@@ -1591,6 +1699,14 @@ namespace Mono.CSharp {
                {
                        if (!IsApplicable_String (ec, left, right, oper))
                                return false;
+                       
+                       Type l = left.Type;
+                       Type r = right.Type;
+                       if (OverloadResolve_PredefinedIntegral (ec) ||
+                               OverloadResolve_PredefinedFloating (ec)) {
+                               Error_OperatorAmbiguous (loc, oper, l, r);
+                       }
+                       
                        Type t = TypeManager.string_type;
                        if (Convert.ImplicitConversionExists (ec, left, t))
                                left = ForceConversion (ec, left, t);
@@ -1627,14 +1743,17 @@ namespace Mono.CSharp {
                                name, left, right);
                }
                
-               void Error_OperatorCannotBeApplied ()
+               protected void Error_OperatorCannotBeApplied ()
                {
                        Error_OperatorCannotBeApplied (Location, OperName (oper), TypeManager.CSharpName (left.Type),
                                TypeManager.CSharpName(right.Type));
                }
 
-               static bool is_unsigned (Type t)
+               static bool IsUnsigned (Type t)
                {
+                       if (t.IsPointer)
+                               return IsUnsigned (t.GetElementType ());
+                       
                        return (t == TypeManager.uint32_type || t == TypeManager.uint64_type ||
                                t == TypeManager.short_type || t == TypeManager.byte_type);
                }
@@ -1858,41 +1977,43 @@ namespace Mono.CSharp {
                        }
 
                        //
-                       // Step 0: String concatenation (because overloading will get this wrong)
+                       // String concatenation
+                       // 
+                       // string operator + (string x, string y);
+                       // string operator + (string x, object y);
+                       // string operator + (object x, string y);
                        //
-                       if (oper == Operator.Addition){
-                               //
-                               // If any of the arguments is a string, cast to string
+                       if (oper == Operator.Addition && !TypeManager.IsDelegateType (l)) {
+                               // 
+                               // Either left or right expression is implicitly convertible to string
                                //
-                               
-                               // Simple constant folding
-                               if (left is StringConstant && right is StringConstant)
-                                       return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value, left.Location);
-                               
-                               if (l == TypeManager.string_type || r == TypeManager.string_type) {
-
+                               if (OverloadResolve_PredefinedString (ec, oper)) {
                                        if (r == TypeManager.void_type || l == TypeManager.void_type) {
                                                Error_OperatorCannotBeApplied ();
                                                return null;
                                        }
 
-                                       // try to fold it in on the left
-                                       if (left is StringConcat) {
+                                       //
+                                       // Constants folding for strings and nulls
+                                       //
+                                       if (left.Type == TypeManager.string_type && right.Type == TypeManager.string_type &&
+                                               left is Constant && right is Constant) {
+                                               string lvalue = (string)((Constant) left).GetValue ();
+                                               string rvalue = (string)((Constant) right).GetValue ();
+                                               return new StringConstant (lvalue + rvalue, left.Location);
+                                       }
 
-                                               //
-                                               // We have to test here for not-null, since we can be doubly-resolved
-                                               // take care of not appending twice
-                                               //
-                                               if (type == null){
-                                                       type = TypeManager.string_type;
-                                                       ((StringConcat) left).Append (ec, right);
-                                                       return left.Resolve (ec);
-                                               } else {
-                                                       return left;
-                                               }
+                                       // 
+                                       // Append to existing string concatenation
+                                       //
+                                       if (left is StringConcat) {
+                                               ((StringConcat) left).Append (ec, right);
+                                               return left;
                                        }
 
-                                       // Otherwise, start a new concat expression
+                                       //
+                                       // Otherwise, start a new concat expression using converted expression
+                                       //
                                        return new StringConcat (ec, loc, left, right).Resolve (ec);
                                }
 
@@ -1926,13 +2047,13 @@ namespace Mono.CSharp {
                                        }
 
                                        if (l.IsPointer && r == TypeManager.null_type) {
-                                               right = new EmptyCast (NullPointer.Null, l);
+                                               right = new EmptyConstantCast (NullPointer.Null, l);
                                                type = TypeManager.bool_type;
                                                return this;
                                        }
 
                                        if (r.IsPointer && l == TypeManager.null_type) {
-                                               left = new EmptyCast (NullPointer.Null, r);
+                                               left = new EmptyConstantCast (NullPointer.Null, r);
                                                type = TypeManager.bool_type;
                                                return this;
                                        }
@@ -1971,6 +2092,15 @@ namespace Mono.CSharp {
                                        //
                                        // Also, a standard conversion must exist from either one
                                        //
+                                       // NOTE: An interface is converted to the object before the
+                                       // standard conversion is applied. It's not clear from the
+                                       // standard but it looks like it works like that.
+                                       //
+                                       if (l.IsInterface)
+                                               l = TypeManager.object_type;
+                                       if (r.IsInterface)
+                                               r = TypeManager.object_type;                                    
+                                       
                                        bool left_to_right =
                                                Convert.ImplicitStandardConversionExists (left, r);
                                        bool right_to_left = !left_to_right &&
@@ -2003,9 +2133,9 @@ namespace Mono.CSharp {
                                        // We are going to have to convert to an object to compare
                                        //
                                        if (l != TypeManager.object_type)
-                                               left = new EmptyCast (left, TypeManager.object_type);
+                                               left = EmptyCast.Create (left, TypeManager.object_type);
                                        if (r != TypeManager.object_type)
-                                               right = new EmptyCast (right, TypeManager.object_type);
+                                               right = EmptyCast.Create (right, TypeManager.object_type);
 
                                        return this;
                                }
@@ -2329,7 +2459,7 @@ namespace Mono.CSharp {
                                                break;
                                        return left;
                        }
-                       Error_OperatorCannotBeApplied (loc, Binary.OperName (oper), left.Type, right.Type);
+                       Error_OperatorCannotBeApplied ();
                        return null;
                }
 
@@ -2545,7 +2675,7 @@ namespace Mono.CSharp {
                ///   The expression's code is generated, and we will generate a branch to `target'
                ///   if the resulting expression value is equal to isTrue
                /// </remarks>
-               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
                {
                        ILGenerator ig = ec.ig;
 
@@ -2556,7 +2686,7 @@ namespace Mono.CSharp {
                        // if we are comparing against null
                        //
                        if ((oper == Operator.Equality || oper == Operator.Inequality) && (left is Constant || right is Constant)) {
-                               bool my_on_true = oper == Operator.Inequality ? onTrue : !onTrue;
+                               bool my_on_true = oper == Operator.Inequality ? on_true : !on_true;
                                
                                //
                                // put the constant on the rhs, for simplicity
@@ -2587,7 +2717,7 @@ namespace Mono.CSharp {
 
                        } else if (oper == Operator.LogicalAnd) {
 
-                               if (onTrue) {
+                               if (on_true) {
                                        Label tests_end = ig.DefineLabel ();
                                        
                                        left.EmitBranchable (ec, tests_end, false);
@@ -2608,7 +2738,7 @@ namespace Mono.CSharp {
                                return;
                                
                        } else if (oper == Operator.LogicalOr){
-                               if (onTrue) {
+                               if (on_true) {
                                        left.EmitBranchable (ec, target, true);
                                        right.EmitBranchable (ec, target, true);
                                        
@@ -2624,7 +2754,7 @@ namespace Mono.CSharp {
                        } else if (!(oper == Operator.LessThan        || oper == Operator.GreaterThan ||
                                     oper == Operator.LessThanOrEqual || oper == Operator.GreaterThanOrEqual ||
                                     oper == Operator.Equality        || oper == Operator.Inequality)) {
-                               base.EmitBranchable (ec, target, onTrue);
+                               base.EmitBranchable (ec, target, on_true);
                                return;
                        }
                        
@@ -2632,57 +2762,57 @@ namespace Mono.CSharp {
                        right.Emit (ec);
 
                        Type t = left.Type;
-                       bool isUnsigned = is_unsigned (t) || t == TypeManager.double_type || t == TypeManager.float_type;
+                       bool is_unsigned = IsUnsigned (t) || t == TypeManager.double_type || t == TypeManager.float_type;
                        
                        switch (oper){
                        case Operator.Equality:
-                               if (onTrue)
+                               if (on_true)
                                        ig.Emit (OpCodes.Beq, target);
                                else
                                        ig.Emit (OpCodes.Bne_Un, target);
                                break;
 
                        case Operator.Inequality:
-                               if (onTrue)
+                               if (on_true)
                                        ig.Emit (OpCodes.Bne_Un, target);
                                else
                                        ig.Emit (OpCodes.Beq, target);
                                break;
 
                        case Operator.LessThan:
-                               if (onTrue)
-                                       if (isUnsigned)
+                               if (on_true)
+                                       if (is_unsigned)
                                                ig.Emit (OpCodes.Blt_Un, target);
                                        else
                                                ig.Emit (OpCodes.Blt, target);
                                else
-                                       if (isUnsigned)
+                                       if (is_unsigned)
                                                ig.Emit (OpCodes.Bge_Un, target);
                                        else
                                                ig.Emit (OpCodes.Bge, target);
                                break;
 
                        case Operator.GreaterThan:
-                               if (onTrue)
-                                       if (isUnsigned)
+                               if (on_true)
+                                       if (is_unsigned)
                                                ig.Emit (OpCodes.Bgt_Un, target);
                                        else
                                                ig.Emit (OpCodes.Bgt, target);
                                else
-                                       if (isUnsigned)
+                                       if (is_unsigned)
                                                ig.Emit (OpCodes.Ble_Un, target);
                                        else
                                                ig.Emit (OpCodes.Ble, target);
                                break;
 
                        case Operator.LessThanOrEqual:
-                               if (onTrue)
-                                       if (isUnsigned)
+                               if (on_true)
+                                       if (is_unsigned)
                                                ig.Emit (OpCodes.Ble_Un, target);
                                        else
                                                ig.Emit (OpCodes.Ble, target);
                                else
-                                       if (isUnsigned)
+                                       if (is_unsigned)
                                                ig.Emit (OpCodes.Bgt_Un, target);
                                        else
                                                ig.Emit (OpCodes.Bgt, target);
@@ -2690,13 +2820,13 @@ namespace Mono.CSharp {
 
 
                        case Operator.GreaterThanOrEqual:
-                               if (onTrue)
-                                       if (isUnsigned)
+                               if (on_true)
+                                       if (is_unsigned)
                                                ig.Emit (OpCodes.Bge_Un, target);
                                        else
                                                ig.Emit (OpCodes.Bge, target);
                                else
-                                       if (isUnsigned)
+                                       if (is_unsigned)
                                                ig.Emit (OpCodes.Blt_Un, target);
                                        else
                                                ig.Emit (OpCodes.Blt, target);
@@ -2746,14 +2876,14 @@ namespace Mono.CSharp {
                        left.Emit (ec);
                        right.Emit (ec);
 
-                       bool isUnsigned = is_unsigned (left.Type);
+                       bool is_unsigned = IsUnsigned (left.Type);
                        
                        switch (oper){
                        case Operator.Multiply:
                                if (ec.CheckState){
                                        if (l == TypeManager.int32_type || l == TypeManager.int64_type)
                                                opcode = OpCodes.Mul_Ovf;
-                                       else if (isUnsigned)
+                                       else if (is_unsigned)
                                                opcode = OpCodes.Mul_Ovf_Un;
                                        else
                                                opcode = OpCodes.Mul;
@@ -2763,14 +2893,14 @@ namespace Mono.CSharp {
                                break;
 
                        case Operator.Division:
-                               if (isUnsigned)
+                               if (is_unsigned)
                                        opcode = OpCodes.Div_Un;
                                else
                                        opcode = OpCodes.Div;
                                break;
 
                        case Operator.Modulus:
-                               if (isUnsigned)
+                               if (is_unsigned)
                                        opcode = OpCodes.Rem_Un;
                                else
                                        opcode = OpCodes.Rem;
@@ -2780,7 +2910,7 @@ namespace Mono.CSharp {
                                if (ec.CheckState){
                                        if (l == TypeManager.int32_type || l == TypeManager.int64_type)
                                                opcode = OpCodes.Add_Ovf;
-                                       else if (isUnsigned)
+                                       else if (is_unsigned)
                                                opcode = OpCodes.Add_Ovf_Un;
                                        else
                                                opcode = OpCodes.Add;
@@ -2792,7 +2922,7 @@ namespace Mono.CSharp {
                                if (ec.CheckState){
                                        if (l == TypeManager.int32_type || l == TypeManager.int64_type)
                                                opcode = OpCodes.Sub_Ovf;
-                                       else if (isUnsigned)
+                                       else if (is_unsigned)
                                                opcode = OpCodes.Sub_Ovf_Un;
                                        else
                                                opcode = OpCodes.Sub;
@@ -2801,7 +2931,7 @@ namespace Mono.CSharp {
                                break;
 
                        case Operator.RightShift:
-                               if (isUnsigned)
+                               if (is_unsigned)
                                        opcode = OpCodes.Shr_Un;
                                else
                                        opcode = OpCodes.Shr;
@@ -2823,14 +2953,14 @@ namespace Mono.CSharp {
                                break;
 
                        case Operator.LessThan:
-                               if (isUnsigned)
+                               if (is_unsigned)
                                        opcode = OpCodes.Clt_Un;
                                else
                                        opcode = OpCodes.Clt;
                                break;
 
                        case Operator.GreaterThan:
-                               if (isUnsigned)
+                               if (is_unsigned)
                                        opcode = OpCodes.Cgt_Un;
                                else
                                        opcode = OpCodes.Cgt;
@@ -2839,7 +2969,7 @@ namespace Mono.CSharp {
                        case Operator.LessThanOrEqual:
                                Type lt = left.Type;
                                
-                               if (isUnsigned || (lt == TypeManager.double_type || lt == TypeManager.float_type))
+                               if (is_unsigned || (lt == TypeManager.double_type || lt == TypeManager.float_type))
                                        ig.Emit (OpCodes.Cgt_Un);
                                else
                                        ig.Emit (OpCodes.Cgt);
@@ -2851,7 +2981,7 @@ namespace Mono.CSharp {
                        case Operator.GreaterThanOrEqual:
                                Type le = left.Type;
                                
-                               if (isUnsigned || (le == TypeManager.double_type || le == TypeManager.float_type))
+                               if (is_unsigned || (le == TypeManager.double_type || le == TypeManager.float_type))
                                        ig.Emit (OpCodes.Clt_Un);
                                else
                                        ig.Emit (OpCodes.Clt);
@@ -3030,7 +3160,7 @@ namespace Mono.CSharp {
                                                // method might look at the type of this expression, see it is a
                                                // string and emit a string [] when we want an object [];
                                                
-                                               e = new EmptyCast (e, TypeManager.object_type);
+                                               e = EmptyCast.Create (e, TypeManager.object_type);
                                        }
                                        operands [i] = new Argument (e, Argument.AType.Expression);
                                }
@@ -3315,13 +3445,13 @@ namespace Mono.CSharp {
        ///   Implements the ternary conditional operator (?:)
        /// </summary>
        public class Conditional : Expression {
-               Expression expr, trueExpr, falseExpr;
+               Expression expr, true_expr, false_expr;
                
-               public Conditional (Expression expr, Expression trueExpr, Expression falseExpr)
+               public Conditional (Expression expr, Expression true_expr, Expression false_expr)
                {
                        this.expr = expr;
-                       this.trueExpr = trueExpr;
-                       this.falseExpr = falseExpr;
+                       this.true_expr = true_expr;
+                       this.false_expr = false_expr;
                        this.loc = expr.Location;
                }
 
@@ -3333,13 +3463,13 @@ namespace Mono.CSharp {
 
                public Expression TrueExpr {
                        get {
-                               return trueExpr;
+                               return true_expr;
                        }
                }
 
                public Expression FalseExpr {
                        get {
-                               return falseExpr;
+                               return false_expr;
                        }
                }
 
@@ -3352,7 +3482,7 @@ namespace Mono.CSharp {
 
 #if GMCS_SOURCE
                        if (TypeManager.IsNullableValueType (expr.Type))
-                               return new Nullable.LiftedConditional (expr, trueExpr, falseExpr, loc).Resolve (ec);
+                               return new Nullable.LiftedConditional (expr, true_expr, false_expr, loc).Resolve (ec);
 #endif
                        
                        if (expr.Type != TypeManager.bool_type){
@@ -3368,51 +3498,51 @@ namespace Mono.CSharp {
                                Report.Warning (665, 3, loc, "Assignment in conditional expression is always constant; did you mean to use == instead of = ?");
                        }
 
-                       trueExpr = trueExpr.Resolve (ec);
-                       falseExpr = falseExpr.Resolve (ec);
+                       true_expr = true_expr.Resolve (ec);
+                       false_expr = false_expr.Resolve (ec);
 
-                       if (trueExpr == null || falseExpr == null)
+                       if (true_expr == null || false_expr == null)
                                return null;
 
                        eclass = ExprClass.Value;
-                       if (trueExpr.Type == falseExpr.Type) {
-                               type = trueExpr.Type;
+                       if (true_expr.Type == false_expr.Type) {
+                               type = true_expr.Type;
                                if (type == TypeManager.null_type) {
                                        // TODO: probably will have to implement ConditionalConstant
                                        // to call method without return constant as well
                                        Report.Warning (-101, 1, loc, "Conditional expression will always return same value");
-                                       return trueExpr;
+                                       return true_expr;
                                }
                        } else {
                                Expression conv;
-                               Type true_type = trueExpr.Type;
-                               Type false_type = falseExpr.Type;
+                               Type true_type = true_expr.Type;
+                               Type false_type = false_expr.Type;
 
                                //
-                               // First, if an implicit conversion exists from trueExpr
-                               // to falseExpr, then the result type is of type falseExpr.Type
+                               // First, if an implicit conversion exists from true_expr
+                               // to false_expr, then the result type is of type false_expr.Type
                                //
-                               conv = Convert.ImplicitConversion (ec, trueExpr, false_type, loc);
+                               conv = Convert.ImplicitConversion (ec, true_expr, false_type, loc);
                                if (conv != null){
                                        //
                                        // Check if both can convert implicitl to each other's type
                                        //
-                                       if (Convert.ImplicitConversion (ec, falseExpr, true_type, loc) != null){
+                                       if (Convert.ImplicitConversion (ec, false_expr, true_type, loc) != null){
                                                Error (172,
                                                       "Can not compute type of conditional expression " +
-                                                      "as `" + TypeManager.CSharpName (trueExpr.Type) +
-                                                      "' and `" + TypeManager.CSharpName (falseExpr.Type) +
+                                                      "as `" + TypeManager.CSharpName (true_expr.Type) +
+                                                      "' and `" + TypeManager.CSharpName (false_expr.Type) +
                                                       "' convert implicitly to each other");
                                                return null;
                                        }
                                        type = false_type;
-                                       trueExpr = conv;
-                               } else if ((conv = Convert.ImplicitConversion(ec, falseExpr, true_type,loc))!= null){
+                                       true_expr = conv;
+                               } else if ((conv = Convert.ImplicitConversion(ec, false_expr, true_type,loc))!= null){
                                        type = true_type;
-                                       falseExpr = conv;
+                                       false_expr = conv;
                                } else {
                                        Report.Error (173, loc, "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'",
-                                               trueExpr.GetSignatureForError (), falseExpr.GetSignatureForError ());
+                                               true_expr.GetSignatureForError (), false_expr.GetSignatureForError ());
                                        return null;
                                }
                        }
@@ -3421,8 +3551,8 @@ namespace Mono.CSharp {
                        if (expr is BoolConstant){
                                BoolConstant bc = (BoolConstant) expr;
 
-                               Report.Warning (429, 4, bc.Value ? falseExpr.Location : trueExpr.Location, "Unreachable expression code detected");
-                               return bc.Value ? trueExpr : falseExpr;
+                               Report.Warning (429, 4, bc.Value ? false_expr.Location : true_expr.Location, "Unreachable expression code detected");
+                               return bc.Value ? true_expr : false_expr;
                        }
 
                        return this;
@@ -3440,10 +3570,10 @@ namespace Mono.CSharp {
                        Label end_target = ig.DefineLabel ();
 
                        expr.EmitBranchable (ec, false_target, false);
-                       trueExpr.Emit (ec);
+                       true_expr.Emit (ec);
                        ig.Emit (OpCodes.Br, end_target);
                        ig.MarkLabel (false_target);
-                       falseExpr.Emit (ec);
+                       false_expr.Emit (ec);
                        ig.MarkLabel (end_target);
                }
 
@@ -3452,8 +3582,8 @@ namespace Mono.CSharp {
                        Conditional target = (Conditional) t;
 
                        target.expr = expr.Clone (clonectx);
-                       target.trueExpr = trueExpr.Clone (clonectx);
-                       target.falseExpr = falseExpr.Clone (clonectx);
+                       target.true_expr = true_expr.Clone (clonectx);
+                       target.false_expr = false_expr.Clone (clonectx);
                }
        }
 
@@ -3495,9 +3625,6 @@ namespace Mono.CSharp {
                        EmitLoad (ec);
 
                        if (IsRef) {
-                               if (prepared)
-                                       ec.ig.Emit (OpCodes.Dup);
-       
                                //
                                // If we are a reference, we loaded on the stack a pointer
                                // Now lets load the real value
@@ -3525,13 +3652,20 @@ namespace Mono.CSharp {
                        prepared = prepare_for_load;
 
                        Variable.EmitInstance (ec);
-                       if (prepare_for_load && Variable.HasInstance)
-                               ig.Emit (OpCodes.Dup);
-                       else if (IsRef && !prepared)
+                       if (prepare_for_load) {
+                               if (Variable.HasInstance)
+                                       ig.Emit (OpCodes.Dup);
+                       }
+
+                       if (IsRef)
                                Variable.Emit (ec);
 
                        source.Emit (ec);
 
+                       // HACK: variable is already emitted when source is an initializer 
+                       if (source is NewInitialize)
+                               return;
+
                        if (leave_copy) {
                                ig.Emit (OpCodes.Dup);
                                if (IsRef || Variable.NeedsTemporary) {
@@ -3636,9 +3770,12 @@ namespace Mono.CSharp {
                                        return null;
                                }
 
-                               ScopeInfo scope = local_info.Block.CreateScopeInfo ();
-                               variable = scope.AddLocal (local_info);
-                               type = variable.Type;
+                               if (!ec.IsInProbingMode)
+                               {
+                                       ScopeInfo scope = local_info.Block.CreateScopeInfo ();
+                                       variable = scope.AddLocal (local_info);
+                                       type = variable.Type;
+                               }
                        }
 
                        return this;
@@ -3787,6 +3924,10 @@ namespace Mono.CSharp {
 
                public bool IsAssigned (EmitContext ec, Location loc)
                {
+                       // HACK: Variables are not captured in probing mode
+                       if (ec.IsInProbingMode)
+                               return true;
+                       
                        if (!ec.DoFlowAnalysis || !is_out || ec.CurrentBranching.IsAssigned (VariableInfo))
                                return true;
 
@@ -4039,6 +4180,19 @@ namespace Mono.CSharp {
                                ml.AddressOf (ec, mode);
                }
 
+               public void EmitArrayArgument (EmitContext ec)
+               {
+                       Type argtype = Expr.Type;
+                       Expr.Emit (ec);
+                               
+                       if (argtype == TypeManager.uint32_type)
+                               ec.ig.Emit (OpCodes.Conv_U);
+                       else if (argtype == TypeManager.int64_type)
+                               ec.ig.Emit (OpCodes.Conv_Ovf_I);
+                       else if (argtype == TypeManager.uint64_type)
+                               ec.ig.Emit (OpCodes.Conv_Ovf_I_Un);
+               }
+
                public Argument Clone (CloneContext clonectx)
                {
                        return new Argument (Expr.Clone (clonectx), ArgType);
@@ -4049,9 +4203,9 @@ namespace Mono.CSharp {
        ///   Invocation of methods or delegates.
        /// </summary>
        public class Invocation : ExpressionStatement {
-               ArrayList Arguments;
+               protected ArrayList Arguments;
                Expression expr;
-               MethodGroupExpr mg;
+               protected MethodGroupExpr mg;
                
                //
                // arguments is an ArrayList, but we do not want to typecast,
@@ -4086,325 +4240,27 @@ namespace Mono.CSharp {
                        return sb.ToString ();
                }
 
-               public static bool IsParamsMethodApplicable (EmitContext ec, MethodGroupExpr me,
-                                                            ArrayList arguments, int arg_count,
-                                                            ref MethodBase candidate)
-               {
-                       return IsParamsMethodApplicable (
-                               ec, me, arguments, arg_count, false, ref candidate) ||
-                               IsParamsMethodApplicable (
-                                       ec, me, arguments, arg_count, true, ref candidate);
-
-
-               }
-
-               static bool IsParamsMethodApplicable (EmitContext ec, MethodGroupExpr me,
-                                                     ArrayList arguments, int arg_count,
-                                                     bool do_varargs, ref MethodBase candidate)
-               {
-#if GMCS_SOURCE
-                       if (!me.HasTypeArguments &&
-                           !TypeManager.InferParamsTypeArguments (ec, arguments, ref candidate))
-                               return false;
-
-                       if (TypeManager.IsGenericMethodDefinition (candidate))
-                               throw new InternalErrorException ("a generic method definition took part in overload resolution");
-#endif
-
-                       return IsParamsMethodApplicable (
-                               ec, arguments, arg_count, candidate, do_varargs);
-               }
-
-               /// <summary>
-               ///   Determines if the candidate method, if a params method, is applicable
-               ///   in its expanded form to the given set of arguments
-               /// </summary>
-               static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments,
-                                                     int arg_count, MethodBase candidate,
-                                                     bool do_varargs)
+               public override Expression DoResolve (EmitContext ec)
                {
-                       ParameterData pd = TypeManager.GetParameterData (candidate);
-
-                       int pd_count = pd.Count;
-                       if (pd_count == 0)
-                               return false;
+                       Expression expr_resolved = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
+                       if (expr_resolved == null)
+                               return null;
 
-                       int count = pd_count - 1;
-                       if (do_varargs) {
-                               if (pd.ParameterModifier (count) != Parameter.Modifier.ARGLIST)
-                                       return false;
-                               if (pd_count != arg_count)
-                                       return false;
+                       mg = expr_resolved as MethodGroupExpr;
+                       if (mg == null) {
+                               Type expr_type = expr_resolved.Type;
 
-                               if (!(((Argument) arguments [count]).Expr is Arglist))
-                                       return false;
-                               --pd_count;
-                       } else {
-                               if (!pd.HasParams)
-                                       return false;
+                               if (expr_type != null && TypeManager.IsDelegateType (expr_type)){
+                                       return (new DelegateInvocation (
+                                               expr_resolved, Arguments, loc)).Resolve (ec);
+                               }
+                               
+                               expr_resolved.Error_UnexpectedKind (ResolveFlags.MethodGroup, loc);
+                               return null;
                        }
-                       
-                       if (count > arg_count)
-                               return false;
-                       
-                       if (pd_count == 1 && arg_count == 0)
-                               return true;
 
                        //
-                       // If we have come this far, the case which
-                       // remains is when the number of parameters is
-                       // less than or equal to the argument count.
-                       //
-                       int argument_index = 0;
-                       Argument a;
-                       for (int i = 0; i < pd_count; ++i) {
-
-                               if ((pd.ParameterModifier (i) & Parameter.Modifier.PARAMS) != 0) {
-                                       Type element_type = TypeManager.GetElementType (pd.ParameterType (i));
-                                       int params_args_count = arg_count - pd_count;
-                                       if (params_args_count < 0)
-                                               continue;
-
-                                       do {
-                                               a = (Argument) arguments [argument_index++];
-
-                                               if (!Convert.ImplicitConversionExists (ec, a.Expr, element_type))
-                                                       return false;
-                                       } while (params_args_count-- > 0);
-                                       continue;
-                               }
-
-                               a = (Argument) arguments [argument_index++];
-
-                               Parameter.Modifier a_mod = a.Modifier & 
-                                       (unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK)));
-                               Parameter.Modifier p_mod = pd.ParameterModifier (i) &
-                                       (unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK)));
-
-                               if (a_mod == p_mod) {
-
-                                       if (a_mod == Parameter.Modifier.NONE)
-                                               if (!Convert.ImplicitConversionExists (ec,
-                                                       a.Expr,
-                                                       pd.ParameterType (i)))
-                                                       return false;
-
-                                       if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
-                                               Type pt = pd.ParameterType (i);
-
-                                               if (!pt.IsByRef)
-                                                       pt = TypeManager.GetReferenceType (pt);
-                                               
-                                               if (pt != a.Type)
-                                                       return false;
-                                       }
-                               } else
-                                       return false;
-                               
-                       }
-
-                       return true;
-               }
-
-               public static bool IsApplicable (EmitContext ec, MethodGroupExpr me,
-                                                ArrayList arguments, int arg_count,
-                                                ref MethodBase method)
-               {
-                       MethodBase candidate = method;
-
-#if GMCS_SOURCE
-                       if (!me.HasTypeArguments &&
-                           !TypeManager.InferTypeArguments (ec, arguments, ref candidate))
-                               return false;
-
-                       if (TypeManager.IsGenericMethodDefinition (candidate))
-                               throw new InternalErrorException ("a generic method definition took part in overload resolution");
-#endif
-
-                       if (IsApplicable (ec, arguments, arg_count, candidate)) {
-                               method = candidate;
-                               return true;
-                       }
-
-                       return false;
-               }
-
-               /// <summary>
-               ///   Determines if the candidate method is applicable (section 14.4.2.1)
-               ///   to the given set of arguments
-               /// </summary>
-               public static bool IsApplicable (EmitContext ec, ArrayList arguments, int arg_count,
-                                                MethodBase candidate)
-               {
-                       ParameterData pd = TypeManager.GetParameterData (candidate);
-
-                       if (arg_count != pd.Count)
-                               return false;
-
-                       for (int i = arg_count; i > 0; ) {
-                               i--;
-
-                               Argument a = (Argument) arguments [i];
-                               
-                               Parameter.Modifier a_mod = a.Modifier &
-                                       ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
-
-                               Parameter.Modifier p_mod = pd.ParameterModifier (i) &
-                                       ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK | Parameter.Modifier.PARAMS);
-
-                               if (a_mod != p_mod)
-                                       return false;
-
-                               Type pt = pd.ParameterType (i);
-
-                               if (TypeManager.IsEqual (pt, a.Type))
-                                       continue;
-
-                               if (a_mod != Parameter.Modifier.NONE)
-                                       return false;
-
-                               // FIXME: Kill this abomination (EmitContext.TempEc)
-                               EmitContext prevec = EmitContext.TempEc;
-                               EmitContext.TempEc = ec;
-                               try {
-                                       if (!Convert.ImplicitConversionExists (ec, a.Expr, pt))
-                                               return false;
-                               } finally {
-                                       EmitContext.TempEc = prevec;
-                               }
-                       }
-
-                       return true;
-               }
-
-               public static void Error_WrongNumArguments (Location loc, String name, int arg_count)
-               {
-                       Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments",
-                               name, arg_count.ToString ());
-               }
-                        
-               static void Error_InvalidArguments (Location loc, int idx, MethodBase method,
-                                                    Type delegate_type, Argument a, ParameterData expected_par)
-               {
-                       if (delegate_type == null) 
-                               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 ((a.Modifier & Parameter.Modifier.ISBYREF) != 0 && mod != a.Modifier) {
-                               if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) == 0)
-                                       Report.Error (1615, loc, "Argument `{0}' should not be passed with the `{1}' keyword",
-                                               index, Parameter.GetModifierSignature (a.Modifier));
-                               else
-                                       Report.Error (1620, loc, "Argument `{0}' must be passed with the `{1}' keyword",
-                                               index, Parameter.GetModifierSignature (mod));
-                       } else {
-                               string p1 = Argument.FullDesc (a);
-                               string p2 = TypeManager.CSharpName (expected_par.ParameterType (idx));
-
-                               if (p1 == p2) {
-                                       Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous ");
-                                       Report.SymbolRelatedToPreviousError (a.Expr.Type);
-                                       Report.SymbolRelatedToPreviousError (expected_par.ParameterType (idx));
-                               }
-                               Report.Error (1503, loc, "Argument {0}: Cannot convert type `{1}' to `{2}'", index, p1, p2);
-                       }
-               }
-               
-               public static bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments,
-                                                         int arg_count, MethodBase method, 
-                                                         bool chose_params_expanded,
-                                                         Type delegate_type, bool may_fail,
-                                                         Location loc)
-               {
-                       ParameterData pd = TypeManager.GetParameterData (method);
-                       int j;
-                       int a_idx = 0;
-                       Argument a = null;
-                       for (j = 0; j < pd.Count; j++) {
-                               Type parameter_type = pd.ParameterType (j);
-                               Parameter.Modifier pm = pd.ParameterModifier (j);
-
-                               if (pm == Parameter.Modifier.ARGLIST) {
-                                       a = (Argument) Arguments [a_idx];
-                                       if (!(a.Expr is Arglist))
-                                               break;
-                                       ++a_idx;
-                                       continue;
-                               }
-
-                               int params_arg_count = 1;
-                               if (pm == Parameter.Modifier.PARAMS) {
-                                       pm = Parameter.Modifier.NONE;
-                                       params_arg_count = arg_count - pd.Count + 1;
-                                       if (chose_params_expanded)
-                                               parameter_type = TypeManager.GetElementType (parameter_type);
-                               }
-
-                               while (params_arg_count > 0) {
-                                       a = (Argument) Arguments [a_idx];
-                                       if (pm != a.Modifier)
-                                               break;
-
-                                       if (!TypeManager.IsEqual (a.Type, parameter_type)) {
-                                               if (pm == Parameter.Modifier.OUT || pm == Parameter.Modifier.REF)
-                                                       break;
-
-                                               Expression conv = Convert.ImplicitConversion (ec, a.Expr, parameter_type, loc);
-                                               if (conv == null)
-                                                       break;
-
-                                               // Update the argument with the implicit conversion
-                                               if (a.Expr != conv)
-                                                       a.Expr = conv;
-                                       }
-
-                                       --params_arg_count;
-                                       ++a_idx;
-                               }
-                               if (params_arg_count > 0)
-                                       break;
-
-                               if (parameter_type.IsPointer && !ec.InUnsafe) {
-                                       if (!may_fail)
-                                               UnsafeError (loc);
-                                       return false;
-                               }
-                       }
-
-                       if (a_idx == arg_count)
-                               return true;
-
-                       if (!may_fail)
-                               Error_InvalidArguments (loc, a_idx, method, delegate_type, a, pd);
-                       return false;
-               }
-
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       Expression expr_resolved = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
-                       if (expr_resolved == null)
-                               return null;
-
-                       mg = expr_resolved as MethodGroupExpr;
-                       if (mg == null) {
-                               Type expr_type = expr_resolved.Type;
-
-                               if (expr_type != null && TypeManager.IsDelegateType (expr_type)){
-                                       return (new DelegateInvocation (
-                                               expr_resolved, Arguments, loc)).Resolve (ec);
-                               }
-                               expr.Error_UnexpectedKind (ResolveFlags.MethodGroup, loc);
-                               return null;
-                       }
-
-                       //
-                       // Next, evaluate all the expressions in the argument list
+                       // Next, evaluate all the expressions in the argument list
                        //
                        if (Arguments != null){
                                foreach (Argument a in Arguments){
@@ -4413,28 +4269,25 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       mg = mg.OverloadResolve (ec, Arguments, false, loc);
+                       mg = DoResolveOverload (ec);
                        if (mg == null)
                                return null;
 
                        MethodInfo method = (MethodInfo)mg;
                        if (method != null) {
                                type = TypeManager.TypeToCoreType (method.ReturnType);
+
+                               // TODO: this is a copy of mg.ResolveMemberAccess method
                                Expression iexpr = mg.InstanceExpression;
                                if (method.IsStatic) {
-                                       if (iexpr == null || 
-                                           iexpr is This || iexpr is EmptyExpression ||
-                                           mg.IdenticalTypeName) {
+                                       if (iexpr == null ||
+                                               iexpr is This || iexpr is EmptyExpression ||
+                                               mg.IdenticalTypeName) {
                                                mg.InstanceExpression = null;
                                        } else {
                                                MemberExpr.error176 (loc, mg.GetSignatureForError ());
                                                return null;
                                        }
-                               } else {
-                                       if (iexpr == null || iexpr is EmptyExpression) {
-                                               SimpleName.Error_ObjectRefRequired (ec, loc, mg.GetSignatureForError ());
-                                               return null;
-                                       }
                                }
                        }
 
@@ -4453,7 +4306,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       if (Arguments == null && method.Name == "Finalize") {
+                       if (Arguments == null && method.DeclaringType == TypeManager.object_type && method.Name == "Finalize") {
                                if (mg.IsBase)
                                        Report.Error (250, loc, "Do not directly call your base class Finalize method. It is called automatically from your destructor");
                                else
@@ -4486,6 +4339,11 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               protected virtual MethodGroupExpr DoResolveOverload (EmitContext ec)
+               {
+                       return mg.OverloadResolve (ec, Arguments, false, loc);
+               }
+
                bool IsSpecialMethodInvocation (MethodBase method)
                {
                        if (!TypeManager.IsSpecialMethod (method))
@@ -4558,7 +4416,7 @@ namespace Mono.CSharp {
                        for (int i = 0; i < top; i++){
                                if (pd != null){
                                        if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){
-                                               //Type element_type = TypeManager.GetElementType (pd.ParameterType (i));
+                                               Type p_type = pd.ParameterType (i);
                                                int params_args_count = arguments == null ?
                                                        0 : arguments.Count - top + 1;
 
@@ -4566,23 +4424,27 @@ namespace Mono.CSharp {
                                                if (params_args_count <= 0) {
                                                        ILGenerator ig = ec.ig;
                                                        IntConstant.EmitInt (ig, 0);
-                                                       ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (i)));
-                                                       continue;
+                                                       ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (p_type));
+                                               } else {
+                                                       //
+                                                       // Special case if we are passing the same data as the
+                                                       // params argument, we do not need to recreate an array.
+                                                       //
+                                                       a = (Argument) arguments [argument_index];
+                                                       if (params_args_count == 1 && p_type == a.Type) {
+                                                               ++argument_index;
+                                                               a.Emit (ec);
+                                                       } else {
+                                                               EmitParams (ec, arguments, i, params_args_count);
+                                                               argument_index += params_args_count;
+                                                       }
                                                }
 
-                                               //
-                                               // Special case if we are passing the same data as the
-                                               // params argument, we do not need to recreate an array.
-                                               //
-                                               a = (Argument) arguments [argument_index];
-                                               if (params_args_count == 1 && pd.ParameterType (i) == a.Type) {
-                                                       ++argument_index;
-                                                       a.Emit (ec);
-                                                       continue;
+                                               if (dup_args) {
+                                                       ec.ig.Emit (OpCodes.Dup);
+                                                       temps [i] = new LocalTemporary (p_type);
+                                                       temps [i].Store (ec);
                                                }
-
-                                               EmitParams (ec, arguments, i, params_args_count);
-                                               argument_index += params_args_count;
                                                continue;
                                        }
                                }
@@ -4622,19 +4484,21 @@ namespace Mono.CSharp {
                /// <summary>
                /// This checks the ConditionalAttribute on the method 
                /// </summary>
-               static bool IsMethodExcluded (MethodBase method)
+               public static bool IsMethodExcluded (MethodBase method)
                {
                        if (method.IsConstructor)
                                return false;
 
-                       IMethodData md = TypeManager.GetMethod (method);
-                       if (md != null)
-                               return md.IsExcluded ();
+                       method = TypeManager.DropGenericMethodArguments (method);
+                       if (method.DeclaringType.Module == CodeGen.Module.Builder) {
+                               IMethodData md = TypeManager.GetMethod (method);
+                               if (md != null)
+                                       return md.IsExcluded ();
 
-                       // For some methods (generated by delegate class) GetMethod returns null
-                       // because they are not included in builder_to_method table
-                       if (method.DeclaringType is TypeBuilder)
+                               // For some methods (generated by delegate class) GetMethod returns null
+                               // because they are not included in builder_to_method table
                                return false;
+                       }
 
                        return AttributeTester.IsConditionalMethodExcluded (method);
                }
@@ -4982,8 +4846,8 @@ namespace Mono.CSharp {
                // If set, the new expression is for a value_target, and
                // we will not leave anything on the stack.
                //
-               Expression value_target;
-               bool value_target_set = false;
+               protected Expression value_target;
+               protected bool value_target_set;
                bool is_type_parameter = false;
                
                public New (Expression requested_type, ArrayList arguments, Location l)
@@ -4993,7 +4857,7 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public bool SetValueTypeVariable (Expression value)
+               public bool SetTargetVariable (Expression value)
                {
                        value_target = value;
                        value_target_set = true;
@@ -5119,6 +4983,12 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       if (type.IsPointer) {
+                               Report.Error (1919, loc, "Unsafe type `{0}' cannot be used in an object creation expression",
+                                       TypeManager.CSharpName (type));
+                               return null;
+                       }
+
                        if (Arguments == null) {
                                Expression c = Constantify (type);
                                if (c != null)
@@ -5192,29 +5062,25 @@ namespace Mono.CSharp {
                        Expression ml = MemberLookupFinal (ec, type, type, ".ctor",
                                MemberTypes.Constructor, AllBindingFlags | BindingFlags.DeclaredOnly, loc);
 
+                       if (Arguments != null){
+                               foreach (Argument a in Arguments){
+                                       if (!a.Resolve (ec, loc))
+                                               return null;
+                               }
+                       }
+
                        if (ml == null)
                                return null;
 
                        method = ml as MethodGroupExpr;
-
                        if (method == null) {
                                ml.Error_UnexpectedKind (ec.DeclContainer, "method group", loc);
                                return null;
                        }
 
-                       if (Arguments != null){
-                               foreach (Argument a in Arguments){
-                                       if (!a.Resolve (ec, loc))
-                                               return null;
-                               }
-                       }
-                       
                        method = method.OverloadResolve (ec, Arguments, false, loc);
-                       if (method == null) {
-                               if (almostMatchedMembers.Count != 0)
-                                       MemberLookupFailed (ec.ContainerType, type, type, ".ctor", null, true, loc);
+                       if (method == null)
                                return null;
-                       }
 
                        return this;
                }
@@ -5347,6 +5213,12 @@ namespace Mono.CSharp {
 
                }
 
+               public virtual bool HasInitializer {
+                       get {
+                               return false;
+                       }
+               }
+
                public void AddressOf (EmitContext ec, AddressOp Mode)
                {
                        if (is_type_parameter) {
@@ -5730,7 +5602,7 @@ namespace Mono.CSharp {
                        if (factor == 0)
                                throw new Exception ("unrecognized type in MakeByteBlob: " + array_element_type);
 
-                       data = new byte [(count * factor + 4) & ~3];
+                       data = new byte [(count * factor + 3) & ~3];
                        int idx = 0;
 
                        for (int i = 0; i < count; ++i) {
@@ -5977,17 +5849,8 @@ namespace Mono.CSharp {
 
                void EmitArrayArguments (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-                       
-                       foreach (Argument a in arguments) {
-                               Type atype = a.Type;
-                               a.Emit (ec);
-
-                               if (atype == TypeManager.uint64_type)
-                                       ig.Emit (OpCodes.Conv_Ovf_U4);
-                               else if (atype == TypeManager.int64_type)
-                                       ig.Emit (OpCodes.Conv_Ovf_I4);
-                       }
+                       foreach (Argument a in arguments)
+                               a.EmitArrayArgument (ec);
                }
                
                public override void Emit (EmitContext ec)
@@ -6018,7 +5881,7 @@ namespace Mono.CSharp {
                        }                               
                }
 
-               public override bool GetAttributableValue (Type valueType, out object value)
+               public override bool GetAttributableValue (Type value_type, out object value)
                {
                        if (arguments.Count != 1) {
                                // Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays");
@@ -6059,7 +5922,8 @@ namespace Mono.CSharp {
                {
                        ArrayCreation target = (ArrayCreation) t;
 
-                       target.requested_base_type = requested_base_type.Clone (clonectx);
+                       if (requested_base_type != null)
+                               target.requested_base_type = requested_base_type.Clone (clonectx);
 
                        if (arguments != null){
                                target.arguments = new ArrayList (arguments.Count);
@@ -6083,6 +5947,9 @@ namespace Mono.CSharp {
                public ImplicitlyTypedArrayCreation (string rank, ArrayList initializers, Location loc)
                        : base (null, rank, initializers, loc)
                {
+                       if (RootContext.Version <= LanguageVersion.ISO_2)
+                               Report.FeatureIsNotAvailable (loc, "implicitly typed arrays");
+                               
                        if (rank.Length > 2) {
                                while (rank [++dimensions] == ',');
                        } else {
@@ -6239,7 +6106,6 @@ namespace Mono.CSharp {
                                                      "Consider copying `this' to a local variable " +
                                                      "outside the anonymous method and using the " +
                                                      "local instead.");
-                                       return false;
                                }
 
                                RootScopeInfo host = block.Toplevel.RootScope;
@@ -6279,7 +6145,7 @@ namespace Mono.CSharp {
                                return null;
 
 
-                       if (ec.IsFieldInitializer) {
+                       if (ec.IsInFieldInitializer) {
                                Error (27, "Keyword `this' is not available in the current context");
                                return null;
                        }
@@ -6381,7 +6247,7 @@ namespace Mono.CSharp {
                        eclass = ExprClass.Variable;
                        type = TypeManager.runtime_argument_handle_type;
 
-                       if (ec.IsFieldInitializer || !ec.CurrentBlock.Toplevel.HasVarargs) 
+                       if (ec.IsInFieldInitializer || !ec.CurrentBlock.Toplevel.HasVarargs) 
                        {
                                Error (190, "The __arglist construct is valid only within " +
                                       "a variable argument method");
@@ -6525,7 +6391,7 @@ namespace Mono.CSharp {
                        ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
                }
 
-               public override bool GetAttributableValue (Type valueType, out object value)
+               public override bool GetAttributableValue (Type value_type, out object value)
                {
                        if (TypeManager.ContainsGenericParameters (typearg) &&
                                !TypeManager.IsGenericTypeDefinition (typearg)) {
@@ -6536,7 +6402,7 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       if (valueType == TypeManager.object_type) {
+                       if (value_type == TypeManager.object_type) {
                                value = (object)typearg;
                                return true;
                        }
@@ -6659,7 +6525,7 @@ namespace Mono.CSharp {
                public QualifiedAliasMember (string alias, string identifier, Location l)
                {
                        if (RootContext.Version == LanguageVersion.ISO_1)
-                               Report.FeatureIsNotISO1 (l, "namespace alias qualifier");
+                               Report.FeatureIsNotAvailable (l, "namespace alias qualifier");
 
                        this.alias = alias;
                        this.identifier = identifier;
@@ -6821,6 +6687,9 @@ namespace Mono.CSharp {
                                        "System.NullReferenceException");
                        }
 
+                       if (args != null)
+                               args.Resolve (ec);
+
                        Expression member_lookup;
                        member_lookup = MemberLookup (
                                ec.ContainerType, expr_type, expr_type, Identifier, loc);
@@ -6831,15 +6700,22 @@ namespace Mono.CSharp {
                        }
 #endif
                        if (member_lookup == null) {
-                               ExtensionMethodGroupExpr ex_method_lookup = ec.DeclContainer.LookupExtensionMethod (expr_type, Identifier);
+                               ExtensionMethodGroupExpr ex_method_lookup = ec.TypeContainer.LookupExtensionMethod (expr_type, Identifier);
                                if (ex_method_lookup != null) {
                                        ex_method_lookup.ExtensionExpression = expr_resolved;
+
+                                       if (args != null) {
+                                               ex_method_lookup.SetTypeArguments (args);
+                                               return ex_method_lookup.ResolveGeneric (ec, args);
+                                       }
+
                                        return ex_method_lookup.DoResolve (ec);
                                }
 
-                               if (!ec.IsInProbingMode)
-                                       MemberLookupFailed (
-                                               ec.ContainerType, expr_type, expr_type, Identifier, null, true, loc);
+                               expr = expr_resolved;
+                               Error_MemberLookupFailed (
+                                       ec.ContainerType, expr_type, expr_type, Identifier, null,
+                                       AllMemberTypes, AllBindingFlags);
                                return null;
                        }
 
@@ -6878,21 +6754,17 @@ namespace Mono.CSharp {
                        }
 
                        MemberExpr me = (MemberExpr) member_lookup;
-                       member_lookup = me.ResolveMemberAccess (ec, expr_resolved, loc, original);
-                       if (member_lookup == null)
+                       me = me.ResolveMemberAccess (ec, expr_resolved, loc, original);
+                       if (me == null)
                                return null;
 
                        if (args != null) {
-                               MethodGroupExpr mg = member_lookup as MethodGroupExpr;
-                               if (mg == null)
-                                       throw new InternalErrorException ();
-
-                               return mg.ResolveGeneric (ec, args);
+                               me.SetTypeArguments (args);
+                               return me.ResolveGeneric (ec, args);
                        }
 
                        if (original != null && !TypeManager.IsValueType (expr_type)) {
-                               me = member_lookup as MemberExpr;
-                               if (me != null && me.IsInstance) {
+                               if (me.IsInstance) {
                                        LocalVariableReference var = expr_resolved as LocalVariableReference;
                                        if (var != null && !var.VerifyAssigned (ec))
                                                return null;
@@ -6903,9 +6775,9 @@ namespace Mono.CSharp {
                        // check.
 
                        if (right_side != null)
-                               return member_lookup.DoResolveLValue (ec, right_side);
+                               return me.DoResolveLValue (ec, right_side);
                        else
-                               return member_lookup.DoResolve (ec);
+                               return me.DoResolve (ec);
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -7008,6 +6880,20 @@ namespace Mono.CSharp {
                        throw new Exception ("Should not happen");
                }
 
+               protected override void Error_TypeDoesNotContainDefinition (Type type, string name)
+               {
+                       if (RootContext.Version > LanguageVersion.ISO_2 &&
+                               ((expr.eclass & (ExprClass.Value | ExprClass.Variable)) != 0)) {
+                               Report.Error (1061, loc, "Type `{0}' does not contain a definition for `{1}' and no " +
+                                       "extension method `{1}' of type `{0}' could be found " +
+                                       "(are you missing a using directive or an assembly reference?)",
+                                       TypeManager.CSharpName (type), name);
+                               return;
+                       }
+
+                       base.Error_TypeDoesNotContainDefinition (type, name);
+               }
+
                public override string ToString ()
                {
                        return expr + "." + MemberName.MakeName (Identifier, args);
@@ -7061,10 +6947,10 @@ namespace Mono.CSharp {
                                Expr.Emit (ec);
                }
 
-               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
                {
                        using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
-                               Expr.EmitBranchable (ec, target, onTrue);
+                               Expr.EmitBranchable (ec, target, on_true);
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -7110,10 +6996,10 @@ namespace Mono.CSharp {
                                Expr.Emit (ec);
                }
                
-               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
                {
                        using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
-                               Expr.EmitBranchable (ec, target, onTrue);
+                               Expr.EmitBranchable (ec, target, on_true);
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -7220,12 +7106,15 @@ namespace Mono.CSharp {
                        if (!CommonResolve (ec))
                                return null;
 
-                       Type t = Expr.Type;
-                       if (t.IsArray)
+                       type = Expr.Type;
+                       if (type.IsArray)
                                return (new ArrayAccess (this, loc)).DoResolveLValue (ec, right_side);
 
-                       if (t.IsPointer)
-                               return MakePointerAccess (ec, t);
+                       if (type.IsPointer)
+                               return MakePointerAccess (ec, type);
+
+                       if (Expr.eclass != ExprClass.Variable && type.IsValueType)
+                               Error_CannotModifyIntermediateExpressionValue (ec);
 
                        return (new IndexerAccess (this, loc)).DoResolveLValue (ec, right_side);
                }
@@ -7235,6 +7124,11 @@ namespace Mono.CSharp {
                        throw new Exception ("Should never be reached");
                }
 
+               public override string GetSignatureForError ()
+               {
+                       return Expr.GetSignatureForError ();
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        ElementAccess target = (ElementAccess) t;
@@ -7256,6 +7150,8 @@ namespace Mono.CSharp {
                ElementAccess ea;
 
                LocalTemporary temp;
+               LocalTemporary prepared_value;
+
                bool prepared;
                
                public ArrayAccess (ElementAccess ea_data, Location l)
@@ -7330,8 +7226,14 @@ namespace Mono.CSharp {
                ///    Emits the right opcode to load an object of Type `t'
                ///    from an array of T
                /// </summary>
-               static public void EmitLoadOpcode (ILGenerator ig, Type type)
+               void EmitLoadOpcode (ILGenerator ig, Type type, int rank)
                {
+                       if (rank > 1) {
+                               MethodInfo get = FetchGetMethod ();
+                               ig.Emit (OpCodes.Call, get);
+                               return;
+                       }
+
                        if (type == TypeManager.byte_type || type == TypeManager.bool_type)
                                ig.Emit (OpCodes.Ldelem_U1);
                        else if (type == TypeManager.sbyte_type)
@@ -7355,7 +7257,7 @@ namespace Mono.CSharp {
                        else if (type == TypeManager.intptr_type)
                                ig.Emit (OpCodes.Ldelem_I);
                        else if (TypeManager.IsEnumType (type)){
-                               EmitLoadOpcode (ig, TypeManager.EnumToUnderlying (type));
+                               EmitLoadOpcode (ig, TypeManager.EnumToUnderlying (type), rank);
                        } else if (type.IsValueType){
                                ig.Emit (OpCodes.Ldelema, type);
                                ig.Emit (OpCodes.Ldobj, type);
@@ -7466,21 +7368,32 @@ namespace Mono.CSharp {
                // initialized), then load the arguments the first time and store them
                // in locals.  otherwise load from local variables.
                //
-               void LoadArrayAndArguments (EmitContext ec)
+               // prepare_for_load is used in compound assignments to cache original index
+               // values ( label[idx++] += s )
+               //
+               LocalTemporary [] LoadArrayAndArguments (EmitContext ec, bool prepare_for_load)
                {
-                       ILGenerator ig = ec.ig;
-                       
                        ea.Expr.Emit (ec);
-                       foreach (Argument a in ea.Arguments){
-                               Type argtype = a.Expr.Type;
-                               
-                               a.Expr.Emit (ec);
-                               
-                               if (argtype == TypeManager.int64_type)
-                                       ig.Emit (OpCodes.Conv_Ovf_I);
-                               else if (argtype == TypeManager.uint64_type)
-                                       ig.Emit (OpCodes.Conv_Ovf_I_Un);
+
+                       LocalTemporary[] indexes = null;
+                       if (prepare_for_load) {
+                               ec.ig.Emit (OpCodes.Dup);
+                               indexes = new LocalTemporary [ea.Arguments.Count];
+                       }
+
+                       for (int i = 0; i < ea.Arguments.Count; ++i) {
+                               ((Argument)ea.Arguments [i]).EmitArrayArgument (ec);
+                               if (!prepare_for_load)
+                                       continue;
+
+                               // Keep original array index value on the stack
+                               ec.ig.Emit (OpCodes.Dup);
+
+                               indexes [i] = new LocalTemporary (TypeManager.intptr_type);
+                               indexes [i].Store (ec);
                        }
+
+                       return indexes;
                }
 
                public void Emit (EmitContext ec, bool leave_copy)
@@ -7488,22 +7401,17 @@ namespace Mono.CSharp {
                        int rank = ea.Expr.Type.GetArrayRank ();
                        ILGenerator ig = ec.ig;
 
-                       if (!prepared) {
-                               LoadArrayAndArguments (ec);
-                               
-                               if (rank == 1)
-                                       EmitLoadOpcode (ig, type);
-                               else {
-                                       MethodInfo method;
-                                       
-                                       method = FetchGetMethod ();
-                                       ig.Emit (OpCodes.Call, method);
-                               }
-                       } else
-                               LoadFromPtr (ec.ig, this.type);
-                       
+                       if (prepared_value != null) {
+                               prepared_value.Emit (ec);
+                       } else if (prepared) {
+                               LoadFromPtr (ig, this.type);
+                       } else {
+                               LoadArrayAndArguments (ec, false);
+                               EmitLoadOpcode (ig, type, rank);
+                       }       
+
                        if (leave_copy) {
-                               ec.ig.Emit (OpCodes.Dup);
+                               ig.Emit (OpCodes.Dup);
                                temp = new LocalTemporary (this.type);
                                temp.Store (ec);
                        }
@@ -7519,39 +7427,39 @@ namespace Mono.CSharp {
                        int rank = ea.Expr.Type.GetArrayRank ();
                        ILGenerator ig = ec.ig;
                        Type t = source.Type;
-                       prepared = prepare_for_load;
+                       prepared = prepare_for_load && !(source is StringConcat);
 
-                       if (prepare_for_load) {
+                       if (prepared) {
                                AddressOf (ec, AddressOp.LoadStore);
                                ec.ig.Emit (OpCodes.Dup);
-                               source.Emit (ec);
-                               if (leave_copy) {
-                                       ec.ig.Emit (OpCodes.Dup);
-                                       temp = new LocalTemporary (this.type);
-                                       temp.Store (ec);
-                               }
-                               StoreFromPtr (ec.ig, t);
-                               
-                               if (temp != null) {
-                                       temp.Emit (ec);
-                                       temp.Release (ec);
+                       } else {
+                               LocalTemporary[] original_indexes_values = LoadArrayAndArguments (ec,
+                                       prepare_for_load && (source is StringConcat));
+
+                               if (original_indexes_values != null) {
+                                       prepared_value = new LocalTemporary (type);
+                                       EmitLoadOpcode (ig, type, rank);
+                                       prepared_value.Store (ec);
+                                       foreach (LocalTemporary lt in original_indexes_values) {
+                                               lt.Emit (ec);
+                                               lt.Release (ec);
+                                       }
                                }
-                               
-                               return;
                        }
-                       
-                       LoadArrayAndArguments (ec);
 
                        if (rank == 1) {
                                bool is_stobj, has_type_arg;
                                OpCode op = GetStoreOpcode (t, out is_stobj, out has_type_arg);
-                               //
-                               // The stobj opcode used by value types will need
-                               // an address on the stack, not really an array/array
-                               // pair
-                               //
-                               if (is_stobj)
-                                       ig.Emit (OpCodes.Ldelema, t);
+
+                               if (!prepared) {
+                                       //
+                                       // The stobj opcode used by value types will need
+                                       // an address on the stack, not really an array/array
+                                       // pair
+                                       //
+                                       if (is_stobj)
+                                               ig.Emit (OpCodes.Ldelema, t);
+                               }
                                
                                source.Emit (ec);
                                if (leave_copy) {
@@ -7560,39 +7468,41 @@ namespace Mono.CSharp {
                                        temp.Store (ec);
                                }
                                
-                               if (is_stobj)
+                               if (prepared)
+                                       StoreFromPtr (ig, t);
+                               else if (is_stobj)
                                        ig.Emit (OpCodes.Stobj, t);
                                else if (has_type_arg)
                                        ig.Emit (op, t);
                                else
                                        ig.Emit (op);
                        } else {
-                               ModuleBuilder mb = CodeGen.Module.Builder;
-                               int arg_count = ea.Arguments.Count;
-                               Type [] args = new Type [arg_count + 1];
-                               MethodInfo set;
-                               
                                source.Emit (ec);
                                if (leave_copy) {
                                        ec.ig.Emit (OpCodes.Dup);
                                        temp = new LocalTemporary (this.type);
                                        temp.Store (ec);
                                }
-                               
-                               for (int i = 0; i < arg_count; i++){
-                                       //args [i++] = a.Type;
-                                       args [i] = TypeManager.int32_type;
-                               }
 
-                               args [arg_count] = type;
-                               
-                               set = mb.GetArrayMethod (
-                                       ea.Expr.Type, "Set",
-                                       CallingConventions.HasThis |
-                                       CallingConventions.Standard,
-                                       TypeManager.void_type, args);
-                               
-                               ig.Emit (OpCodes.Call, set);
+                               if (prepared) {
+                                       StoreFromPtr (ig, t);
+                               } else {
+                                       int arg_count = ea.Arguments.Count;
+                                       Type [] args = new Type [arg_count + 1];
+                                       for (int i = 0; i < arg_count; i++) {
+                                               //args [i++] = a.Type;
+                                               args [i] = TypeManager.int32_type;
+                                       }
+                                       args [arg_count] = type;
+
+                                       MethodInfo set = CodeGen.Module.Builder.GetArrayMethod (
+                                               ea.Expr.Type, "Set",
+                                               CallingConventions.HasThis |
+                                               CallingConventions.Standard,
+                                               TypeManager.void_type, args);
+
+                                       ig.Emit (OpCodes.Call, set);
+                               }
                        }
                        
                        if (temp != null) {
@@ -7606,7 +7516,7 @@ namespace Mono.CSharp {
                        int rank = ea.Expr.Type.GetArrayRank ();
                        ILGenerator ig = ec.ig;
 
-                       LoadArrayAndArguments (ec);
+                       LoadArrayAndArguments (ec, false);
 
                        if (rank == 1){
                                ig.Emit (OpCodes.Ldelema, type);
@@ -7631,115 +7541,135 @@ namespace Mono.CSharp {
                        }
                }
        }
-       
-       class Indexers {
-               // note that the ArrayList itself in mutable.  We just can't assign to 'Properties' again.
-               public readonly ArrayList Properties;
-               static Indexers empty;
-
-               public struct Indexer {
-                       public readonly PropertyInfo PropertyInfo;
-                       public readonly MethodInfo Getter, Setter;
 
-                       public Indexer (PropertyInfo property_info, MethodInfo get, MethodInfo set)
-                       {
-                               this.PropertyInfo = property_info;
-                               this.Getter = get;
-                               this.Setter = set;
-                       }
-               }
-
-               static Indexers ()
+       /// <summary>
+       ///   Expressions that represent an indexer call.
+       /// </summary>
+       public class IndexerAccess : Expression, IAssignMethod
+       {
+               class IndexerMethodGroupExpr : MethodGroupExpr
                {
-                       empty = new Indexers (null);
-               }
+                       public IndexerMethodGroupExpr (Indexers indexers, Location loc)
+                               : base (null, loc)
+                       {
+                               Methods = (MethodBase []) indexers.Methods.ToArray (typeof (MethodBase));
+                       }
 
-               Indexers (ArrayList array)
-               {
-                       Properties = array;
-               }
+                       public override string Name {
+                               get {
+                                       return "this";
+                               }
+                       }
 
-               static void Append (ref Indexers ix, Type caller_type, MemberInfo [] mi)
-               {
-                       bool dummy;
-                       if (mi == null)
-                               return;
-                       foreach (PropertyInfo property in mi){
-                               MethodInfo get, set;
+                       protected override int GetApplicableParametersCount (MethodBase method, ParameterData parameters)
+                       {
+                               //
+                               // Here is the trick, decrease number of arguments by 1 when only
+                               // available property method is setter. This makes overload resolution
+                               // work correctly for indexers.
+                               //
                                
-                               get = property.GetGetMethod (true);
-                               set = property.GetSetMethod (true);
-                               if (get != null && !Expression.IsAccessorAccessible (caller_type, get, out dummy))
-                                       get = null;
-                               if (set != null && !Expression.IsAccessorAccessible (caller_type, set, out dummy))
-                                       set = null;
-                               if (get != null || set != null) {
-                                       if (ix == empty)
-                                               ix = new Indexers (new ArrayList ());
-                                       ix.Properties.Add (new Indexer (property, get, set));
-                               }
+                               if (method.Name [0] == 'g')
+                                       return parameters.Count;
+
+                               return parameters.Count - 1;
                        }
                }
 
-               static private MemberInfo [] GetIndexersForTypeOrInterface (Type caller_type, Type lookup_type)
+               class Indexers
                {
-                       string p_name = TypeManager.IndexerPropertyName (lookup_type);
+                       // Contains either property getter or setter
+                       public ArrayList Methods;
+                       public ArrayList Properties;
 
-                       return TypeManager.MemberLookup (
-                               caller_type, caller_type, lookup_type, MemberTypes.Property,
-                               BindingFlags.Public | BindingFlags.Instance |
-                               BindingFlags.DeclaredOnly, p_name, null);
-               }
-               
-               static public Indexers GetIndexersForType (Type caller_type, Type lookup_type) 
-               {
-                       Indexers ix = empty;
+                       Indexers ()
+                       {
+                       }
 
-#if GMCS_SOURCE
-                       if (lookup_type.IsGenericParameter) {
-                               GenericConstraints gc = TypeManager.GetTypeParameterConstraints (lookup_type);
-                               if (gc == null)
-                                       return empty;
+                       void Append (Type caller_type, MemberInfo [] mi)
+                       {
+                               if (mi == null)
+                                       return;
 
-                               if (gc.HasClassConstraint)
-                                       Append (ref ix, caller_type, GetIndexersForTypeOrInterface (caller_type, gc.ClassConstraint));
+                               foreach (PropertyInfo property in mi) {
+                                       MethodInfo accessor = property.GetGetMethod (true);
+                                       if (accessor == null)
+                                               accessor = property.GetSetMethod (true);
 
-                               Type[] ifaces = gc.InterfaceConstraints;
-                               foreach (Type itype in ifaces)
-                                       Append (ref ix, caller_type, GetIndexersForTypeOrInterface (caller_type, itype));
+                                       if (Methods == null) {
+                                               Methods = new ArrayList ();
+                                               Properties = new ArrayList ();
+                                       }
 
-                               return ix;
+                                       Methods.Add (accessor);
+                                       Properties.Add (property);
+                               }
                        }
-#endif
 
-                       Type copy = lookup_type;
-                       while (copy != TypeManager.object_type && copy != null){
-                               Append (ref ix, caller_type, GetIndexersForTypeOrInterface (caller_type, copy));
-                               copy = copy.BaseType;
+                       static MemberInfo [] GetIndexersForTypeOrInterface (Type caller_type, Type lookup_type)
+                       {
+                               string p_name = TypeManager.IndexerPropertyName (lookup_type);
+
+                               return TypeManager.MemberLookup (
+                                       caller_type, caller_type, lookup_type, MemberTypes.Property,
+                                       BindingFlags.Public | BindingFlags.Instance |
+                                       BindingFlags.DeclaredOnly, p_name, null);
                        }
+                       
+                       public static Indexers GetIndexersForType (Type caller_type, Type lookup_type) 
+                       {
+                               Indexers ix = new Indexers ();
+
+       #if GMCS_SOURCE
+                               if (lookup_type.IsGenericParameter) {
+                                       GenericConstraints gc = TypeManager.GetTypeParameterConstraints (lookup_type);
+                                       if (gc == null)
+                                               return ix;
+
+                                       if (gc.HasClassConstraint)
+                                               ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, gc.ClassConstraint));
 
-                       if (lookup_type.IsInterface) {
-                               Type [] ifaces = TypeManager.GetInterfaces (lookup_type);
-                               if (ifaces != null) {
+                                       Type[] ifaces = gc.InterfaceConstraints;
                                        foreach (Type itype in ifaces)
-                                               Append (ref ix, caller_type, GetIndexersForTypeOrInterface (caller_type, itype));
+                                               ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, itype));
+
+                                       return ix;
+                               }
+       #endif
+
+                               Type copy = lookup_type;
+                               while (copy != TypeManager.object_type && copy != null){
+                                       ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, copy));
+                                       copy = copy.BaseType;
+                               }
+
+                               if (lookup_type.IsInterface) {
+                                       Type [] ifaces = TypeManager.GetInterfaces (lookup_type);
+                                       if (ifaces != null) {
+                                               foreach (Type itype in ifaces)
+                                                       ix.Append (caller_type, GetIndexersForTypeOrInterface (caller_type, itype));
+                                       }
                                }
+
+                               return ix;
                        }
+               }
 
-                       return ix;
+               enum AccessorType
+               {
+                       Get,
+                       Set
                }
-       }
 
-       /// <summary>
-       ///   Expressions that represent an indexer call.
-       /// </summary>
-       public class IndexerAccess : Expression, IAssignMethod {
                //
                // Points to our "data" repository
                //
                MethodInfo get, set;
-               ArrayList set_arguments;
                bool is_base_indexer;
+               bool prepared;
+               LocalTemporary temp;
+               LocalTemporary prepared_value;
+               Expression set_expr;
 
                protected Type indexer_type;
                protected Type current_type;
@@ -7761,6 +7691,17 @@ namespace Mono.CSharp {
                        this.loc = loc;
                }
 
+               static string GetAccessorName (AccessorType at)
+               {
+                       if (at == AccessorType.Set)
+                               return "set";
+
+                       if (at == AccessorType.Get)
+                               return "get";
+
+                       throw new NotImplementedException (at.ToString ());
+               }
+
                protected virtual bool CommonResolve (EmitContext ec)
                {
                        indexer_type = instance_expr.Type;
@@ -7771,67 +7712,7 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       if (!CommonResolve (ec))
-                               return null;
-
-                       //
-                       // Step 1: Query for all `Item' *properties*.  Notice
-                       // that the actual methods are pointed from here.
-                       //
-                       // This is a group of properties, piles of them.  
-
-                       ArrayList AllGetters = null;
-
-                       Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type);
-                       if (ilist.Properties != null) {
-                               AllGetters = new ArrayList(ilist.Properties.Count);
-                               foreach (Indexers.Indexer ix in ilist.Properties) {
-                                       if (ix.Getter != null)
-                                               AllGetters.Add (ix.Getter);
-                               }
-                       }
-
-                       if (AllGetters == null) {
-                               Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `{0}'",
-                                       TypeManager.CSharpName (indexer_type));
-                               return null;
-                       }
-
-                       if (AllGetters.Count == 0) {
-                               // FIXME: we cannot simply select first one as the error message is missleading when
-                               // multiple indexers exist
-                               Indexers.Indexer first_indexer = (Indexers.Indexer)ilist.Properties[ilist.Properties.Count - 1];
-                               Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
-                                       TypeManager.GetFullNameSignature (first_indexer.PropertyInfo));
-                               return null;
-                       }
-
-                       get = (MethodInfo)new MethodGroupExpr (AllGetters, loc).OverloadResolve (ec,
-                                       arguments, false, loc);
-
-                       if (get == null) {
-                               Invocation.Error_WrongNumArguments (loc, "this", arguments.Count);
-                               return null;
-                       }
-
-                       //
-                       // Only base will allow this invocation to happen.
-                       //
-                       if (get.IsAbstract && this is BaseIndexerAccess){
-                               Error_CannotCallAbstractBase (TypeManager.CSharpSignature (get));
-                               return null;
-                       }
-
-                       type = get.ReturnType;
-                       if (type.IsPointer && !ec.InUnsafe){
-                               UnsafeError (loc);
-                               return null;
-                       }
-
-                       instance_expr.CheckMarshalByRefAccess ();
-                       
-                       eclass = ExprClass.IndexerAccess;
-                       return this;
+                       return ResolveAccessor (ec, AccessorType.Get);
                }
 
                public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
@@ -7844,82 +7725,106 @@ namespace Mono.CSharp {
 
                        // if the indexer returns a value type, and we try to set a field in it
                        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);
                        }
 
-                       ArrayList AllSetters = new ArrayList();
-                       if (!CommonResolve (ec))
+                       Expression e = ResolveAccessor (ec, AccessorType.Set);
+                       if (e == null)
                                return null;
 
-                       bool found_any = false, found_any_setters = false;
+                       set_expr = Convert.ImplicitConversion (ec, right_side, type, loc);
+                       return e;
+               }
+
+               Expression ResolveAccessor (EmitContext ec, AccessorType accessorType)
+               {
+                       if (!CommonResolve (ec))
+                               return null;
 
                        Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type);
-                       if (ilist.Properties != null) {
-                               found_any = true;
-                               foreach (Indexers.Indexer ix in ilist.Properties) {
-                                       if (ix.Setter != null)
-                                               AllSetters.Add (ix.Setter);
-                               }
-                       }
-                       if (AllSetters.Count > 0) {
-                               found_any_setters = true;
-                               set_arguments = (ArrayList) arguments.Clone ();
-                               set_arguments.Add (new Argument (right_side, Argument.AType.Expression));
-                               set = (MethodInfo)(new MethodGroupExpr (AllSetters, loc)).OverloadResolve (
-                                       ec,
-                                       set_arguments, false, loc);
-                       }
-
-                       if (!found_any) {
+                       if (ilist.Methods == null) {
                                Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `{0}'",
-                                             TypeManager.CSharpName (indexer_type));
+                                                 TypeManager.CSharpName (indexer_type));
                                return null;
                        }
 
-                       if (!found_any_setters) {
-                               Error (154, "indexer can not be used in this context, because " +
-                                      "it lacks a `set' accessor");
+                       MethodGroupExpr mg = new IndexerMethodGroupExpr (ilist, loc);
+                       mg = mg.OverloadResolve (ec, arguments, false, loc);
+                       if (mg == null)
                                return null;
+
+                       MethodInfo mi = (MethodInfo) mg;
+                       PropertyInfo pi = null;
+                       for (int i = 0; i < ilist.Methods.Count; ++i) {
+                               if (ilist.Methods [i] == mi) {
+                                       pi = (PropertyInfo) ilist.Properties [i];
+                                       break;
+                               }
                        }
 
-                       if (set == null) {
-                               Invocation.Error_WrongNumArguments (loc, "this", arguments.Count);
+                       type = pi.PropertyType;
+                       if (type.IsPointer && !ec.InUnsafe)
+                               UnsafeError (loc);
+
+                       MethodInfo accessor;
+                       if (accessorType == AccessorType.Get) {
+                               accessor = get = pi.GetGetMethod (true);
+                       } else {
+                               accessor = set = pi.GetSetMethod (true);
+                               if (accessor == null && pi.GetGetMethod (true) != null) {
+                                       Report.SymbolRelatedToPreviousError (pi);
+                                       Report.Error (200, loc, "The read only property or indexer `{0}' cannot be assigned to",
+                                               TypeManager.GetFullNameSignature (pi));
+                                       return null;
+                               }
+                       }
+
+                       if (accessor == null) {
+                               Report.SymbolRelatedToPreviousError (pi);
+                               Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks a `{1}' accessor",
+                                       TypeManager.GetFullNameSignature (pi), GetAccessorName (accessorType));
                                return null;
                        }
 
                        //
                        // Only base will allow this invocation to happen.
                        //
-                       if (set.IsAbstract && this is BaseIndexerAccess){
-                               Error_CannotCallAbstractBase (TypeManager.CSharpSignature (set));
-                               return null;
+                       if (accessor.IsAbstract && this is BaseIndexerAccess) {
+                               Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (pi));
                        }
 
-                       //
-                       // Now look for the actual match in the list of indexers to set our "return" type
-                       //
-                       type = TypeManager.void_type;   // default value
-                       foreach (Indexers.Indexer ix in ilist.Properties){
-                               if (ix.Setter == set){
-                                       type = ix.PropertyInfo.PropertyType;
-                                       break;
+                       bool must_do_cs1540_check;
+                       if (!IsAccessorAccessible (ec.ContainerType, accessor, out must_do_cs1540_check)) {
+                               if (set == null)
+                                       set = pi.GetSetMethod (true);
+                               else
+                                       get = pi.GetGetMethod (true);
+
+                               if (set != null && get != null &&
+                                       (set.Attributes & MethodAttributes.MemberAccessMask) != (get.Attributes & MethodAttributes.MemberAccessMask)) {
+                                       Report.SymbolRelatedToPreviousError (accessor);
+                                       Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because a `{1}' accessor is inaccessible",
+                                               TypeManager.GetFullNameSignature (pi), GetAccessorName (accessorType));
+                               } else {
+                                       Report.SymbolRelatedToPreviousError (pi);
+                                       ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (pi));
                                }
                        }
 
                        instance_expr.CheckMarshalByRefAccess ();
-
                        eclass = ExprClass.IndexerAccess;
                        return this;
                }
                
-               bool prepared = false;
-               LocalTemporary temp;
-               
                public void Emit (EmitContext ec, bool leave_copy)
                {
-                       Invocation.EmitCall (ec, is_base_indexer, instance_expr, get, arguments, loc, prepared, false);
+                       if (prepared) {
+                               prepared_value.Emit (ec);
+                       } else {
+                               Invocation.EmitCall (ec, is_base_indexer, instance_expr, get,
+                                       arguments, loc, false, false);
+                       }
+
                        if (leave_copy) {
                                ec.ig.Emit (OpCodes.Dup);
                                temp = new LocalTemporary (Type);
@@ -7935,10 +7840,17 @@ namespace Mono.CSharp {
                public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
                        prepared = prepare_for_load;
-                       Argument a = (Argument) set_arguments [set_arguments.Count - 1];
-                       
+                       Expression value = set_expr;
+
                        if (prepared) {
+                               Invocation.EmitCall (ec, is_base_indexer, instance_expr, get,
+                                       arguments, loc, true, false);
+
+                               prepared_value = new LocalTemporary (type);
+                               prepared_value.Store (ec);
                                source.Emit (ec);
+                               prepared_value.Release (ec);
+
                                if (leave_copy) {
                                        ec.ig.Emit (OpCodes.Dup);
                                        temp = new LocalTemporary (Type);
@@ -7948,10 +7860,11 @@ namespace Mono.CSharp {
                                temp = new LocalTemporary (Type);
                                source.Emit (ec);
                                temp.Store (ec);
-                               a.Expr = temp;
+                               value = temp;
                        }
                        
-                       Invocation.EmitCall (ec, is_base_indexer, instance_expr, set, set_arguments, loc, false, prepared);
+                       arguments.Add (new Argument (value, Argument.AType.Expression));
+                       Invocation.EmitCall (ec, is_base_indexer, instance_expr, set, arguments, loc, false, prepared);
                        
                        if (temp != null) {
                                temp.Emit (ec);
@@ -7959,7 +7872,6 @@ namespace Mono.CSharp {
                        }
                }
                
-               
                public override void Emit (EmitContext ec)
                {
                        Emit (ec, false);
@@ -7967,8 +7879,7 @@ namespace Mono.CSharp {
 
                public override string GetSignatureForError ()
                {
-                       // FIXME: print the argument list of the indexer
-                       return instance_expr.GetSignatureForError () + ".this[...]";
+                       return TypeManager.CSharpSignature (get != null ? get : set, false);
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -8046,7 +7957,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       if (ec.IsFieldInitializer){
+                       if (ec.IsInFieldInitializer){
                                Error (1512, "Keyword `base' is not available in the current context");
                                return null;
                        }
@@ -8054,7 +7965,8 @@ namespace Mono.CSharp {
                        member_lookup = MemberLookup (ec.ContainerType, null, base_type, Identifier,
                                                      AllMemberTypes, AllBindingFlags, loc);
                        if (member_lookup == null) {
-                               MemberLookupFailed (ec.ContainerType, base_type, base_type, Identifier, null, true, loc);
+                               Error_MemberLookupFailed (ec.ContainerType, base_type, base_type, Identifier,
+                                       null, AllMemberTypes, AllBindingFlags);
                                return null;
                        }
 
@@ -8066,31 +7978,18 @@ namespace Mono.CSharp {
                                left = ec.GetThis (loc);
 
                        MemberExpr me = (MemberExpr) member_lookup;
-                       
-                       Expression e = me.ResolveMemberAccess (ec, left, loc, null);
-
-                       if (e is PropertyExpr) {
-                               PropertyExpr pe = (PropertyExpr) e;
-                               pe.IsBase = true;
-                       } else if (e is EventExpr) {
-                               EventExpr ee = (EventExpr) e;
-                               ee.IsBase = true;
-                       }
-
-                       MethodGroupExpr mg = e as MethodGroupExpr;
-                       if (mg != null)
-                               mg.IsBase = true;
+                       me = me.ResolveMemberAccess (ec, left, loc, null);
+                       if (me == null)
+                               return null;
 
+                       me.IsBase = true;
                        if (args != null) {
-                               if (mg != null)
-                                       return mg.ResolveGeneric (ec, args);
-
-                               Report.Error (307, loc, "`{0}' cannot be used with type arguments",
-                                             Identifier);
-                               return null;
+                               args.Resolve (ec);
+                               me.SetTypeArguments (args);
+                               return me.ResolveGeneric (ec, args);
                        }
 
-                       return e;
+                       return me;
                }
 
                public override void Emit (EmitContext ec)
@@ -8102,7 +8001,8 @@ namespace Mono.CSharp {
                {
                        BaseAccess target = (BaseAccess) t;
 
-                       target.args = args.Clone ();
+                       if (args != null)
+                               target.args = args.Clone ();
                }
        }
 
@@ -8199,6 +8099,36 @@ namespace Mono.CSharp {
                        type = t;
                }
        }
+       
+       //
+       // Empty statement expression
+       //
+       public sealed class EmptyExpressionStatement : ExpressionStatement
+       {
+               public static readonly EmptyExpressionStatement Instance = new EmptyExpressionStatement ();
+
+               private EmptyExpressionStatement ()
+               {
+                       type = TypeManager.object_type;
+                       eclass = ExprClass.Value;
+                       loc = Location.Null;
+               }
+
+               public override void EmitStatement (EmitContext ec)
+               {
+                       // Do nothing
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       // Do nothing
+               }
+       }       
 
        public class UserCast : Expression {
                MethodBase method;
@@ -8263,18 +8193,16 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-#if GMCS_SOURCE
                public Expression RemoveNullable ()
                {
                        if (dim.EndsWith ("?")) {
                                dim = dim.Substring (0, dim.Length - 1);
-                               if (dim == "")
+                               if (dim.Length == 0)
                                        return left;
                        }
 
                        return this;
                }
-#endif
 
                protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
                {
@@ -8502,144 +8430,377 @@ namespace Mono.CSharp {
                        target.t = t.Clone (clonectx);
                }
        }
-       
-       public interface IInitializable
+
+       //
+       // An object initializer expression
+       //
+       public class ElementInitializer : Expression
        {
-               bool Initialize (EmitContext ec, Expression target);
+               Expression initializer;
+               public readonly string Name;
+
+               public ElementInitializer (string name, Expression initializer, Location loc)
+               {
+                       this.Name = name;
+                       this.initializer = initializer;
+                       this.loc = loc;
+               }
+
+               protected override void CloneTo (CloneContext clonectx, Expression t)
+               {
+                       if (initializer == null)
+                               return;
+
+                       ElementInitializer target = (ElementInitializer) t;
+                       target.initializer = initializer.Clone (clonectx);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (initializer == null)
+                               return EmptyExpressionStatement.Instance;
+                       
+                       MemberExpr element_member = MemberLookupFinal (ec, ec.CurrentInitializerVariable.Type, ec.CurrentInitializerVariable.Type,
+                               Name, MemberTypes.Field | MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance, loc) as MemberExpr;
+
+                       if (element_member == null)
+                               return null;
+
+                       element_member.InstanceExpression = ec.CurrentInitializerVariable;
+
+                       if (initializer is CollectionOrObjectInitializers) {
+                               Expression previous = ec.CurrentInitializerVariable;
+                               ec.CurrentInitializerVariable = element_member;
+                               initializer = initializer.Resolve (ec);
+                               ec.CurrentInitializerVariable = previous;
+                               return initializer;
+                       }
+
+                       Assign a = new Assign (element_member, initializer, loc);
+                       if (a.Resolve (ec) == null)
+                               return null;
+
+                       //
+                       // Ignore field initializers with default value
+                       //
+                       Constant c = a.Source as Constant;
+                       if (c != null && c.IsDefaultInitializer (a.Type) && a.Target.eclass == ExprClass.Variable)
+                               return EmptyExpressionStatement.Instance;
+
+                       return a;
+               }
+
+               protected override Expression Error_MemberLookupFailed (MemberInfo[] members)
+               {
+                       MemberInfo member = members [0];
+                       if (member.MemberType != MemberTypes.Property && member.MemberType != MemberTypes.Field)
+                               Report.Error (1913, loc, "Member `{0}' cannot be initialized. An object " +
+                                       "initializer may only be used for fields, or properties", TypeManager.GetFullNameSignature (member));
+                       else
+                               Report.Error (1914, loc, " Static field or property `{0}' cannot be assigned in an object initializer",
+                                       TypeManager.GetFullNameSignature (member));
+
+                       return null;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new NotSupportedException ("Should not be reached");
+               }
        }
        
-       public class Initializer
+       //
+       // A collection initializer expression
+       //
+       public class CollectionElementInitializer : Expression
        {
-               public readonly string Name;
-               public readonly object Value;
+               public class ElementInitializerArgument : Argument
+               {
+                       public ElementInitializerArgument (Expression e)
+                               : base (e)
+                       {
+                       }
+               }
+
+               ArrayList arguments;
 
-               public Initializer (string name, Expression value)
+               public CollectionElementInitializer (Expression argument)
                {
-                       Name = name;
-                       Value = value;
+                       arguments = new ArrayList (1);
+                       arguments.Add (argument);
+                       this.loc = argument.Location;
                }
 
-               public Initializer (string name, IInitializable value)
+               public CollectionElementInitializer (ArrayList arguments, Location loc)
                {
-                       Name = name;
-                       Value = value;
+                       this.arguments = arguments;
+                       this.loc = loc;
+               }
+
+               protected override void CloneTo (CloneContext clonectx, Expression t)
+               {
+                       CollectionElementInitializer target = (CollectionElementInitializer) t;
+                       ArrayList t_arguments = target.arguments = new ArrayList (arguments.Count);
+                       foreach (Expression e in arguments)
+                               t_arguments.Add (e.Clone (clonectx));
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // TODO: We should call a constructor which takes element counts argument,
+                       // for know types like List<T>, Dictionary<T, U>
+                       
+                       for (int i = 0; i < arguments.Count; ++i)
+                               arguments [i] = new ElementInitializerArgument ((Expression)arguments [i]);
+
+                       Expression add_method = new Invocation (
+                               new MemberAccess (ec.CurrentInitializerVariable, "Add", loc),
+                               arguments);
+
+                       add_method = add_method.Resolve (ec);
+
+                       return add_method;
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       throw new NotSupportedException ("Should not be reached");
                }
        }
        
-       public class ObjectInitializer : IInitializable
+       //
+       // A block of object or collection initializers
+       //
+       public class CollectionOrObjectInitializers : ExpressionStatement
        {
-               readonly ArrayList initializers;
-               public ObjectInitializer (ArrayList initializers)
+               ArrayList initializers;
+               
+               public static readonly CollectionOrObjectInitializers Empty = 
+                       new CollectionOrObjectInitializers (new ArrayList (0), Location.Null);
+
+               public CollectionOrObjectInitializers (ArrayList initializers, Location loc)
                {
                        this.initializers = initializers;
+                       this.loc = loc;
                }
                
-               public bool Initialize (EmitContext ec, Expression target)
-               {
-                       ArrayList initialized = new ArrayList (initializers.Count);
-                       for (int i = initializers.Count - 1; i >= 0; i--) {
-                               Initializer initializer = initializers[i] as Initializer;
-                               if (initialized.Contains (initializer.Name)) {
-                                       //FIXME proper error
-                                       Console.WriteLine ("Object member can only be initialized once");
-                                       return false;
-                               }
-                               
-                               MemberAccess ma = new MemberAccess (target, initializer.Name);
-                               Expression expr = initializer.Value as Expression;
-                               // If it's an expresison, append the assign.
-                               if (expr != null) {
-                                       Assign a = new Assign (ma, expr);
-                                       ec.CurrentBlock.InsertStatementAfterCurrent (new StatementExpression (a));
-                               }
-                               // If it's another initializer (object or collection), initialize it.
-                               else if (!((IInitializable)initializer.Value).Initialize (ec, ma))
-                                                       return false;
-                               
-                               initialized.Add (initializer.Name);
+               public bool IsEmpty {
+                       get {
+                               return initializers.Count == 0;
                        }
-                       return true;
                }
-       }
-       
-       public class CollectionInitializer : IInitializable
-       {
-               readonly ArrayList items;
-               public CollectionInitializer (ArrayList items)
+
+               protected override void CloneTo (CloneContext clonectx, Expression target)
                {
-                       this.items = items;
+                       CollectionOrObjectInitializers t = (CollectionOrObjectInitializers) target;
+
+                       t.initializers = new ArrayList (initializers.Count);
+                       foreach (Expression e in initializers)
+                               t.initializers.Add (e.Clone (clonectx));
                }
                
-               bool CheckCollection (EmitContext ec, Expression e)
+               public override Expression DoResolve (EmitContext ec)
                {
-                       if (e == null || e.Type == null)
-                               return false;
-                       bool is_ienumerable = false;
-                       foreach (Type t in TypeManager.GetInterfaces (e.Type))
-                               if (t == typeof (IEnumerable)) {
-                                       is_ienumerable = true;
-                                       break;
+                       bool is_elements_initialization = false;
+                       ArrayList element_names = null;
+                       for (int i = 0; i < initializers.Count; ++i) {
+                               Expression initializer = (Expression) initializers [i];
+                               ElementInitializer element_initializer = initializer as ElementInitializer;
+
+                               if (i == 0) {
+                                       if (element_initializer != null) {
+                                               is_elements_initialization = true;
+                                               element_names = new ArrayList (initializers.Count);
+                                               element_names.Add (element_initializer.Name);
+                                       } else {
+                                               if (!TypeManager.ImplementsInterface (ec.CurrentInitializerVariable.Type,
+                                                       TypeManager.ienumerable_type)) {
+                                                       Report.Error (1922, loc, "A field or property `{0}' cannot be initialized with a collection " +
+                                                               "object initializer because type `{1}' does not implement `{2}' interface",
+                                                               ec.CurrentInitializerVariable.GetSignatureForError (),
+                                                               TypeManager.CSharpName (ec.CurrentInitializerVariable.Type),
+                                                               TypeManager.CSharpName (TypeManager.ienumerable_type));
+                                                       return null;
+                                               }
+                                       }
+                               } else {
+                                       if (is_elements_initialization == (element_initializer == null)) {
+                                               Report.Error (747, initializer.Location, "Inconsistent `{0}' member declaration",
+                                                       is_elements_initialization ? "object initializer" : "collection initializer");
+                                               continue;
+                                       }
+                                       
+                                       if (is_elements_initialization) {
+                                               if (element_names.Contains (element_initializer.Name)) {
+                                                       Report.Error (1912, element_initializer.Location,
+                                                               "An object initializer includes more than one member `{0}' initialization",
+                                                               element_initializer.Name);
+                                               } else {
+                                                       element_names.Add (element_initializer.Name);
+                                               }
+                                       }
                                }
-                       
-                       if (!is_ienumerable)
-                               return false;
-                       
-                       MethodGroupExpr mg = Expression.MemberLookup (
-                               ec.ContainerType, e.Type, "Add", MemberTypes.Method,
-                               Expression.AllBindingFlags, Location.Null) as MethodGroupExpr;
 
-                       if (mg == null)
-                                       return false;
-                       
-                       foreach (MethodInfo mi in mg.Methods) {
-                               if (TypeManager.GetParameterData (mi).Count != 1)
-                                       continue;
-                               if ((mi.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
-                                       continue;
-                               return true;
+                               Expression e = initializer.Resolve (ec);
+                               if (e == EmptyExpressionStatement.Instance)
+                                       initializers.RemoveAt (i--);
+                               else
+                                       initializers [i] = e;                           
                        }
-                       return false;
+
+                       type = typeof (CollectionOrObjectInitializers);
+                       eclass = ExprClass.Variable;
+                       return this;
                }
-               
-               public bool Initialize (EmitContext ec, Expression target)
+
+               public override void Emit (EmitContext ec)
                {
-                       if (!CheckCollection (ec, target.Resolve (ec))) {
-                               // FIXME throw proper error
-                               Console.WriteLine ("Error: This is not a collection");
-                               return false;
-                       }
-                       
-                       for (int i = items.Count - 1; i >= 0; i--) {
-                               MemberAccess ma = new MemberAccess (target, "Add");
-                               ArrayList array = new ArrayList ();
-                               array.Add (new Argument ((Expression)items[i]));
-                               Invocation invoke = new Invocation (ma, array);
-                               ec.CurrentBlock.InsertStatementAfterCurrent (new StatementExpression (invoke));
-                       }
-                       return true;
+                       EmitStatement (ec);
+               }
+
+               public override void EmitStatement (EmitContext ec)
+               {
+                       foreach (ExpressionStatement e in initializers)
+                               e.EmitStatement (ec);
                }
        }
        
-       public class NewInitialize : New, IInitializable
+       //
+       // New expression with element/object initializers
+       //
+       public class NewInitialize : New
        {
-               IInitializable initializer;
-
-               public bool Initialize (EmitContext ec, Expression target)
+               //
+               // This class serves as a proxy for variable initializer target instances.
+               // A real variable is assigned later when we resolve left side of an
+               // assignment
+               //
+               sealed class InitializerTargetExpression : Expression, IMemoryLocation
                {
-                       return initializer.Initialize (ec, target);
+                       NewInitialize new_instance;
+
+                       public InitializerTargetExpression (NewInitialize newInstance)
+                       {
+                               this.type = newInstance.type;
+                               this.loc = newInstance.loc;
+                               this.eclass = newInstance.eclass;
+                               this.new_instance = newInstance;
+                       }
+
+                       public override Expression DoResolve (EmitContext ec)
+                       {
+                               return this;
+                       }
+
+                       public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+                       {
+                               return this;
+                       }
+
+                       public override void Emit (EmitContext ec)
+                       {
+                               new_instance.value_target.Emit (ec);
+                       }
+
+                       #region IMemoryLocation Members
+
+                       public void AddressOf (EmitContext ec, AddressOp mode)
+                       {
+                               ((IMemoryLocation)new_instance.value_target).AddressOf (ec, mode);
+                       }
+
+                       #endregion
                }
 
-               public NewInitialize (Expression requested_type, ArrayList arguments, IInitializable initializer, Location l)
+               CollectionOrObjectInitializers initializers;
+
+               public NewInitialize (Expression requested_type, ArrayList arguments, CollectionOrObjectInitializers initializers, Location l)
                        : base (requested_type, arguments, l)
                {
-                       this.initializer = initializer;
+                       this.initializers = initializers;
+               }
+
+               protected override void CloneTo (CloneContext clonectx, Expression t)
+               {
+                       base.CloneTo (clonectx, t);
+
+                       NewInitialize target = (NewInitialize) t;
+                       target.initializers = (CollectionOrObjectInitializers) initializers.Clone (clonectx);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       Expression e = base.DoResolve (ec);
+                       if (type == null)
+                               return null;
+
+                       // Empty initializer can be optimized to simple new
+                       if (initializers.IsEmpty)
+                               return e;
+
+                       Expression previous = ec.CurrentInitializerVariable;
+                       ec.CurrentInitializerVariable = new InitializerTargetExpression (this);
+                       initializers.Resolve (ec);
+                       ec.CurrentInitializerVariable = previous;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       base.Emit (ec);
+
+                       //
+                       // If target is a value, let's use it
+                       //
+                       VariableReference variable = value_target as VariableReference;
+                       if (variable != null) {
+                               if (variable.IsRef)
+                                       StoreFromPtr (ec.ig, type);
+                               else
+                                       variable.Variable.EmitAssign (ec);
+                       } else {
+                               if (value_target == null || value_target_set)
+                                       value_target = new LocalTemporary (type);
+
+                               ((LocalTemporary) value_target).Store (ec);
+                       }
+
+                       initializers.Emit (ec);
+
+                       if (variable == null)
+                               value_target.Emit (ec);
+               }
+
+               public override void EmitStatement (EmitContext ec)
+               {
+                       if (initializers.IsEmpty) {
+                               base.EmitStatement (ec);
+                               return;
+                       }
+
+                       base.Emit (ec);
+
+                       if (value_target == null) {
+                               LocalTemporary variable = new LocalTemporary (type);
+                               variable.Store (ec);
+                               value_target = variable;
+                       }
+
+                       initializers.EmitStatement (ec);
+               }
+
+               public override bool HasInitializer {
+                       get {
+                               return !initializers.IsEmpty;
+                       }
                }
        }
 
        public class AnonymousTypeDeclaration : Expression
        {
-               readonly ArrayList parameters;
+               ArrayList parameters;
                readonly TypeContainer parent;
+               static readonly ArrayList EmptyParameters = new ArrayList (0);
 
                public AnonymousTypeDeclaration (ArrayList parameters, TypeContainer parent, Location loc)
                {
@@ -8648,9 +8809,24 @@ namespace Mono.CSharp {
                        this.loc = loc;
                }
 
-               AnonymousTypeClass CreateAnonymousType ()
+               protected override void CloneTo (CloneContext clonectx, Expression target)
+               {
+                       if (parameters == null)
+                               return;
+
+                       AnonymousTypeDeclaration t = (AnonymousTypeDeclaration) target;
+                       t.parameters = new ArrayList (parameters.Count);
+                       foreach (AnonymousTypeParameter atp in parameters)
+                               t.parameters.Add (atp.Clone (clonectx));
+               }
+
+               AnonymousTypeClass CreateAnonymousType (ArrayList parameters)
                {
-                       AnonymousTypeClass type = AnonymousTypeClass.Create (parent, parameters, loc);
+                       AnonymousTypeClass type = RootContext.ToplevelTypes.GetAnonymousType (parameters);
+                       if (type != null)
+                               return type;
+
+                       type = AnonymousTypeClass.Create (parent, parameters, loc);
                        if (type == null)
                                return null;
 
@@ -8665,11 +8841,19 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
+                       AnonymousTypeClass anonymous_type;
+
+                       if (parameters == null) {
+                               anonymous_type = CreateAnonymousType (EmptyParameters);
+                               return new New (new TypeExpression (anonymous_type.TypeBuilder, loc),
+                                       null, loc).Resolve (ec);
+                       }
+
                        bool error = false;
                        ArrayList arguments = new ArrayList (parameters.Count);
                        TypeExpression [] t_args = new TypeExpression [parameters.Count];
                        for (int i = 0; i < parameters.Count; ++i) {
-                               Expression e = ((AnonymousTypeParameter)parameters [i]).Resolve (ec);
+                               Expression e = ((AnonymousTypeParameter) parameters [i]).Resolve (ec);
                                if (e == null) {
                                        error = true;
                                        continue;
@@ -8682,17 +8866,14 @@ namespace Mono.CSharp {
                        if (error)
                                return null;
 
-                       AnonymousTypeClass anonymous_type = RootContext.ToplevelTypes.GetAnonymousType (parameters);
-                       if (anonymous_type == null) {
-                               anonymous_type = CreateAnonymousType ();
-                               if (anonymous_type == null)
-                                       return null;
-                       }
+                       anonymous_type = CreateAnonymousType (parameters);
+                       if (anonymous_type == null)
+                               return null;
 
                        ConstructedType te = new ConstructedType (anonymous_type.TypeBuilder,
                                new TypeArguments (loc, t_args), loc);
 
-                       return new New (te, arguments, loc).Resolve (ec); 
+                       return new New (te, arguments, loc).Resolve (ec);
                }
 
                public override void Emit (EmitContext ec)
@@ -8704,7 +8885,7 @@ namespace Mono.CSharp {
        public class AnonymousTypeParameter : Expression
        {
                public readonly string Name;
-               readonly Expression initializer;
+               Expression initializer;
 
                public AnonymousTypeParameter (Expression initializer, string name, Location loc)
                {
@@ -8712,6 +8893,19 @@ namespace Mono.CSharp {
                        this.loc = loc;
                        this.initializer = initializer;
                }
+               
+               public AnonymousTypeParameter (Parameter parameter)
+               {
+                       this.Name = parameter.Name;
+                       this.loc = parameter.Location;
+                       this.initializer = new SimpleName (Name, loc);
+               }               
+
+               protected override void CloneTo (CloneContext clonectx, Expression target)
+               {
+                       AnonymousTypeParameter t = (AnonymousTypeParameter) target;
+                       t.initializer = initializer.Clone (clonectx);
+               }
 
                public override bool Equals (object o)
                {
@@ -8733,14 +8927,19 @@ namespace Mono.CSharp {
                        type = e.Type;
                        if (type == TypeManager.void_type || type == TypeManager.null_type ||
                                type == TypeManager.anonymous_method_type || type.IsPointer) {
-                               Report.Error (828, loc, "An anonymous type property `{0}' cannot be initialized with `{1}'",
-                                       Name, e.GetSignatureForError ());
+                               Error_InvalidInitializer (e);
                                return null;
                        }
 
                        return e;
                }
 
+               protected virtual void Error_InvalidInitializer (Expression initializer)
+               {
+                       Report.Error (828, loc, "An anonymous type property `{0}' cannot be initialized with `{1}'",
+                               Name, initializer.GetSignatureForError ());
+               }
+
                public override void Emit (EmitContext ec)
                {
                        throw new InternalErrorException ("Should not be reached");