2007-12-06 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / mcs / expression.cs
index 3ed899e9c2d5d4871c063a18efe3bbb2a54ad3d8..7c9d1d1d7cbd95d4db5da190c744b021e1a9d2d2 100644 (file)
@@ -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 ()
@@ -1077,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;
@@ -1102,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"; }
                }
        }
 
@@ -1335,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);
                }
        }
        
@@ -1422,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
@@ -1619,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);
@@ -1661,10 +1749,10 @@ namespace Mono.CSharp {
                                TypeManager.CSharpName(right.Type));
                }
 
-               static bool is_unsigned (Type t)
+               static bool IsUnsigned (Type t)
                {
                        if (t.IsPointer)
-                               return is_unsigned (t.GetElementType ());
+                               return IsUnsigned (t.GetElementType ());
                        
                        return (t == TypeManager.uint32_type || t == TypeManager.uint64_type ||
                                t == TypeManager.short_type || t == TypeManager.byte_type);
@@ -1889,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);
                                }
 
@@ -2585,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;
 
@@ -2596,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
@@ -2627,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);
@@ -2648,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);
                                        
@@ -2664,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;
                        }
                        
@@ -2672,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);
@@ -2730,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);
@@ -2786,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;
@@ -2803,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;
@@ -2820,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;
@@ -2832,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;
@@ -2841,7 +2931,7 @@ namespace Mono.CSharp {
                                break;
 
                        case Operator.RightShift:
-                               if (isUnsigned)
+                               if (is_unsigned)
                                        opcode = OpCodes.Shr_Un;
                                else
                                        opcode = OpCodes.Shr;
@@ -2863,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;
@@ -2879,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);
@@ -2891,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);
@@ -3355,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;
                }
 
@@ -3373,13 +3463,13 @@ namespace Mono.CSharp {
 
                public Expression TrueExpr {
                        get {
-                               return trueExpr;
+                               return true_expr;
                        }
                }
 
                public Expression FalseExpr {
                        get {
-                               return falseExpr;
+                               return false_expr;
                        }
                }
 
@@ -3392,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){
@@ -3408,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;
                                }
                        }
@@ -3461,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;
@@ -3480,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);
                }
 
@@ -3492,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);
                }
        }
 
@@ -3572,6 +3662,10 @@ namespace Mono.CSharp {
 
                        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) {
@@ -3830,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;
 
@@ -4142,12 +4240,6 @@ namespace Mono.CSharp {
                        return sb.ToString ();
                }
 
-               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 ());
-               }
-               
                public override Expression DoResolve (EmitContext ec)
                {
                        Expression expr_resolved = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
@@ -4162,7 +4254,8 @@ namespace Mono.CSharp {
                                        return (new DelegateInvocation (
                                                expr_resolved, Arguments, loc)).Resolve (ec);
                                }
-                               expr.Error_UnexpectedKind (ResolveFlags.MethodGroup, loc);
+                               
+                               expr_resolved.Error_UnexpectedKind (ResolveFlags.MethodGroup, loc);
                                return null;
                        }
 
@@ -4183,21 +4276,18 @@ namespace Mono.CSharp {
                        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;
-                                       }
                                }
                        }
 
@@ -4394,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);
                }
@@ -4754,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)
@@ -4765,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;
@@ -5121,6 +5213,12 @@ namespace Mono.CSharp {
 
                }
 
+               public virtual bool HasInitializer {
+                       get {
+                               return false;
+                       }
+               }
+
                public void AddressOf (EmitContext ec, AddressOp Mode)
                {
                        if (is_type_parameter) {
@@ -5783,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");
@@ -5850,7 +5948,7 @@ namespace Mono.CSharp {
                        : base (null, rank, initializers, loc)
                {
                        if (RootContext.Version <= LanguageVersion.ISO_2)
-                               Report.FeatureIsNotISO1 (loc, "implicitly typed arrays");
+                               Report.FeatureIsNotAvailable (loc, "implicitly typed arrays");
                                
                        if (rank.Length > 2) {
                                while (rank [++dimensions] == ',');
@@ -6008,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;
@@ -6294,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)) {
@@ -6305,7 +6402,7 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       if (valueType == TypeManager.object_type) {
+                       if (value_type == TypeManager.object_type) {
                                value = (object)typearg;
                                return true;
                        }
@@ -6428,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;
@@ -6590,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);
@@ -6604,8 +6704,10 @@ namespace Mono.CSharp {
                                if (ex_method_lookup != null) {
                                        ex_method_lookup.ExtensionExpression = expr_resolved;
 
-                                       if (args != null)
+                                       if (args != null) {
+                                               ex_method_lookup.SetTypeArguments (args);
                                                return ex_method_lookup.ResolveGeneric (ec, args);
+                                       }
 
                                        return ex_method_lookup.DoResolve (ec);
                                }
@@ -6652,21 +6754,17 @@ namespace Mono.CSharp {
                        }
 
                        MemberExpr me = (MemberExpr) member_lookup;
-                       member_lookup = me.ResolveMemberAccess (ec, expr_resolved, loc, original);
-                       if (member_lookup == null)
-                               return me;
+                       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;
@@ -6677,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)
@@ -6849,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)
@@ -6898,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)
@@ -7008,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);
                }
@@ -7023,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;
@@ -7262,22 +7368,22 @@ namespace Mono.CSharp {
                // initialized), then load the arguments the first time and store them
                // in locals.  otherwise load from local variables.
                //
-               // prepareForLoad is used in compound assignments to cache original index
+               // prepare_for_load is used in compound assignments to cache original index
                // values ( label[idx++] += s )
                //
-               LocalTemporary [] LoadArrayAndArguments (EmitContext ec, bool prepareForLoad)
+               LocalTemporary [] LoadArrayAndArguments (EmitContext ec, bool prepare_for_load)
                {
                        ea.Expr.Emit (ec);
 
                        LocalTemporary[] indexes = null;
-                       if (prepareForLoad) {
+                       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 (!prepareForLoad)
+                               if (!prepare_for_load)
                                        continue;
 
                                // Keep original array index value on the stack
@@ -7619,9 +7725,7 @@ 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);
                        }
 
                        Expression e = ResolveAccessor (ec, AccessorType.Set);
@@ -7736,7 +7840,8 @@ namespace Mono.CSharp {
                public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
                        prepared = prepare_for_load;
-                       
+                       Expression value = set_expr;
+
                        if (prepared) {
                                Invocation.EmitCall (ec, is_base_indexer, instance_expr, get,
                                        arguments, loc, true, false);
@@ -7755,12 +7860,10 @@ namespace Mono.CSharp {
                                temp = new LocalTemporary (Type);
                                source.Emit (ec);
                                temp.Store (ec);
-                               
-                               Argument a = (Argument) arguments [arguments.Count - 1];
-                               a.Expr = temp;
+                               value = temp;
                        }
                        
-                       arguments.Add (new Argument (set_expr, Argument.AType.Expression));
+                       arguments.Add (new Argument (value, Argument.AType.Expression));
                        Invocation.EmitCall (ec, is_base_indexer, instance_expr, set, arguments, loc, false, prepared);
                        
                        if (temp != null) {
@@ -7776,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)
@@ -7876,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)
@@ -7912,7 +8001,8 @@ namespace Mono.CSharp {
                {
                        BaseAccess target = (BaseAccess) t;
 
-                       target.args = args.Clone ();
+                       if (args != null)
+                               target.args = args.Clone ();
                }
        }
 
@@ -8103,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)
                {
@@ -8388,7 +8476,18 @@ namespace Mono.CSharp {
                                return initializer;
                        }
 
-                       return new Assign (element_member, initializer, loc).Resolve (ec);
+                       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)
@@ -8542,7 +8641,11 @@ namespace Mono.CSharp {
                                        }
                                }
 
-                               initializers [i] = initializer.Resolve (ec);
+                               Expression e = initializer.Resolve (ec);
+                               if (e == EmptyExpressionStatement.Instance)
+                                       initializers.RemoveAt (i--);
+                               else
+                                       initializers [i] = e;                           
                        }
 
                        type = typeof (CollectionOrObjectInitializers);
@@ -8567,8 +8670,49 @@ namespace Mono.CSharp {
        //
        public class NewInitialize : New
        {
+               //
+               // 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
+               {
+                       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
+               }
+
                CollectionOrObjectInitializers initializers;
-               TemporaryVariable type_instance;
 
                public NewInitialize (Expression requested_type, ArrayList arguments, CollectionOrObjectInitializers initializers, Location l)
                        : base (requested_type, arguments, l)
@@ -8581,7 +8725,7 @@ namespace Mono.CSharp {
                        base.CloneTo (clonectx, t);
 
                        NewInitialize target = (NewInitialize) t;
-                       target.initializers = (CollectionOrObjectInitializers)initializers.Clone (clonectx);
+                       target.initializers = (CollectionOrObjectInitializers) initializers.Clone (clonectx);
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -8594,11 +8738,8 @@ namespace Mono.CSharp {
                        if (initializers.IsEmpty)
                                return e;
 
-                       type_instance = new TemporaryVariable (type, loc);
-                       type_instance = (TemporaryVariable)type_instance.Resolve (ec);
-
                        Expression previous = ec.CurrentInitializerVariable;
-                       ec.CurrentInitializerVariable = type_instance;
+                       ec.CurrentInitializerVariable = new InitializerTargetExpression (this);
                        initializers.Resolve (ec);
                        ec.CurrentInitializerVariable = previous;
                        return this;
@@ -8608,9 +8749,50 @@ namespace Mono.CSharp {
                {
                        base.Emit (ec);
 
-                       type_instance.EmitStore (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);
-                       type_instance.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;
+                       }
                }
        }