Added few unsafe tests.
[mono.git] / mcs / mcs / expression.cs
index c0f4f01f7832f7d17d2b2d02cfa6216543b687ee..90d72ecf3ece0079f028bb466b27c4a3442ea17d 100644 (file)
@@ -5,8 +5,8 @@
 //   Miguel de Icaza (miguel@ximian.com)
 //   Marek Safar (marek.safar@seznam.cz)
 //
-// (C) 2001, 2002, 2003 Ximian, Inc.
-// (C) 2003, 2004 Novell, Inc.
+// Copyright 2001, 2002, 2003 Ximian, Inc.
+// Copyright 2003-2008 Novell, Inc.
 //
 #define USE_OLD
 
@@ -45,7 +45,7 @@ namespace Mono.CSharp {
                                return expr_tree (ec, mg);
 
                        ArrayList args = new ArrayList (arguments.Count + 1);
-                       args.Add (new Argument (new NullLiteral (loc).CreateExpressionTree (ec)));
+                       args.Add (new Argument (new NullLiteral (loc)));
                        args.Add (new Argument (mg.CreateExpressionTree (ec)));
                        foreach (Argument a in arguments) {
                                args.Add (new Argument (a.Expr.CreateExpressionTree (ec)));
@@ -135,11 +135,15 @@ namespace Mono.CSharp {
        public class Unary : Expression {
                public enum Operator : byte {
                        UnaryPlus, UnaryNegation, LogicalNot, OnesComplement,
-                       Indirection, AddressOf,  TOP
+                       AddressOf,  TOP
                }
 
+               public static readonly string [] oper_names;
+               static Type [] [] predefined_operators;
+
                public readonly Operator Oper;
                public Expression Expr;
+               Expression enum_conversion;
 
                public Unary (Operator op, Expression expr, Location loc)
                {
@@ -148,31 +152,6 @@ namespace Mono.CSharp {
                        this.loc = loc;
                }
 
-               /// <summary>
-               ///   Returns a stringified representation of the Operator
-               /// </summary>
-               static public string OperName (Operator oper)
-               {
-                       switch (oper){
-                       case Operator.UnaryPlus:
-                               return "+";
-                       case Operator.UnaryNegation:
-                               return "-";
-                       case Operator.LogicalNot:
-                               return "!";
-                       case Operator.OnesComplement:
-                               return "~";
-                       case Operator.AddressOf:
-                               return "&";
-                       case Operator.Indirection:
-                               return "*";
-                       }
-
-                       return oper.ToString ();
-               }
-
-               public static readonly string [] oper_names;
-
                static Unary ()
                {
                        oper_names = new string [(int)Operator.TOP];
@@ -181,32 +160,20 @@ namespace Mono.CSharp {
                        oper_names [(int) Operator.UnaryNegation] = "op_UnaryNegation";
                        oper_names [(int) Operator.LogicalNot] = "op_LogicalNot";
                        oper_names [(int) Operator.OnesComplement] = "op_OnesComplement";
-                       oper_names [(int) Operator.Indirection] = "op_Indirection";
                        oper_names [(int) Operator.AddressOf] = "op_AddressOf";
                }
 
-               public static void Error_OperatorCannotBeApplied (Location loc, string oper, Type t)
-               {
-                       Error_OperatorCannotBeApplied (loc, oper, TypeManager.CSharpName (t));
-               }
-
-               public static void Error_OperatorCannotBeApplied (Location loc, string oper, string type)
-               {
-                       Report.Error (23, loc, "The `{0}' operator cannot be applied to operand of type `{1}'",
-                               oper, type);
-               }
-
-               void Error23 (Type t)
-               {
-                       Error_OperatorCannotBeApplied (loc, OperName (Oper), t);
-               }
-
                // <summary>
                //   This routine will attempt to simplify the unary expression when the
                //   argument is a constant.
                // </summary>
                Constant TryReduceConstant (EmitContext ec, Constant e)
                {
+                       if (e is SideEffectConstant) {
+                               Constant r = TryReduceConstant (ec, ((SideEffectConstant) e).value);
+                               return r == null ? null : new SideEffectConstant (r, e, r.Location);
+                       }
+
                        Type expr_type = e.Type;
                        
                        switch (Oper){
@@ -316,8 +283,8 @@ namespace Mono.CSharp {
                                        if (expr_type != TypeManager.bool_type)
                                                return null;
                                        
-                                       BoolConstant b = (BoolConstant) e;
-                                       return new BoolConstant (!(b.Value), b.Location);
+                                       bool b = (bool)e.GetValue ();
+                                       return new BoolConstant (!b, e.Location);
                                
                                case Operator.OnesComplement:
                                        // Unary numeric promotions
@@ -349,234 +316,53 @@ namespace Mono.CSharp {
                                                return e;
                                        }
                                        return null;
-
-                               case Operator.AddressOf:
-                                       return e;
-
-                               case Operator.Indirection:
-                                       return e;
                        }
                        throw new Exception ("Can not constant fold: " + Oper.ToString());
                }
 
-               Expression ResolveOperator (EmitContext ec)
+               protected Expression ResolveOperator (EmitContext ec, Expression expr)
                {
-                       //
-                       // Step 1: Default operations on CLI native types.
-                       //
+                       eclass = ExprClass.Value;
 
-                       // Attempt to use a constant folding operation.
-                       Constant cexpr = Expr as Constant;
-                       if (cexpr != null) {
-                               cexpr = TryReduceConstant (ec, cexpr);
-                               if (cexpr != null) {
-                                       return cexpr;
-                               }
-                       }
+                       if (predefined_operators == null)
+                               CreatePredefinedOperatorsTable ();
+
+                       Type expr_type = expr.Type;
+                       Expression best_expr;
 
                        //
-                       // Step 2: Perform Operator Overload location
+                       // Primitive types first
                        //
-                       Type expr_type = Expr.Type;
-                       string op_name = oper_names [(int) Oper];
-
-                       MethodGroupExpr user_op = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
-                       if (user_op != null) {
-                               ArrayList args = new ArrayList (1);
-                               args.Add (new Argument (Expr));
-                               user_op = user_op.OverloadResolve (ec, ref args, false, loc);
-
-                               if (user_op == null) {
-                                       Error23 (expr_type);
-                                       return null;
-                               }
-
-                               return new UserOperatorCall (user_op, args, CreateExpressionTree, loc);
-                       }
-
-                       switch (Oper){
-                       case Operator.LogicalNot:
-                               if (expr_type != TypeManager.bool_type) {
-                                       Expr = ResolveBoolean (ec, Expr, loc);
-                                       if (Expr == null){
-                                               Error23 (expr_type);
-                                               return null;
-                                       }
-                               }
-                               
-                               type = TypeManager.bool_type;
-                               return this;
-
-                       case Operator.OnesComplement:
-                               // Unary numeric promotions
-                               if (expr_type == TypeManager.byte_type || expr_type == TypeManager.sbyte_type ||
-                                       expr_type == TypeManager.short_type || expr_type == TypeManager.ushort_type ||
-                                       expr_type == TypeManager.char_type) 
-                               {
-                                       type = TypeManager.int32_type;
-                                       return EmptyCast.Create (this, type);
-                               }
-
-                               // Predefined operators
-                               if (expr_type == TypeManager.int32_type || expr_type == TypeManager.uint32_type ||
-                                       expr_type == TypeManager.int64_type || expr_type == TypeManager.uint64_type ||
-                                       TypeManager.IsEnumType (expr_type))
-                               {
-                                       type = expr_type;
-                                       return this;
-                               }
-
-                               type = TypeManager.int32_type;
-                               Expr = Convert.ImplicitUserConversion(ec, Expr, type, loc);
-                               if (Expr != null)
-                                       return this;
-
-                               Error23 (expr_type);
-                               return null;
-
-                       case Operator.AddressOf:
-                               if (!ec.InUnsafe) {
-                                       UnsafeError (loc); 
-                                       return null;
-                               }
-                               
-                               if (!TypeManager.VerifyUnManaged (Expr.Type, loc)){
-                                       return null;
-                               }
-
-                               IVariable variable = Expr as IVariable;
-                               bool is_fixed = variable != null && variable.VerifyFixed ();
-
-                               if (!ec.InFixedInitializer && !is_fixed) {
-                                       Error (212, "You can only take the address of unfixed expression inside " +
-                                              "of a fixed statement initializer");
-                                       return null;
-                               }
-
-                               if (ec.InFixedInitializer && is_fixed) {
-                                       Error (213, "You cannot use the fixed statement to take the address of an already fixed expression");
-                                       return null;
-                               }
-
-                               LocalVariableReference lr = Expr as LocalVariableReference;
-                               if (lr != null){
-                                       if (lr.local_info.IsCaptured){
-                                               AnonymousMethod.Error_AddressOfCapturedVar (lr.Name, loc);
-                                               return null;
-                                       }
-                                       lr.local_info.AddressTaken = true;
-                                       lr.local_info.Used = true;
-                               }
-
-                               ParameterReference pr = Expr as ParameterReference;
-                               if ((pr != null) && pr.Parameter.IsCaptured) {
-                                       AnonymousMethod.Error_AddressOfCapturedVar (pr.Name, loc);
+                       if (TypeManager.IsPrimitiveType (expr_type)) {
+                               best_expr = ResolvePrimitivePredefinedType (expr);
+                               if (best_expr == null)
                                        return null;
-                               }
-
-                               // According to the specs, a variable is considered definitely assigned if you take
-                               // its address.
-                               if ((variable != null) && (variable.VariableInfo != null)){
-                                       variable.VariableInfo.SetAssigned (ec);
-                               }
 
-                               type = TypeManager.GetPointerType (Expr.Type);
+                               type = best_expr.Type;
+                               Expr = best_expr;
                                return this;
+                       }
 
-                       case Operator.Indirection:
-                               if (!ec.InUnsafe){
-                                       UnsafeError (loc);
-                                       return null;
-                               }
-                               
-                               if (!expr_type.IsPointer){
-                                       Error (193, "The * or -> operator must be applied to a pointer");
-                                       return null;
-                               }
-                               
-                               //
-                               // We create an Indirection expression, because
-                               // it can implement the IMemoryLocation.
-                               // 
-                               return new Indirection (Expr, loc);
-                       
-                       case Operator.UnaryPlus:
-                               // Unary numeric promotions
-                               if (expr_type == TypeManager.byte_type || expr_type == TypeManager.sbyte_type ||
-                                       expr_type == TypeManager.short_type || expr_type == TypeManager.ushort_type ||
-                                       expr_type == TypeManager.char_type) 
-                               {
-                                       return EmptyCast.Create (Expr, TypeManager.int32_type);
-                               }
-
-                               // Predefined operators
-                               if (expr_type == TypeManager.int32_type || expr_type == TypeManager.uint32_type ||
-                                       expr_type == TypeManager.int64_type || expr_type == TypeManager.uint64_type ||
-                                       expr_type == TypeManager.float_type || expr_type == TypeManager.double_type ||
-                                       expr_type == TypeManager.decimal_type)
-                               {
-                                       return Expr;
-                               }
-
-                               Expr = Convert.ImplicitUserConversion(ec, Expr, TypeManager.int32_type, loc);
-                               if (Expr != null) {
-                                        // Because we can completely ignore unary +
-                                       return Expr;
-                               }
-
-                               Error23 (expr_type);
-                               return null;
-
-                       case Operator.UnaryNegation:
-                               //
-                               // transform - - expr into expr
-                               //
-                               Unary u = Expr as Unary;
-                               if (u != null && u.Oper == Operator.UnaryNegation) {
-                                       return u.Expr;
-                               }
-
-                               // Unary numeric promotions
-                               if (expr_type == TypeManager.byte_type || expr_type == TypeManager.sbyte_type ||
-                                       expr_type == TypeManager.short_type || expr_type == TypeManager.ushort_type ||
-                                       expr_type == TypeManager.char_type) 
-                               {
-                                       type = TypeManager.int32_type;
-                                       return EmptyCast.Create (this, type);
-                               }
-
-                               //
-                               // Predefined operators
-                               //
-                               if (expr_type == TypeManager.uint32_type) {
-                                       type = TypeManager.int64_type;
-                                       Expr = Convert.ImplicitNumericConversion (Expr, type);
-                                       return this;
-                               }
-
-                               if (expr_type == TypeManager.int32_type || expr_type == TypeManager.int64_type || 
-                                       expr_type == TypeManager.float_type || expr_type == TypeManager.double_type ||
-                                       expr_type == TypeManager.decimal_type)
-                               {
-                                       type = expr_type;
-                                       return this;
-                               }
-
-                               //
-                               // User conversion
+                       //
+                       // E operator ~(E x);
+                       //
+                       if (Oper == Operator.OnesComplement && TypeManager.IsEnumType (expr_type))
+                               return ResolveEnumOperator (ec, expr);
 
-                               type = TypeManager.int32_type;
-                               Expr = Convert.ImplicitUserConversion(ec, Expr, type, loc);
-                               if (Expr != null)
-                                       return this;
+                       return ResolveUserType (ec, expr);
+               }
 
-                               Error23 (expr_type);
+               protected virtual Expression ResolveEnumOperator (EmitContext ec, Expression expr)
+               {
+                       Type underlying_type = TypeManager.GetEnumUnderlyingType (expr.Type);
+                       Expression best_expr = ResolvePrimitivePredefinedType (EmptyCast.Create (expr, underlying_type));
+                       if (best_expr == null)
                                return null;
-                       }
 
-                       Error (187, "No such operator '" + OperName (Oper) + "' defined for type '" +
-                              TypeManager.CSharpName (expr_type) + "'");
-                       return null;
+                       Expr = best_expr;
+                       enum_conversion = Convert.ExplicitNumericConversion (new EmptyExpression (best_expr.Type), underlying_type);
+                       type = expr.Type;
+                       return EmptyCast.Create (this, type);
                }
 
                public override Expression CreateExpressionTree (EmitContext ec)
@@ -586,14 +372,24 @@ namespace Mono.CSharp {
 
                Expression CreateExpressionTree (EmitContext ec, MethodGroupExpr user_op)
                {
-                       string method_name; 
+                       string method_name;
                        switch (Oper) {
+                       case Operator.AddressOf:
+                               Error_PointerInsideExpressionTree ();
+                               return null;
                        case Operator.UnaryNegation:
-                               method_name = "Negate";
+                               if (ec.CheckState && user_op == null && !IsFloat (type))
+                                       method_name = "NegateChecked";
+                               else
+                                       method_name = "Negate";
                                break;
+                       case Operator.OnesComplement:
                        case Operator.LogicalNot:
                                method_name = "Not";
                                break;
+                       case Operator.UnaryPlus:
+                               method_name = "UnaryPlus";
+                               break;
                        default:
                                throw new InternalErrorException ("Unknown unary operator " + Oper.ToString ());
                        }
@@ -605,6 +401,64 @@ namespace Mono.CSharp {
                        return CreateExpressionFactoryCall (method_name, args);
                }
 
+               static void CreatePredefinedOperatorsTable ()
+               {
+                       predefined_operators = new Type [(int) Operator.TOP] [];
+
+                       //
+                       // 7.6.1 Unary plus operator
+                       //
+                       predefined_operators [(int) Operator.UnaryPlus] = new Type [] {
+                               TypeManager.int32_type, TypeManager.uint32_type,
+                               TypeManager.int64_type, TypeManager.uint64_type,
+                               TypeManager.float_type, TypeManager.double_type,
+                               TypeManager.decimal_type
+                       };
+
+                       //
+                       // 7.6.2 Unary minus operator
+                       //
+                       predefined_operators [(int) Operator.UnaryNegation] = new Type [] {
+                               TypeManager.int32_type, 
+                               TypeManager.int64_type,
+                               TypeManager.float_type, TypeManager.double_type,
+                               TypeManager.decimal_type
+                       };
+
+                       //
+                       // 7.6.3 Logical negation operator
+                       //
+                       predefined_operators [(int) Operator.LogicalNot] = new Type [] {
+                               TypeManager.bool_type
+                       };
+
+                       //
+                       // 7.6.4 Bitwise complement operator
+                       //
+                       predefined_operators [(int) Operator.OnesComplement] = new Type [] {
+                               TypeManager.int32_type, TypeManager.uint32_type,
+                               TypeManager.int64_type, TypeManager.uint64_type
+                       };
+               }
+
+               //
+               // Unary numeric promotions
+               //
+               static Expression DoNumericPromotion (Operator op, Expression expr)
+               {
+                       Type expr_type = expr.Type;
+                       if ((op == Operator.UnaryPlus || op == Operator.UnaryNegation || op == Operator.OnesComplement) &&
+                               expr_type == TypeManager.byte_type || expr_type == TypeManager.sbyte_type ||
+                               expr_type == TypeManager.short_type || expr_type == TypeManager.ushort_type ||
+                               expr_type == TypeManager.char_type)
+                               return Convert.ImplicitNumericConversion (expr, TypeManager.int32_type);
+
+                       if (op == Operator.UnaryNegation && expr_type == TypeManager.uint32_type)
+                               return Convert.ImplicitNumericConversion (expr, TypeManager.int64_type);
+
+                       return expr;
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        if (Oper == Operator.AddressOf) {
@@ -614,40 +468,61 @@ namespace Mono.CSharp {
                                        Error (211, "Cannot take the address of the given expression");
                                        return null;
                                }
+
+                               return ResolveAddressOf (ec);
                        }
-                       else
-                               Expr = Expr.Resolve (ec);
 
+                       Expr = Expr.Resolve (ec);
                        if (Expr == null)
                                return null;
 
-#if GMCS_SOURCE
                        if (TypeManager.IsNullableValueType (Expr.Type))
                                return new Nullable.LiftedUnaryOperator (Oper, Expr, loc).Resolve (ec);
-#endif
 
-                       eclass = ExprClass.Value;
-                       return ResolveOperator (ec);
+                       //
+                       // Attempt to use a constant folding operation.
+                       //
+                       Constant cexpr = Expr as Constant;
+                       if (cexpr != null) {
+                               cexpr = TryReduceConstant (ec, cexpr);
+                               if (cexpr != null)
+                                       return cexpr;
+                       }
+
+                       Expression expr = ResolveOperator (ec, Expr);
+                       if (expr == null)
+                               Error_OperatorCannotBeApplied (loc, OperName (Oper), Expr.Type);
+                       
+                       //
+                       // Reduce unary operator on predefined types
+                       //
+                       if (expr == this && Oper == Operator.UnaryPlus)
+                               return Expr;
+
+                       return expr;
                }
 
                public override Expression DoResolveLValue (EmitContext ec, Expression right)
                {
-                       if (Oper == Operator.Indirection)
-                               return DoResolve (ec);
-
                        return null;
                }
 
                public override void Emit (EmitContext ec)
+               {
+                       EmitOperator (ec, type);
+               }
+
+               protected void EmitOperator (EmitContext ec, Type type)
                {
                        ILGenerator ig = ec.ig;
 
                        switch (Oper) {
                        case Operator.UnaryPlus:
-                               throw new Exception ("This should be caught by Resolve");
+                               Expr.Emit (ec);
+                               break;
                                
                        case Operator.UnaryNegation:
-                               if (ec.CheckState && type != TypeManager.float_type && type != TypeManager.double_type) {
+                               if (ec.CheckState && !IsFloat (type)) {
                                        ig.Emit (OpCodes.Ldc_I4_0);
                                        if (type == TypeManager.int64_type)
                                                ig.Emit (OpCodes.Conv_U8);
@@ -679,6 +554,12 @@ namespace Mono.CSharp {
                                throw new Exception ("This should not happen: Operator = "
                                                     + Oper.ToString ());
                        }
+
+                       //
+                       // Same trick as in Binary expression
+                       //
+                       if (enum_conversion != null)
+                               enum_conversion.Emit (ec);
                }
 
                public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
@@ -689,9 +570,182 @@ namespace Mono.CSharp {
                                base.EmitBranchable (ec, target, on_true);
                }
 
-               public override string ToString ()
+               public override void EmitSideEffect (EmitContext ec)
+               {
+                       Expr.EmitSideEffect (ec);
+               }
+
+               public static void Error_OperatorCannotBeApplied (Location loc, string oper, Type t)
+               {
+                       Report.Error (23, loc, "The `{0}' operator cannot be applied to operand of type `{1}'",
+                               oper, TypeManager.CSharpName (t));
+               }
+
+               static bool IsFloat (Type t)
+               {
+                       return t == TypeManager.float_type || t == TypeManager.double_type;
+               }
+
+               //
+               // Returns a stringified representation of the Operator
+               //
+               public static string OperName (Operator oper)
+               {
+                       switch (oper) {
+                       case Operator.UnaryPlus:
+                               return "+";
+                       case Operator.UnaryNegation:
+                               return "-";
+                       case Operator.LogicalNot:
+                               return "!";
+                       case Operator.OnesComplement:
+                               return "~";
+                       case Operator.AddressOf:
+                               return "&";
+                       }
+
+                       throw new NotImplementedException (oper.ToString ());
+               }
+
+               Expression ResolveAddressOf (EmitContext ec)
+               {
+                       if (!ec.InUnsafe) {
+                               UnsafeError (loc);
+                               return null;
+                       }
+
+                       if (!TypeManager.VerifyUnManaged (Expr.Type, loc)) {
+                               return null;
+                       }
+
+                       IVariable variable = Expr as IVariable;
+                       bool is_fixed = variable != null && variable.VerifyFixed ();
+
+                       if (!ec.InFixedInitializer && !is_fixed) {
+                               Error (212, "You can only take the address of unfixed expression inside " +
+                                          "of a fixed statement initializer");
+                               return null;
+                       }
+
+                       if (ec.InFixedInitializer && is_fixed) {
+                               Error (213, "You cannot use the fixed statement to take the address of an already fixed expression");
+                               return null;
+                       }
+
+                       LocalVariableReference lr = Expr as LocalVariableReference;
+                       if (lr != null) {
+                               if (lr.local_info.IsCaptured) {
+                                       AnonymousMethod.Error_AddressOfCapturedVar (lr.Name, loc);
+                                       return null;
+                               }
+                               lr.local_info.AddressTaken = true;
+                               lr.local_info.Used = true;
+                       }
+
+                       ParameterReference pr = Expr as ParameterReference;
+                       if ((pr != null) && pr.Parameter.IsCaptured) {
+                               AnonymousMethod.Error_AddressOfCapturedVar (pr.Name, loc);
+                               return null;
+                       }
+
+                       // According to the specs, a variable is considered definitely assigned if you take
+                       // its address.
+                       if ((variable != null) && (variable.VariableInfo != null)) {
+                               variable.VariableInfo.SetAssigned (ec);
+                       }
+
+                       type = TypeManager.GetPointerType (Expr.Type);
+                       eclass = ExprClass.Value;
+                       return this;
+               }
+
+               Expression ResolvePrimitivePredefinedType (Expression expr)
+               {
+                       expr = DoNumericPromotion (Oper, expr);
+                       Type expr_type = expr.Type;
+                       Type[] predefined = predefined_operators [(int) Oper];
+                       foreach (Type t in predefined) {
+                               if (t == expr_type)
+                                       return expr;
+                       }
+                       return null;
+               }
+
+               //
+               // Perform user-operator overload resolution
+               //
+               protected virtual Expression ResolveUserOperator (EmitContext ec, Expression expr)
                {
-                       return "Unary (" + Oper + ", " + Expr + ")";
+                       string op_name = oper_names [(int) Oper];
+                       MethodGroupExpr user_op = MemberLookup (ec.ContainerType, expr.Type, op_name, MemberTypes.Method, AllBindingFlags, expr.Location) as MethodGroupExpr;
+                       if (user_op == null)
+                               return null;
+
+                       ArrayList args = new ArrayList (1);
+                       args.Add (new Argument (expr));
+                       user_op = user_op.OverloadResolve (ec, ref args, false, expr.Location);
+
+                       if (user_op == null)
+                               return null;
+
+                       Expr = ((Argument) args [0]).Expr;
+                       return new UserOperatorCall (user_op, args, CreateExpressionTree, expr.Location);
+               }
+
+               //
+               // Unary user type overload resolution
+               //
+               Expression ResolveUserType (EmitContext ec, Expression expr)
+               {
+                       Expression best_expr = ResolveUserOperator (ec, expr);
+                       if (best_expr != null)
+                               return best_expr;
+
+                       Type[] predefined = predefined_operators [(int) Oper];
+                       foreach (Type t in predefined) {
+                               Expression oper_expr = Convert.UserDefinedConversion (ec, expr, t, expr.Location, false);
+                               if (oper_expr == null)
+                                       continue;
+
+                               //
+                               // decimal type is predefined but has user-operators
+                               //
+                               if (oper_expr.Type == TypeManager.decimal_type)
+                                       oper_expr = ResolveUserType (ec, oper_expr);
+                               else
+                                       oper_expr = ResolvePrimitivePredefinedType (oper_expr);
+
+                               if (oper_expr == null)
+                                       continue;
+
+                               if (best_expr == null) {
+                                       best_expr = oper_expr;
+                                       continue;
+                               }
+
+                               int result = MethodGroupExpr.BetterTypeConversion (ec, best_expr.Type, t);
+                               if (result == 0) {
+                                       Report.Error (35, loc, "Operator `{0}' is ambiguous on an operand of type `{1}'",
+                                               OperName (Oper), TypeManager.CSharpName (expr.Type));
+                                       break;
+                               }
+
+                               if (result == 2)
+                                       best_expr = oper_expr;
+                       }
+                       
+                       if (best_expr == null)
+                               return null;
+                       
+                       //
+                       // HACK: Decimal user-operator is included in standard operators
+                       //
+                       if (best_expr.Type == TypeManager.decimal_type)
+                               return best_expr;                       
+
+                       Expr = best_expr;
+                       type = best_expr.Type;
+                       return this;                    
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -715,10 +769,14 @@ namespace Mono.CSharp {
                public Indirection (Expression expr, Location l)
                {
                        this.expr = expr;
-                       type = TypeManager.HasElementType (expr.Type) ? TypeManager.GetElementType (expr.Type) : expr.Type;
-                       eclass = ExprClass.Variable;
                        loc = l;
                }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       Error_PointerInsideExpressionTree ();
+                       return null;
+               }
                
                public override void Emit (EmitContext ec)
                {
@@ -774,9 +832,20 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       //
-                       // Born fully resolved
-                       //
+                       expr = expr.Resolve (ec);
+                       if (expr == null)
+                               return null;
+
+                       if (!ec.InUnsafe)
+                               UnsafeError (loc);
+
+                       if (!expr.Type.IsPointer) {
+                               Error (193, "The * or -> operator must be applied to a pointer");
+                               return null;
+                       }
+
+                       type = TypeManager.GetElementType (expr.Type);
+                       eclass = ExprClass.Variable;
                        return this;
                }
                
@@ -927,6 +996,11 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       return new SimpleAssign (this, this).CreateExpressionTree (ec);
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        expr = expr.Resolve (ec);
@@ -1137,6 +1211,14 @@ namespace Mono.CSharp {
                        : base (expr, probe_type, l)
                {
                }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       ArrayList args = new ArrayList (2);
+                       args.Add (new Argument (expr.CreateExpressionTree (ec)));
+                       args.Add (new Argument (new TypeOf (probe_type_expr, loc)));
+                       return CreateExpressionFactoryCall ("TypeIs", args);
+               }
                
                public override void Emit (EmitContext ec)
                {
@@ -1156,7 +1238,7 @@ namespace Mono.CSharp {
                        ig.Emit (OpCodes.Isinst, probe_type_expr.Type);
                        ig.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
                }
-
+               
                Expression CreateConstantResult (bool result)
                {
                        if (result)
@@ -1166,7 +1248,7 @@ namespace Mono.CSharp {
                                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);
+                       return ReducedExpression.Create (new BoolConstant (result, loc), this);
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -1273,14 +1355,22 @@ namespace Mono.CSharp {
        ///   Implementation of the `as' operator.
        /// </summary>
        public class As : Probe {
+               bool do_isinst;
+               Expression resolved_type;
+               
                public As (Expression expr, Expression probe_type, Location l)
                        : base (expr, probe_type, l)
                {
                }
 
-               bool do_isinst = false;
-               Expression resolved_type;
-               
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       ArrayList args = new ArrayList (2);
+                       args.Add (new Argument (expr.CreateExpressionTree (ec)));
+                       args.Add (new Argument (new TypeOf (probe_type_expr, loc)));
+                       return CreateExpressionFactoryCall ("TypeAs", args);
+               }
+
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
@@ -1781,6 +1871,7 @@ namespace Mono.CSharp {
                readonly Operator oper;
                protected Expression left, right;
                readonly bool is_compound;
+               Expression enum_conversion;
 
                // This must be kept in sync with Operator!!!
                public static readonly string [] oper_names;
@@ -1958,6 +2049,9 @@ namespace Mono.CSharp {
                        Expression expr;
                        bool primitives_only = false;
 
+                       if (standard_operators == null)
+                               CreateStandardOperatorsTable ();
+
                        //
                        // Handles predefined primitive types
                        //
@@ -2003,13 +2097,12 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (standard_operators == null)
-                               CreateStandardOperatorsTable ();
-
-                       return ResolveOperatorPredefined (ec, standard_operators, primitives_only);
+                       return ResolveOperatorPredefined (ec, standard_operators, primitives_only, null);
                }
 
-               Constant EnumLiftUp (Constant left, Constant right)
+               // at least one of 'left' or 'right' is an enumeration constant (EnumConstant or SideEffectConstant or ...)
+               // if 'left' is not an enumeration constant, create one from the type of 'right'
+               Constant EnumLiftUp (EmitContext ec, Constant left, Constant right, Location loc)
                {
                        switch (oper) {
                        case Operator.BitwiseOr:
@@ -2021,11 +2114,11 @@ namespace Mono.CSharp {
                        case Operator.LessThanOrEqual:
                        case Operator.GreaterThan:
                        case Operator.GreaterThanOrEqual:
-                               if (left is EnumConstant)
+                               if (TypeManager.IsEnumType (left.Type))
                                        return left;
                                
                                if (left.IsZeroInteger)
-                                       return new EnumConstant (left, right.Type);
+                                       return left.TryReduce (ec, right.Type, loc);
                                
                                break;
                                
@@ -2038,7 +2131,7 @@ namespace Mono.CSharp {
                        case Operator.Modulus:
                        case Operator.LeftShift:
                        case Operator.RightShift:
-                               if (right is EnumConstant || left is EnumConstant)
+                               if (TypeManager.IsEnumType (right.Type) || TypeManager.IsEnumType (left.Type))
                                        break;
                                return left;
                        }
@@ -2216,7 +2309,7 @@ namespace Mono.CSharp {
                        if (ltype != int32) {
                                Constant c = left as Constant;
                                if (c != null)
-                                       temp = c.ImplicitConversionRequired (int32, loc);
+                                       temp = c.ConvertImplicitly (int32);
                                else
                                        temp = Convert.ImplicitNumericConversion (left, int32);
 
@@ -2228,7 +2321,7 @@ namespace Mono.CSharp {
                        if (rtype != int32) {
                                Constant c = right as Constant;
                                if (c != null)
-                                       temp = c.ImplicitConversionRequired (int32, loc);
+                                       temp = c.ConvertImplicitly (int32);
                                else
                                        temp = Convert.ImplicitNumericConversion (right, int32);
 
@@ -2283,11 +2376,11 @@ namespace Mono.CSharp {
 
                        // The conversion rules are ignored in enum context but why
                        if (!ec.InEnumContext && lc != null && rc != null && (TypeManager.IsEnumType (left.Type) || TypeManager.IsEnumType (right.Type))) {
-                               left = lc = EnumLiftUp (lc, rc);
+                               left = lc = EnumLiftUp (ec, lc, rc, loc);
                                if (lc == null)
                                        return null;
 
-                               right = rc = EnumLiftUp (rc, lc);
+                               right = rc = EnumLiftUp (ec, rc, lc, loc);
                                if (rc == null)
                                        return null;
                        }
@@ -2311,11 +2404,6 @@ namespace Mono.CSharp {
                                                right = left;
                                                lc = rc;
                                        }
-                                       
-                                       // TODO: there must be better way how to check that the expression
-                                       // does not have any mutator
-                                       if (right is MemberExpr)
-                                               return lc;
 
                                        // The result is a constant with side-effect
                                        return new SideEffectConstant (lc, right, loc);
@@ -2331,7 +2419,8 @@ namespace Mono.CSharp {
                                CheckUselessComparison (rc, left.Type);
                        }
 
-                       if ((TypeManager.IsNullableType (left.Type) || TypeManager.IsNullableType (right.Type) ||
+                       if (RootContext.Version >= LanguageVersion.ISO_2 &&
+                               (TypeManager.IsNullableType (left.Type) || TypeManager.IsNullableType (right.Type) ||
                                (left is NullLiteral && right.Type.IsValueType) || (right is NullLiteral && left.Type.IsValueType)))
                                return new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
 
@@ -2401,92 +2490,114 @@ namespace Mono.CSharp {
                //
                // Enumeration operators
                //
-               Binary ResolveOperatorEnum (EmitContext ec, bool lenum, bool renum, Type ltype, Type rtype)
+               Expression ResolveOperatorEnum (EmitContext ec, bool lenum, bool renum, Type ltype, Type rtype)
                {
-                       Expression temp;
+                       //
+                       // bool operator == (E x, E y);
+                       // bool operator != (E x, E y);
+                       // bool operator < (E x, E y);
+                       // bool operator > (E x, E y);
+                       // bool operator <= (E x, E y);
+                       // bool operator >= (E x, E y);
+                       //
+                       // E operator & (E x, E y);
+                       // E operator | (E x, E y);
+                       // E operator ^ (E x, E y);
+                       //
+                       // U operator - (E e, E f)
+                       // E operator - (E e, U x)
+                       //
+                       // E operator + (U x, E e)
+                       // E operator + (E e, U x)
+                       //
+                       if (!((oper & (Operator.ComparisonMask | Operator.BitwiseMask)) != 0 ||
+                               (oper == Operator.Subtraction && lenum) || (oper == Operator.Addition && lenum != renum)))
+                               return null;
 
-                       if (lenum || renum) {
-                               //
-                               // bool operator == (E x, E y);
-                               // bool operator != (E x, E y);
-                               // bool operator < (E x, E y);
-                               // bool operator > (E x, E y);
-                               // bool operator <= (E x, E y);
-                               // bool operator >= (E x, E y);
-                               //
-                               if ((oper & Operator.ComparisonMask) != 0) {
-                                       type = TypeManager.bool_type;
-                               } else if ((oper & Operator.BitwiseMask) != 0) {
-                                       type = ltype;
-                               }
+                       Expression ltemp = left;
+                       Expression rtemp = right;
+                       Type underlying_type;
 
-                               if (type != null) {
-                                       if (!TypeManager.IsEqual (ltype, rtype)) {
-                                               if (!lenum) {
-                                                       temp = Convert.ImplicitConversion (ec, left, rtype, loc);
-                                                       if (temp == null)
-                                                               return null;
-                                                       left = temp;
-                                               } else {
-                                                       temp = Convert.ImplicitConversion (ec, right, ltype, loc);
-                                                       if (temp == null)
-                                                               return null;
-                                                       right = temp;
-                                               }
-                                       }
+                       if (TypeManager.IsEqual (ltype, rtype)) {
+                               underlying_type = TypeManager.GetEnumUnderlyingType (ltype);
 
-                                       return this;
-                               }
-                       }
+                               if (left is Constant)
+                                       left = ((Constant) left).ConvertExplicitly (false, underlying_type);
+                               else
+                                       left = EmptyCast.Create (left, underlying_type);
 
-                       Type underlying_type;
-                       if (lenum && !renum) {
-                               //
-                               // E operator + (E e, U x)
-                               // E operator - (E e, U x)
-                               //
-                               if (oper == Operator.Addition || oper == Operator.Subtraction) {
-                                       underlying_type = TypeManager.GetEnumUnderlyingType (ltype);
-                                       temp = Convert.ImplicitConversion (ec, right, underlying_type, loc);
-                                       if (temp == null)
+                               if (right is Constant)
+                                       right = ((Constant) right).ConvertExplicitly (false, underlying_type);
+                               else
+                                       right = EmptyCast.Create (right, underlying_type);
+                       } else if (lenum) {
+                               if (oper != Operator.Subtraction && oper != Operator.Addition) {
+                                       Constant c = right as Constant;
+                                       if (c == null || !c.IsDefaultValue)
                                                return null;
+                               }
 
-                                       right = temp;
-                                       type = ltype;
-                                       return this;
+                               underlying_type = TypeManager.GetEnumUnderlyingType (ltype);
+                               if (left is Constant)
+                                       left = ((Constant) left).ConvertExplicitly (false, underlying_type);
+                               else
+                                       left = EmptyCast.Create (left, underlying_type);
+                       } else if (renum) {
+                               if (oper != Operator.Addition) {
+                                       Constant c = left as Constant;
+                                       if (c == null || !c.IsDefaultValue)
+                                               return null;
                                }
 
+                               underlying_type = TypeManager.GetEnumUnderlyingType (rtype);
+                               if (right is Constant)
+                                       right = ((Constant) right).ConvertExplicitly (false, underlying_type);
+                               else
+                                       right = EmptyCast.Create (right, underlying_type);
+                       } else {
+                               return null;
+                       }
+
+                       //
+                       // C# specification uses explicit cast syntax which means binary promotion
+                       // should happen, however it seems that csc does not do that
+                       //
+                       if (!DoBinaryOperatorPromotion (ec)) {
+                               left = ltemp;
+                               right = rtemp;
                                return null;
                        }
 
-                       if (renum) {
-                               //
-                               // E operator + (U x, E e)
-                               //
-                               if (oper == Operator.Addition) {
-                                       underlying_type = TypeManager.GetEnumUnderlyingType (rtype);
-                                       temp = Convert.ImplicitConversion (ec, left, underlying_type, loc);
-                                       if (temp == null)
-                                               return null;
+                       Type res_type = null;
+                       if ((oper & Operator.BitwiseMask) != 0 || oper == Operator.Subtraction || oper == Operator.Addition) {
+                               Type promoted_type = lenum ? left.Type : right.Type;
+                               enum_conversion = Convert.ExplicitNumericConversion (
+                                       new EmptyExpression (promoted_type), underlying_type);
 
-                                       left = temp;
-                                       type = rtype;
-                                       return this;
-                               }
+                               if (oper == Operator.Subtraction && renum && lenum)
+                                       res_type = underlying_type;
+                               else if (oper == Operator.Addition && renum)
+                                       res_type = rtype;
+                               else
+                                       res_type = ltype;
                        }
+                       
+                       Expression expr = ResolveOperatorPredefined (ec, standard_operators, true, res_type);
+                       if (!is_compound || expr == null)
+                               return expr;
 
                        //
-                       // U operator - (E e, E f)
+                       // TODO: Need to corectly implemented Coumpound Assigment for all operators
+                       // Section: 7.16.2
                        //
-                       if (oper == Operator.Subtraction) {
-                               if (!TypeManager.IsEqual (ltype, rtype))
-                                       return null;
+                       if (Convert.ImplicitConversionExists (ec, left, rtype))
+                               return expr;
 
-                               type = TypeManager.GetEnumUnderlyingType (ltype);
-                               return this;
-                       }
+                       if (!Convert.ImplicitConversionExists (ec, ltemp, rtype))
+                               return null;
 
-                       return null;
+                       expr = Convert.ExplicitConversion (ec, expr, rtype, loc);
+                       return expr;
                }
 
                //
@@ -2569,6 +2680,8 @@ namespace Mono.CSharp {
                                        return null;
                        } else if (l.IsInterface) {
                                l = TypeManager.object_type;
+                       } else if (l.IsValueType) {
+                               return null;
                        }
 
                        if (rgen) {
@@ -2577,8 +2690,11 @@ namespace Mono.CSharp {
                                        return null;
                        } else if (r.IsInterface) {
                                r = TypeManager.object_type;
+                       } else if (r.IsValueType) {
+                               return null;
                        }
 
+
                        const string ref_comparison = "Possible unintended reference comparison. " +
                                "Consider casting the {0} side of the expression to `string' to compare the values";
 
@@ -2637,13 +2753,13 @@ namespace Mono.CSharp {
                        if (pointer_operators == null)
                                CreatePointerOperatorsTable ();
 
-                       return ResolveOperatorPredefined (ec, pointer_operators, false);
+                       return ResolveOperatorPredefined (ec, pointer_operators, false, null);
                }
 
                //
                // Build-in operators method overloading
                //
-               protected virtual Expression ResolveOperatorPredefined (EmitContext ec, PredefinedOperator [] operators, bool primitives_only)
+               protected virtual Expression ResolveOperatorPredefined (EmitContext ec, PredefinedOperator [] operators, bool primitives_only, Type enum_type)
                {
                        PredefinedOperator best_operator = null;
                        Type l = left.Type;
@@ -2683,7 +2799,15 @@ namespace Mono.CSharp {
                        if (best_operator == null)
                                return null;
 
-                       return best_operator.ConvertResult (ec, this);
+                       Expression expr = best_operator.ConvertResult (ec, this);
+                       if (enum_type == null)
+                               return expr;
+
+                       //
+                       // HACK: required by enum_conversion
+                       //
+                       expr.Type = enum_type;
+                       return EmptyCast.Create (expr, enum_type);
                }
 
                //
@@ -2891,20 +3015,12 @@ namespace Mono.CSharp {
                                }
                                
                                if (((Constant) right).IsZeroInteger) {
-                                       left.Emit (ec);
-                                       if (my_on_true)
-                                               ig.Emit (OpCodes.Brtrue, target);
-                                       else
-                                               ig.Emit (OpCodes.Brfalse, target);
-                                       
+                                       left.EmitBranchable (ec, target, my_on_true);
                                        return;
-                               } else if (right is BoolConstant) {
-                                       left.Emit (ec);
-                                       if (my_on_true != ((BoolConstant) right).Value)
-                                               ig.Emit (OpCodes.Brtrue, target);
-                                       else
-                                               ig.Emit (OpCodes.Brfalse, target);
-                                       
+                               }
+                               if (right.Type == TypeManager.bool_type) {
+                                       // right is a boolean, and it's not 'false' => it is 'true'
+                                       left.EmitBranchable (ec, target, !my_on_true);
                                        return;
                                }
 
@@ -3031,10 +3147,10 @@ namespace Mono.CSharp {
                
                public override void Emit (EmitContext ec)
                {
-                       EmitOperator (ec);
+                       EmitOperator (ec, left.Type);
                }
 
-               protected void EmitOperator (EmitContext ec)
+               protected virtual void EmitOperator (EmitContext ec, Type l)
                {
                        ILGenerator ig = ec.ig;
 
@@ -3073,7 +3189,6 @@ namespace Mono.CSharp {
 
                        right.Emit (ec);
 
-                       Type l = left.Type;
                        OpCode opcode;
                        
                        switch (oper){
@@ -3202,6 +3317,24 @@ namespace Mono.CSharp {
                        }
 
                        ig.Emit (opcode);
+
+                       //
+                       // Nullable enum could require underlying type cast and we cannot simply wrap binary
+                       // expression because that would wrap lifted binary operation
+                       //
+                       if (enum_conversion != null)
+                               enum_conversion.Emit (ec);
+               }
+
+               public override void EmitSideEffect (EmitContext ec)
+               {
+                       if ((oper & Operator.LogicalMask) != 0 ||
+                           (ec.CheckState && (oper == Operator.Multiply || oper == Operator.Addition || oper == Operator.Subtraction))) {
+                               base.EmitSideEffect (ec);
+                       } else {
+                               left.EmitSideEffect (ec);
+                               right.EmitSideEffect (ec);
+                       }
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -3224,7 +3357,7 @@ namespace Mono.CSharp {
                        
                        switch (oper) {
                        case Operator.Addition:
-                               if (method == null && ec.CheckState && !IsFloat (left.Type))
+                               if (method == null && ec.CheckState && !IsFloat (type))
                                        method_name = "AddChecked";
                                else
                                        method_name = "Add";
@@ -3278,7 +3411,7 @@ namespace Mono.CSharp {
                                method_name = "Modulo";
                                break;
                        case Operator.Multiply:
-                               if (method == null && ec.CheckState && !IsFloat (left.Type))
+                               if (method == null && ec.CheckState && !IsFloat (type))
                                        method_name = "MultiplyChecked";
                                else
                                        method_name = "Multiply";
@@ -3287,7 +3420,7 @@ namespace Mono.CSharp {
                                method_name = "RightShift";
                                break;
                        case Operator.Subtraction:
-                               if (method == null && ec.CheckState && !IsFloat (left.Type))
+                               if (method == null && ec.CheckState && !IsFloat (type))
                                        method_name = "SubtractChecked";
                                else
                                        method_name = "Subtract";
@@ -3569,6 +3702,12 @@ namespace Mono.CSharp {
                        is_add = is_addition;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       Error_PointerInsideExpressionTree ();
+                       return null;
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        eclass = ExprClass.Variable;
@@ -3824,6 +3963,11 @@ namespace Mono.CSharp {
                        Emit (ec, false);
                }
 
+               public override void EmitSideEffect (EmitContext ec)
+               {
+                       // do nothing
+               }
+
                //
                // This method is used by parameters that are references, that are
                // being passed as references:  we only want to pass the pointer (that
@@ -3883,8 +4027,13 @@ namespace Mono.CSharp {
                        source.Emit (ec);
 
                        // HACK: variable is already emitted when source is an initializer 
-                       if (source is NewInitialize)
+                       if (source is NewInitialize) {
+                               if (leave_copy) {
+                                       Variable.EmitInstance (ec);
+                                       Variable.Emit (ec);
+                               }
                                return;
+                       }
 
                        if (leave_copy) {
                                ig.Emit (OpCodes.Dup);
@@ -3969,6 +4118,13 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       ArrayList arg = new ArrayList (1);
+                       arg.Add (new Argument (this));
+                       return CreateExpressionFactoryCall ("Constant", arg);
+               }
+
                protected Expression DoResolveBase (EmitContext ec)
                {
                        type = local_info.VariableType;
@@ -4027,7 +4183,8 @@ namespace Mono.CSharp {
                        if (type == null) {
                                VarExpr ve = local_info.Type as VarExpr;
                                if (ve != null) {
-                                       ve.DoResolveLValue (ec, right_side);
+                                       if (!ve.InferType (ec, right_side))
+                                               return null;
                                        type = local_info.VariableType = ve.Type;
                                }
                        }
@@ -4366,6 +4523,9 @@ namespace Mono.CSharp {
 
                public bool Resolve (EmitContext ec, Location loc)
                {
+                       if (Expr == null)
+                               return false;
+
                        using (ec.With (EmitContext.Flags.DoFlowAnalysis, true)) {
                                // Verify that the argument is readable
                                if (ArgType != AType.Out)
@@ -4414,7 +4574,7 @@ namespace Mono.CSharp {
        /// </summary>
        public class Invocation : ExpressionStatement {
                protected ArrayList Arguments;
-               Expression expr;
+               protected Expression expr;
                protected MethodGroupExpr mg;
                bool arguments_resolved;
                
@@ -4431,7 +4591,8 @@ namespace Mono.CSharp {
                                this.expr = expr;
                        
                        Arguments = arguments;
-                       loc = expr.Location;
+                       if (expr != null)
+                               loc = expr.Location;
                }
 
                public Invocation (Expression expr, ArrayList arguments, bool arguments_resolved)
@@ -4453,17 +4614,19 @@ namespace Mono.CSharp {
                                return CreateExpressionFactoryCall ("Quote", args);
                        }
 
-                       args = new ArrayList (Arguments.Count + 3);
+                       args = new ArrayList (Arguments == null ? 2 : Arguments.Count + 2);
                        if (mg.IsInstance)
                                args.Add (new Argument (mg.InstanceExpression.CreateExpressionTree (ec)));
                        else
-                               args.Add (new Argument (new NullLiteral (loc).CreateExpressionTree (ec)));
+                               args.Add (new Argument (new NullLiteral (loc)));
 
                        args.Add (new Argument (mg.CreateExpressionTree (ec)));
-                       foreach (Argument a in Arguments) {
-                               Expression e = a.Expr.CreateExpressionTree (ec);
-                               if (e != null)
-                                       args.Add (new Argument (e));
+                       if (Arguments != null) {
+                               foreach (Argument a in Arguments) {
+                                       Expression e = a.Expr.CreateExpressionTree (ec);
+                                       if (e != null)
+                                               args.Add (new Argument (e));
+                               }
                        }
 
                        return CreateExpressionFactoryCall ("Call", args);
@@ -4494,7 +4657,7 @@ namespace Mono.CSharp {
                                        return null;
                                }
                                
-                               mg = ec.TypeContainer.LookupExtensionMethod (me.Type, me.Name);
+                               mg = ec.TypeContainer.LookupExtensionMethod (me.Type, me.Name, loc);
                                if (mg == null) {
                                        Report.Error (1955, loc, "The member `{0}' cannot be used as method or delegate",
                                                expr_resolved.GetSignatureForError ());
@@ -5103,6 +5266,28 @@ namespace Mono.CSharp {
                        Cast cast = new Cast (new TypeExpression (type, loc), proxy, loc);
                        return cast.Resolve (ec);
                }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       ArrayList args = Arguments == null ?
+                               new ArrayList (1) : new ArrayList (Arguments.Count + 1);
+
+                       if (method == null) {
+                               args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+                       } else {
+                               args.Add (new Argument (method.CreateExpressionTree (ec)));
+                               if (Arguments != null) {
+                                       Expression expr;
+                                       foreach (Argument a in Arguments) {
+                                               expr = a.Expr.CreateExpressionTree (ec);
+                                               if (expr != null)
+                                                       args.Add (new Argument (expr));
+                                       }
+                               }
+                       }
+
+                       return CreateExpressionFactoryCall ("New", args);
+               }
                
                public override Expression DoResolve (EmitContext ec)
                {
@@ -5435,7 +5620,7 @@ namespace Mono.CSharp {
        ///   specified but where initialization data is mandatory.
        /// </remarks>
        public class ArrayCreation : Expression {
-               Expression requested_base_type;
+               FullNamedExpression requested_base_type;
                ArrayList initializers;
 
                //
@@ -5458,7 +5643,7 @@ namespace Mono.CSharp {
                int const_initializers_count;
                bool only_constant_initializers;
                
-               public ArrayCreation (Expression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l)
+               public ArrayCreation (FullNamedExpression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l)
                {
                        this.requested_base_type = requested_base_type;
                        this.initializers = initializers;
@@ -5473,7 +5658,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public ArrayCreation (Expression requested_base_type, string rank, ArrayList initializers, Location l)
+               public ArrayCreation (FullNamedExpression requested_base_type, string rank, ArrayList initializers, Location l)
                {
                        this.requested_base_type = requested_base_type;
                        this.initializers = initializers;
@@ -5488,19 +5673,6 @@ namespace Mono.CSharp {
                        expect_initializers = true;
                }
 
-               public Expression FormArrayType (Expression base_type, int idx_count, string rank)
-               {
-                       StringBuilder sb = new StringBuilder (rank);
-                       
-                       sb.Append ("[");
-                       for (int i = 1; i < idx_count; i++)
-                               sb.Append (",");
-                       
-                       sb.Append ("]");
-
-                       return new ComposedCast (base_type, sb.ToString (), loc);
-               }
-
                void Error_IncorrectArrayInitializer ()
                {
                        Error (178, "Invalid rank specifier: expected `,' or `]'");
@@ -5594,12 +5766,23 @@ namespace Mono.CSharp {
 
                public override Expression CreateExpressionTree (EmitContext ec)
                {
+                       ArrayList args;
+
                        if (dimensions != 1) {
-                               Report.Error (838, loc, "An expression tree cannot contain a multidimensional array initializer");
-                               return null;
+                               if (initializers != null) {
+                                       Report.Error (838, loc, "An expression tree cannot contain a multidimensional array initializer");
+                                       return null;
+                               }
+
+                               args = new ArrayList (arguments.Count + 1);
+                               args.Add (new Argument (new TypeOf (new TypeExpression (array_element_type, loc), loc)));
+                               foreach (Argument a in arguments)
+                                       args.Add (new Argument (a.Expr.CreateExpressionTree (ec)));
+
+                               return CreateExpressionFactoryCall ("NewArrayBounds", args);
                        }
 
-                       ArrayList args = new ArrayList (array_data == null ? 1 : array_data.Count + 1);
+                       args = new ArrayList (array_data == null ? 1 : array_data.Count + 1);
                        args.Add (new Argument (new TypeOf (new TypeExpression (array_element_type, loc), loc)));
                        if (array_data != null) {
                                foreach (Expression e in array_data)
@@ -5632,12 +5815,22 @@ namespace Mono.CSharp {
 
                }
 
+               Expression first_emit;
+               LocalTemporary first_emit_temp;
+
                protected virtual Expression ResolveArrayElement (EmitContext ec, Expression element)
                {
                        element = element.Resolve (ec);
                        if (element == null)
                                return null;
 
+                       if (element is CompoundAssign.Helper) {
+                               if (first_emit != null)
+                                       throw new InternalErrorException ("Can only handle one mutator at a time");
+                               first_emit = element;
+                               element = first_emit_temp = new LocalTemporary (element.Type);
+                       }
+
                        return Convert.ImplicitConversionRequired (
                                ec, element, array_element_type, loc);
                }
@@ -6034,6 +6227,11 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
 
+                       if (first_emit != null) {
+                               first_emit.Emit (ec);
+                               first_emit_temp.Store (ec);
+                       }
+
                        foreach (Argument a in arguments)
                                a.Emit (ec);
 
@@ -6057,7 +6255,10 @@ namespace Mono.CSharp {
                                        EmitDynamicInitializers (ec, false);
                        } else {
                                EmitDynamicInitializers (ec, true);
-                       }                               
+                       }
+
+                       if (first_emit_temp != null)
+                               first_emit_temp.Release (ec);
                }
 
                public override bool GetAttributableValue (Type value_type, out object value)
@@ -6102,7 +6303,7 @@ namespace Mono.CSharp {
                        ArrayCreation target = (ArrayCreation) t;
 
                        if (requested_base_type != null)
-                               target.requested_base_type = requested_base_type.Clone (clonectx);
+                               target.requested_base_type = (FullNamedExpression)requested_base_type.Clone (clonectx);
 
                        if (arguments != null){
                                target.arguments = new ArrayList (arguments.Count);
@@ -6434,6 +6635,11 @@ namespace Mono.CSharp {
                        this.loc = loc;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        eclass = ExprClass.Variable;
@@ -6522,29 +6728,6 @@ namespace Mono.CSharp {
                }
        }
 
-       //
-       // This produces the value that renders an instance, used by the iterators code
-       //
-       public class ProxyInstance : Expression, IMemoryLocation  {
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       eclass = ExprClass.Variable;
-                       type = ec.ContainerType;
-                       return this;
-               }
-               
-               public override void Emit (EmitContext ec)
-               {
-                       ec.ig.Emit (OpCodes.Ldarg_0);
-
-               }
-               
-               public void AddressOf (EmitContext ec, AddressOp mode)
-               {
-                       ec.ig.Emit (OpCodes.Ldarg_0);
-               }
-       }
-
        /// <summary>
        ///   Implements the typeof operator
        /// </summary>
@@ -6558,8 +6741,19 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       ArrayList args = new ArrayList (2);
+                       args.Add (new Argument (this));
+                       args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+                       return CreateExpressionFactoryCall ("Constant", args);
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
+                       if (eclass != ExprClass.Invalid)
+                               return this;
+
                        TypeExpr texpr = QueriedType.ResolveAsTypeTerminal (ec, false);
                        if (texpr == null)
                                return null;
@@ -6630,59 +6824,163 @@ namespace Mono.CSharp {
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        TypeOf target = (TypeOf) t;
+                       if (QueriedType != null)
+                               target.QueriedType = QueriedType.Clone (clonectx);
+               }
+       }
+
+       /// <summary>
+       ///   Implements the `typeof (void)' operator
+       /// </summary>
+       public class TypeOfVoid : TypeOf {
+               public TypeOfVoid (Location l) : base (null, l)
+               {
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = TypeManager.type_type;
+                       typearg = TypeManager.void_type;
+
+                       return DoResolveBase ();
+               }
+       }
+
+       class TypeOfMethodInfo : TypeOfMethod
+       {
+               public TypeOfMethodInfo (MethodBase method, Location loc)
+                       : base (method, loc)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = typeof (MethodInfo);
+                       return base.DoResolve (ec);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldtoken, (MethodInfo) method);
+                       base.Emit (ec);
+                       ec.ig.Emit (OpCodes.Castclass, type);
+               }
+       }
+
+       class TypeOfConstructorInfo : TypeOfMethod
+       {
+               public TypeOfConstructorInfo (MethodBase method, Location loc)
+                       : base (method, loc)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = typeof (ConstructorInfo);
+                       return base.DoResolve (ec);
+               }
 
-                       target.QueriedType = QueriedType.Clone (clonectx);
+               public override void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldtoken, (ConstructorInfo) method);
+                       base.Emit (ec);
+                       ec.ig.Emit (OpCodes.Castclass, type);
                }
        }
 
-       /// <summary>
-       ///   Implements the `typeof (void)' operator
-       /// </summary>
-       public class TypeOfVoid : TypeOf {
-               public TypeOfVoid (Location l) : base (null, l)
-               {
-                       loc = l;
+       abstract class TypeOfMethod : Expression
+       {
+               protected readonly MethodBase method;
+
+               protected TypeOfMethod (MethodBase method, Location loc)
+               {
+                       this.method = method;
+                       this.loc = loc;
+               }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       ArrayList args = new ArrayList (2);
+                       args.Add (new Argument (this));
+                       args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+                       return CreateExpressionFactoryCall ("Constant", args);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       bool is_generic = TypeManager.IsGenericType (method.DeclaringType);
+                       MethodInfo mi = is_generic ?
+                               TypeManager.methodbase_get_type_from_handle_generic :
+                               TypeManager.methodbase_get_type_from_handle;
+
+                       if (mi == null) {
+                               Type t = TypeManager.CoreLookupType ("System.Reflection", "MethodBase", Kind.Class, true);
+                               Type handle_type = TypeManager.CoreLookupType ("System", "RuntimeMethodHandle", Kind.Class, true);
+
+                               if (t == null || handle_type == null)
+                                       return null;
+
+                               mi = TypeManager.GetPredefinedMethod (t, "GetMethodFromHandle", loc,
+                                       is_generic ?
+                                       new Type[] { handle_type, TypeManager.runtime_handle_type } :
+                                       new Type[] { handle_type } );
+
+                               if (is_generic)
+                                       TypeManager.methodbase_get_type_from_handle_generic = mi;
+                               else
+                                       TypeManager.methodbase_get_type_from_handle = mi;
+                       }
+
+                       eclass = ExprClass.Value;
+                       return this;
                }
 
-               public override Expression DoResolve (EmitContext ec)
+               public override void Emit (EmitContext ec)
                {
-                       type = TypeManager.type_type;
-                       typearg = TypeManager.void_type;
+                       bool is_generic = TypeManager.IsGenericType (method.DeclaringType);
+                       MethodInfo mi;
+                       if (is_generic) {
+                               mi = TypeManager.methodbase_get_type_from_handle_generic;
+                               ec.ig.Emit (OpCodes.Ldtoken, method.DeclaringType);
+                       } else {
+                               mi = TypeManager.methodbase_get_type_from_handle;
+                       }
 
-                       return DoResolveBase ();
+                       ec.ig.Emit (OpCodes.Call, mi);
                }
        }
 
-       internal class TypeOfMethod : Expression
+       internal class TypeOfField : Expression
        {
-               readonly MethodInfo method;
+               readonly FieldInfo field;
 
-               public TypeOfMethod (MethodInfo method, Location loc)
+               public TypeOfField (FieldInfo field, Location loc)
                {
-                       this.method = method;
+                       this.field = field;
                        this.loc = loc;
                }
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       if (TypeManager.methodbase_get_type_from_handle == null) {
-                               Type t = TypeManager.CoreLookupType ("System.Reflection", "MethodBase", Kind.Class, true);
-                               Type handle_type = TypeManager.CoreLookupType ("System", "RuntimeMethodHandle", Kind.Class, true);
+                       if (TypeManager.fieldinfo_get_field_from_handle == null) {
+                               Type t = TypeManager.CoreLookupType ("System.Reflection", "FieldInfo", Kind.Class, true);
+                               Type handle_type = TypeManager.CoreLookupType ("System", "RuntimeFieldHandle", Kind.Class, true);
 
                                if (t != null && handle_type != null)
-                                       TypeManager.methodbase_get_type_from_handle = TypeManager.GetPredefinedMethod (t,
-                                               "GetMethodFromHandle", loc, handle_type);
+                                       TypeManager.fieldinfo_get_field_from_handle = TypeManager.GetPredefinedMethod (t,
+                                               "GetFieldFromHandle", loc, handle_type);
                        }
 
-                       type = typeof (MethodBase);
+                       type = typeof (FieldInfo);
                        eclass = ExprClass.Value;
                        return this;
                }
 
                public override void Emit (EmitContext ec)
                {
-                       ec.ig.Emit (OpCodes.Ldtoken, method);
-                       ec.ig.Emit (OpCodes.Call, TypeManager.methodbase_get_type_from_handle);
+                       ec.ig.Emit (OpCodes.Ldtoken, field);
+                       ec.ig.Emit (OpCodes.Call, TypeManager.fieldinfo_get_field_from_handle);
                }
        }
 
@@ -6699,19 +6997,18 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       Error_PointerInsideExpressionTree ();
+                       return null;
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        TypeExpr texpr = QueriedType.ResolveAsTypeTerminal (ec, false);
                        if (texpr == null)
                                return null;
 
-#if GMCS_SOURCE
-                       if (texpr is TypeParameterExpr){
-                               ((TypeParameterExpr)texpr).Error_CannotUseAsUnmanagedType (loc);
-                               return null;
-                       }
-#endif
-
                        type_queried = texpr.Type;
                        if (TypeManager.IsEnumType (type_queried))
                                type_queried = TypeManager.GetEnumUnderlyingType (type_queried);
@@ -6726,14 +7023,14 @@ namespace Mono.CSharp {
                                return new IntConstant (size_of, loc);
                        }
 
-                       if (!ec.InUnsafe) {
-                               Report.Error (233, loc, "`{0}' does not have a predefined size, therefore sizeof can only be used in an unsafe context (consider using System.Runtime.InteropServices.Marshal.SizeOf)",
-                                        TypeManager.CSharpName (type_queried));
+                       if (!TypeManager.VerifyUnManaged (type_queried, loc)){
                                return null;
                        }
 
-                       if (!TypeManager.VerifyUnManaged (type_queried, loc)){
-                               return null;
+                       if (!ec.InUnsafe) {
+                               Report.Error (233, loc,
+                                       "`{0}' does not have a predefined size, therefore sizeof can only be used in an unsafe context (consider using System.Runtime.InteropServices.Marshal.SizeOf)",
+                                       TypeManager.CSharpName (type_queried));
                        }
                        
                        type = TypeManager.int32_type;
@@ -6759,83 +7056,73 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Implements the qualified-alias-member (::) expression.
        /// </summary>
-       public class QualifiedAliasMember : Expression
+       public class QualifiedAliasMember : MemberAccess
        {
-               string alias, identifier;
+               readonly string alias;
+
+               public QualifiedAliasMember (string alias, string identifier, TypeArguments targs, Location l)
+                       : base (null, identifier, targs, l)
+               {
+                       this.alias = alias;
+               }
 
                public QualifiedAliasMember (string alias, string identifier, Location l)
+                       : base (null, identifier, l)
                {
                        this.alias = alias;
-                       this.identifier = identifier;
-                       loc = l;
                }
 
                public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
                {
-                       if (alias == "global")
-                               return new MemberAccess (RootNamespace.Global, identifier, loc).ResolveAsTypeStep (ec, silent);
+                       if (alias == "global") {
+                               expr = RootNamespace.Global;
+                               return base.ResolveAsTypeStep (ec, silent);
+                       }
 
                        int errors = Report.Errors;
-                       FullNamedExpression fne = ec.DeclContainer.NamespaceEntry.LookupAlias (alias);
-                       if (fne == null) {
+                       expr = ec.DeclContainer.NamespaceEntry.LookupAlias (alias);
+                       if (expr == null) {
                                if (errors == Report.Errors)
                                        Report.Error (432, loc, "Alias `{0}' not found", alias);
                                return null;
                        }
-                       if (fne.eclass != ExprClass.Namespace) {
-                               if (!silent)
-                                       Report.Error (431, loc, "`{0}' cannot be used with '::' since it denotes a type", alias);
-                               return null;
-                       }
-                       return new MemberAccess (fne, identifier).ResolveAsTypeStep (ec, silent);
-               }
-
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       FullNamedExpression fne;
-                       if (alias == "global") {
-                               fne = RootNamespace.Global;
-                       } else {
-                               int errors = Report.Errors;
-                               fne = ec.DeclContainer.NamespaceEntry.LookupAlias (alias);
-                               if (fne == null) {
-                                       if (errors == Report.Errors)
-                                               Report.Error (432, loc, "Alias `{0}' not found", alias);
-                                       return null;
-                               }
-                       }
 
-                       Expression retval = new MemberAccess (fne, identifier).DoResolve (ec);
-                       if (retval == null)
+                       FullNamedExpression fne = base.ResolveAsTypeStep (ec, silent);
+                       if (fne == null)
                                return null;
 
-                       if (!(retval is FullNamedExpression)) {
-                               Report.Error (687, loc, "The expression `{0}::{1}' did not resolve to a namespace or a type", alias, identifier);
+                       if (expr.eclass == ExprClass.Type) {
+                               if (!silent) {
+                                       Report.Error (431, loc,
+                                               "Alias `{0}' cannot be used with '::' since it denotes a type. Consider replacing '::' with '.'", alias);
+                               }
                                return null;
                        }
 
-                       // We defer this check till the end to match the behaviour of CSC
-                       if (fne.eclass != ExprClass.Namespace) {
-                               Report.Error (431, loc, "`{0}' cannot be used with '::' since it denotes a type", alias);
-                               return null;
-                       }
-                       return retval;
+                       return fne;
                }
 
-               public override void Emit (EmitContext ec)
+               public override Expression DoResolve (EmitContext ec)
                {
-                       throw new InternalErrorException ("QualifiedAliasMember found in resolved tree");
+                       return ResolveAsTypeStep (ec, false);
                }
 
-
-               public override string ToString ()
+               protected override void Error_IdentifierNotFound (IResolveContext rc, FullNamedExpression expr_type, string identifier)
                {
-                       return alias + "::" + identifier;
+                       Report.Error (687, loc,
+                               "A namespace alias qualifier `{0}' did not resolve to a namespace or a type",
+                               GetSignatureForError ());
                }
 
                public override string GetSignatureForError ()
                {
-                       return ToString ();
+                       string name = Name;
+                       if (targs != null) {
+                               name = TypeManager.RemoveGenericArity (Name) + "<" +
+                                       targs.GetSignatureForError () + ">";
+                       }
+
+                       return alias + "::" + name;
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -6847,31 +7134,25 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Implements the member access expression
        /// </summary>
-       public class MemberAccess : Expression {
-               public readonly string Identifier;
-               Expression expr;
-               readonly TypeArguments args;
+       public class MemberAccess : ATypeNameExpression {
+               protected Expression expr;
 
                public MemberAccess (Expression expr, string id)
-                       : this (expr, id, expr.Location)
+                       : base (id, expr.Location)
                {
+                       this.expr = expr;
                }
 
                public MemberAccess (Expression expr, string identifier, Location loc)
+                       : base (identifier, loc)
                {
                        this.expr = expr;
-                       Identifier = identifier;
-                       this.loc = loc;
                }
 
                public MemberAccess (Expression expr, string identifier, TypeArguments args, Location loc)
-                       : this (expr, identifier, loc)
+                       : base (identifier, args, loc)
                {
-                       this.args = args;
-               }
-
-               protected string LookupIdentifier {
-                       get { return MemberName.MakeName (Identifier, args); }
+                       this.expr = expr;
                }
 
                // TODO: this method has very poor performace for Enum fields and
@@ -6896,28 +7177,27 @@ namespace Mono.CSharp {
                        if (expr_resolved == null)
                                return null;
 
+                       string LookupIdentifier = MemberName.MakeName (Name, targs);
+
                        if (expr_resolved is Namespace) {
                                Namespace ns = (Namespace) expr_resolved;
                                FullNamedExpression retval = ns.Lookup (ec.DeclContainer, LookupIdentifier, loc);
 #if GMCS_SOURCE
-                               if ((retval != null) && (args != null))
-                                       retval = new ConstructedType (retval, args, loc).ResolveAsTypeStep (ec, false);
+                               if ((retval != null) && (targs != null))
+                                       retval = new ConstructedType (retval, targs, loc).ResolveAsTypeStep (ec, false);
 #endif
 
                                if (retval == null)
-                                       ns.Error_NamespaceDoesNotExist (ec.DeclContainer, loc, Identifier);
+                                       ns.Error_NamespaceDoesNotExist (ec.DeclContainer, loc, Name);
                                return retval;
                        }
 
                        Type expr_type = expr_resolved.Type;
-                       if (expr_type.IsPointer || expr_type == TypeManager.void_type || expr_resolved is NullLiteral){
+                       if (expr_type.IsPointer || expr_type == TypeManager.void_type ||
+                               expr_resolved is NullLiteral || expr_type == TypeManager.anonymous_method_type) {
                                Unary.Error_OperatorCannotBeApplied (loc, ".", expr_type);
                                return null;
                        }
-                       if (expr_type == TypeManager.anonymous_method_type){
-                               Unary.Error_OperatorCannotBeApplied (loc, ".", "anonymous method");
-                               return null;
-                       }
 
                        Constant c = expr_resolved as Constant;
                        if (c != null && c.GetValue () == null) {
@@ -6925,16 +7205,16 @@ namespace Mono.CSharp {
                                        "System.NullReferenceException");
                        }
 
-                       if (args != null) {
-                               if (!args.Resolve (ec))
+                       if (targs != null) {
+                               if (!targs.Resolve (ec))
                                        return null;
                        }
 
                        Expression member_lookup;
                        member_lookup = MemberLookup (
-                               ec.ContainerType, expr_type, expr_type, Identifier, loc);
+                               ec.ContainerType, expr_type, expr_type, Name, loc);
 #if GMCS_SOURCE
-                       if ((member_lookup == null) && (args != null)) {
+                       if ((member_lookup == null) && (targs != null)) {
                                member_lookup = MemberLookup (
                                        ec.ContainerType, expr_type, expr_type, LookupIdentifier, loc);
                        }
@@ -6948,12 +7228,12 @@ namespace Mono.CSharp {
                                if (expr_eclass == ExprClass.Value || expr_eclass == ExprClass.Variable ||
                                        expr_eclass == ExprClass.IndexerAccess || expr_eclass == ExprClass.PropertyAccess ||
                                        expr_eclass == ExprClass.EventAccess) {
-                                       ExtensionMethodGroupExpr ex_method_lookup = ec.TypeContainer.LookupExtensionMethod (expr_type, Identifier);
+                                       ExtensionMethodGroupExpr ex_method_lookup = ec.TypeContainer.LookupExtensionMethod (expr_type, Name, loc);
                                        if (ex_method_lookup != null) {
                                                ex_method_lookup.ExtensionExpression = expr_resolved;
 
-                                               if (args != null) {
-                                                       ex_method_lookup.SetTypeArguments (args);
+                                               if (targs != null) {
+                                                       ex_method_lookup.SetTypeArguments (targs);
                                                }
 
                                                return ex_method_lookup.DoResolve (ec);
@@ -6962,7 +7242,7 @@ namespace Mono.CSharp {
 
                                expr = expr_resolved;
                                Error_MemberLookupFailed (
-                                       ec.ContainerType, expr_type, expr_type, Identifier, null,
+                                       ec.ContainerType, expr_type, expr_type, Name, null,
                                        AllMemberTypes, AllBindingFlags);
                                return null;
                        }
@@ -6972,7 +7252,7 @@ namespace Mono.CSharp {
                                if (!(expr_resolved is TypeExpr) && 
                                    (original == null || !original.IdenticalNameAndTypeName (ec, expr_resolved, loc))) {
                                        Report.Error (572, loc, "`{0}': cannot reference a type through an expression; try `{1}' instead",
-                                               Identifier, member_lookup.GetSignatureForError ());
+                                               Name, member_lookup.GetSignatureForError ());
                                        return null;
                                }
 
@@ -7006,8 +7286,8 @@ namespace Mono.CSharp {
                        if (me == null)
                                return null;
 
-                       if (args != null) {
-                               me.SetTypeArguments (args);
+                       if (targs != null) {
+                               me.SetTypeArguments (targs);
                        }
 
                        if (original != null && !TypeManager.IsValueType (expr_type)) {
@@ -7049,12 +7329,14 @@ namespace Mono.CSharp {
                        if (new_expr == null)
                                return null;
 
+                       string LookupIdentifier = MemberName.MakeName (Name, targs);
+
                        if (new_expr is Namespace) {
                                Namespace ns = (Namespace) new_expr;
                                FullNamedExpression retval = ns.Lookup (rc.DeclContainer, LookupIdentifier, loc);
 #if GMCS_SOURCE
-                               if ((retval != null) && (args != null))
-                                       retval = new ConstructedType (retval, args, loc).ResolveAsTypeStep (rc, false);
+                               if ((retval != null) && (targs != null))
+                                       retval = new ConstructedType (retval, targs, loc).ResolveAsTypeStep (rc, false);
 #endif
                                if (!silent && retval == null)
                                        ns.Error_NamespaceDoesNotExist (rc.DeclContainer, loc, LookupIdentifier);
@@ -7080,30 +7362,7 @@ namespace Mono.CSharp {
                                if (silent)
                                        return null;
 
-                               member_lookup = MemberLookup (
-                                       rc.DeclContainer.TypeBuilder, expr_type, expr_type, SimpleName.RemoveGenericArity (LookupIdentifier),
-                                       MemberTypes.NestedType, BindingFlags.Public | BindingFlags.NonPublic, loc);
-
-                               if (member_lookup != null) {
-                                       tnew_expr = member_lookup.ResolveAsTypeTerminal (rc, false);
-                                       if (tnew_expr == null)
-                                               return null;
-
-                                       Namespace.Error_TypeArgumentsCannotBeUsed (tnew_expr.Type, loc);
-                                       return null;
-                               }
-
-                               member_lookup = MemberLookup (
-                                       rc.DeclContainer.TypeBuilder, expr_type, expr_type, LookupIdentifier,
-                                               MemberTypes.All, BindingFlags.Public | BindingFlags.NonPublic, loc);
-
-                               if (member_lookup == null) {
-                                       Report.Error (426, loc, "The nested type `{0}' does not exist in the type `{1}'",
-                                                         Identifier, new_expr.GetSignatureForError ());
-                               } else {
-                                       // TODO: Report.SymbolRelatedToPreviousError
-                                       member_lookup.Error_UnexpectedKind (null, "type", loc);
-                               }
+                               Error_IdentifierNotFound (rc, new_expr, LookupIdentifier);
                                return null;
                        }
 
@@ -7112,7 +7371,7 @@ namespace Mono.CSharp {
                                return null;
 
 #if GMCS_SOURCE
-                       TypeArguments the_args = args;
+                       TypeArguments the_args = targs;
                        Type declaring_type = texpr.Type.DeclaringType;
                        if (TypeManager.HasGenericArguments (declaring_type)) {
                                while (!TypeManager.IsEqual (TypeManager.DropGenericTypeArguments (expr_type), declaring_type)) {
@@ -7123,8 +7382,8 @@ namespace Mono.CSharp {
                                foreach (Type decl in TypeManager.GetTypeArguments (expr_type))
                                        new_args.Add (new TypeExpression (decl, loc));
 
-                               if (args != null)
-                                       new_args.Add (args);
+                               if (targs != null)
+                                       new_args.Add (targs);
 
                                the_args = new_args;
                        }
@@ -7138,9 +7397,32 @@ namespace Mono.CSharp {
                        return texpr;
                }
 
-               public override void Emit (EmitContext ec)
+               protected virtual void Error_IdentifierNotFound (IResolveContext rc, FullNamedExpression expr_type, string identifier)
                {
-                       throw new Exception ("Should not happen");
+                       Expression member_lookup = MemberLookup (
+                               rc.DeclContainer.TypeBuilder, expr_type.Type, expr_type.Type, SimpleName.RemoveGenericArity (identifier),
+                               MemberTypes.NestedType, BindingFlags.Public | BindingFlags.NonPublic, loc);
+
+                       if (member_lookup != null) {
+                               expr_type = member_lookup.ResolveAsTypeTerminal (rc, false);
+                               if (expr_type == null)
+                                       return;
+
+                               Namespace.Error_TypeArgumentsCannotBeUsed (expr_type.Type, loc);
+                               return;
+                       }
+
+                       member_lookup = MemberLookup (
+                               rc.DeclContainer.TypeBuilder, expr_type.Type, expr_type.Type, identifier,
+                                       MemberTypes.All, BindingFlags.Public | BindingFlags.NonPublic, loc);
+
+                       if (member_lookup == null) {
+                               Report.Error (426, loc, "The nested type `{0}' does not exist in the type `{1}'",
+                                                 Name, expr_type.GetSignatureForError ());
+                       } else {
+                               // TODO: Report.SymbolRelatedToPreviousError
+                               member_lookup.Error_UnexpectedKind (null, "type", loc);
+                       }
                }
 
                protected override void Error_TypeDoesNotContainDefinition (Type type, string name)
@@ -7157,14 +7439,9 @@ namespace Mono.CSharp {
                        base.Error_TypeDoesNotContainDefinition (type, name);
                }
 
-               public override string ToString ()
-               {
-                       return expr + "." + MemberName.MakeName (Identifier, args);
-               }
-
                public override string GetSignatureForError ()
                {
-                       return expr.GetSignatureForError () + "." + Identifier;
+                       return expr.GetSignatureForError () + "." + base.GetSignatureForError ();
                }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -7435,7 +7712,6 @@ namespace Mono.CSharp {
                ElementAccess ea;
 
                LocalTemporary temp;
-               LocalTemporary prepared_value;
 
                bool prepared;
                
@@ -7644,36 +7920,13 @@ namespace Mono.CSharp {
                //
                // Load the array arguments into the stack.
                //
-               // If we have been requested to cache the values (cached_locations array
-               // initialized), then load the arguments the first time and store them
-               // in locals.  otherwise load from local variables.
-               //
-               // prepare_for_load is used in compound assignments to cache original index
-               // values ( label[idx++] += s )
-               //
-               LocalTemporary [] LoadArrayAndArguments (EmitContext ec, bool prepare_for_load)
+               void LoadArrayAndArguments (EmitContext ec)
                {
                        ea.Expr.Emit (ec);
 
-                       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]).Emit (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)
@@ -7681,12 +7934,10 @@ namespace Mono.CSharp {
                        int rank = ea.Expr.Type.GetArrayRank ();
                        ILGenerator ig = ec.ig;
 
-                       if (prepared_value != null) {
-                               prepared_value.Emit (ec);
-                       } else if (prepared) {
+                       if (prepared) {
                                LoadFromPtr (ig, this.type);
                        } else {
-                               LoadArrayAndArguments (ec, false);
+                               LoadArrayAndArguments (ec);
                                EmitLoadOpcode (ig, type, rank);
                        }       
 
@@ -7707,24 +7958,13 @@ namespace Mono.CSharp {
                        int rank = ea.Expr.Type.GetArrayRank ();
                        ILGenerator ig = ec.ig;
                        Type t = source.Type;
-                       prepared = prepare_for_load && !(source is StringConcat);
+                       prepared = prepare_for_load;
 
                        if (prepared) {
                                AddressOf (ec, AddressOp.LoadStore);
                                ec.ig.Emit (OpCodes.Dup);
                        } 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);
-                                       }
-                               }
+                               LoadArrayAndArguments (ec);
                        }
 
                        if (rank == 1) {
@@ -7796,7 +8036,7 @@ namespace Mono.CSharp {
                        int rank = ea.Expr.Type.GetArrayRank ();
                        ILGenerator ig = ec.ig;
 
-                       LoadArrayAndArguments (ec, false);
+                       LoadArrayAndArguments (ec);
 
                        if (rank == 1){
                                ig.Emit (OpCodes.Ldelema, type);
@@ -8368,6 +8608,10 @@ namespace Mono.CSharp {
                        // nothing, as we only exist to not do anything.
                }
 
+               public override void EmitSideEffect (EmitContext ec)
+               {
+               }
+
                //
                // This is just because we might want to reuse this bad boy
                // instead of creating gazillions of EmptyExpressions.
@@ -8433,8 +8677,7 @@ namespace Mono.CSharp {
                        ArrayList args = new ArrayList (2);
                        args.Add (new Argument (source.CreateExpressionTree (ec)));
                        args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
-                       args.Add (new Argument (new Cast (new TypeExpression (typeof (MethodInfo), loc),
-                               new TypeOfMethod (method, loc))));
+                       args.Add (new Argument (new TypeOfMethodInfo (method, loc)));
                        return CreateExpressionFactoryCall ("Convert", args);
                }
                        
@@ -8460,15 +8703,15 @@ namespace Mono.CSharp {
        //   one bit at a time.
        // </summary>
        public class ComposedCast : TypeExpr {
-               Expression left;
+               FullNamedExpression left;
                string dim;
                
-               public ComposedCast (Expression left, string dim)
+               public ComposedCast (FullNamedExpression left, string dim)
                        : this (left, dim, left.Location)
                {
                }
 
-               public ComposedCast (Expression left, string dim, Location l)
+               public ComposedCast (FullNamedExpression left, string dim, Location l)
                {
                        this.left = left;
                        this.dim = dim;
@@ -8533,14 +8776,6 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               public override string Name {
-                       get { return left + dim; }
-               }
-
-               public override string FullName {
-                       get { return type.FullName; }
-               }
-
                public override string GetSignatureForError ()
                {
                        return left.GetSignatureForError () + dim;
@@ -8550,7 +8785,7 @@ namespace Mono.CSharp {
                {
                        ComposedCast target = (ComposedCast) t;
 
-                       target.left = left.Clone (clonectx);
+                       target.left = (FullNamedExpression)left.Clone (clonectx);
                }
        }
 
@@ -8566,6 +8801,12 @@ namespace Mono.CSharp {
                        eclass = ExprClass.Value;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       Error_PointerInsideExpressionTree ();
+                       return null;
+               }
+
                public override void Emit(EmitContext ec)
                {
                        array.Emit (ec);
@@ -8608,34 +8849,24 @@ namespace Mono.CSharp {
        //
        // Encapsulates a conversion rules required for array indexes
        //
-       public class ArrayIndexCast : Expression
+       public class ArrayIndexCast : TypeCast
        {
-               Expression expr;
-
                public ArrayIndexCast (Expression expr)
+                       : base (expr, expr.Type)
                {
-                       this.expr = expr;
-                       this.loc = expr.Location;
                }
 
                public override Expression CreateExpressionTree (EmitContext ec)
                {
                        ArrayList args = new ArrayList (2);
-                       args.Add (new Argument (expr.CreateExpressionTree (ec)));
+                       args.Add (new Argument (child.CreateExpressionTree (ec)));
                        args.Add (new Argument (new TypeOf (new TypeExpression (TypeManager.int32_type, loc), loc)));
                        return CreateExpressionFactoryCall ("ConvertChecked", args);
                }
 
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       type = expr.Type;
-                       eclass = expr.eclass;
-                       return this;
-               }
-
                public override void Emit (EmitContext ec)
                {
-                       expr.Emit (ec);
+                       child.Emit (ec);
                                
                        if (type == TypeManager.int32_type)
                                return;
@@ -8651,45 +8882,6 @@ namespace Mono.CSharp {
                }
        }
 
-       //
-       // Used by the fixed statement
-       //
-       public class StringPtr : Expression {
-               LocalBuilder b;
-               
-               public StringPtr (LocalBuilder b, Location l)
-               {
-                       this.b = b;
-                       eclass = ExprClass.Value;
-                       type = TypeManager.char_ptr_type;
-                       loc = l;
-               }
-
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       // This should never be invoked, we are born in fully
-                       // initialized state.
-
-                       return this;
-               }
-
-               public override void Emit (EmitContext ec)
-               {
-                       if (TypeManager.int_get_offset_to_string_data == null) {
-                               // TODO: Move to resolve !!
-                               TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedMethod (
-                                       TypeManager.runtime_helpers_type, "get_OffsetToStringData", loc, Type.EmptyTypes);
-                       }
-
-                       ILGenerator ig = ec.ig;
-
-                       ig.Emit (OpCodes.Ldloc, b);
-                       ig.Emit (OpCodes.Conv_I);
-                       ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
-                       ig.Emit (OpCodes.Add);
-               }
-       }
-       
        //
        // Implements the `stackalloc' keyword
        //
@@ -8705,6 +8897,11 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        count = count.Resolve (ec);
@@ -8768,60 +8965,76 @@ namespace Mono.CSharp {
        //
        // An object initializer expression
        //
-       public class ElementInitializer : Expression
+       public class ElementInitializer : Assign
        {
-               Expression initializer;
                public readonly string Name;
 
                public ElementInitializer (string name, Expression initializer, Location loc)
+                       : base (null, initializer, 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);
+                       target.source = source.Clone (clonectx);
+               }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       ArrayList args = new ArrayList (2);
+                       FieldExpr fe = target as FieldExpr;
+                       if (fe != null)
+                               args.Add (new Argument (fe.CreateTypeOfExpression ()));
+                       else
+                               args.Add (new Argument (((PropertyExpr)target).CreateSetterTypeOfExpression ()));
+
+                       args.Add (new Argument (source.CreateExpressionTree (ec)));
+                       return CreateExpressionFactoryCall (
+                               source is CollectionOrObjectInitializers ? "ListBind" : "Bind",
+                               args);
                }
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       if (initializer == null)
+                       if (source == null)
                                return EmptyExpressionStatement.Instance;
                        
-                       MemberExpr element_member = MemberLookupFinal (ec, ec.CurrentInitializerVariable.Type, ec.CurrentInitializerVariable.Type,
+                       MemberExpr me = MemberLookupFinal (ec, ec.CurrentInitializerVariable.Type, ec.CurrentInitializerVariable.Type,
                                Name, MemberTypes.Field | MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance, loc) as MemberExpr;
 
-                       if (element_member == null)
+                       if (me == null)
                                return null;
 
-                       element_member.InstanceExpression = ec.CurrentInitializerVariable;
+                       target = me;
+                       me.InstanceExpression = ec.CurrentInitializerVariable;
 
-                       if (initializer is CollectionOrObjectInitializers) {
+                       if (source is CollectionOrObjectInitializers) {
                                Expression previous = ec.CurrentInitializerVariable;
-                               ec.CurrentInitializerVariable = element_member;
-                               initializer = initializer.Resolve (ec);
+                               ec.CurrentInitializerVariable = target;
+                               source = source.Resolve (ec);
                                ec.CurrentInitializerVariable = previous;
-                               return initializer;
+                               if (source == null)
+                                       return null;
+                                       
+                               eclass = source.eclass;
+                               type = source.Type;
+                               return this;
                        }
 
-                       Assign a = new Assign (element_member, initializer, loc);
-                       if (a.Resolve (ec) == null)
+                       Expression expr = base.DoResolve (ec);
+                       if (expr == 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)
+                       Constant c = source as Constant;
+                       if (c != null && c.IsDefaultInitializer (type) && target.eclass == ExprClass.Variable)
                                return EmptyExpressionStatement.Instance;
 
-                       return a;
+                       return expr;
                }
 
                protected override Expression Error_MemberLookupFailed (MemberInfo[] members)
@@ -8836,17 +9049,20 @@ namespace Mono.CSharp {
 
                        return null;
                }
-
-               public override void Emit (EmitContext ec)
+               
+               public override void EmitStatement (EmitContext ec)
                {
-                       throw new NotSupportedException ("Should not be reached");
+                       if (source is CollectionOrObjectInitializers)
+                               source.Emit (ec);
+                       else
+                               base.EmitStatement (ec);
                }
        }
        
        //
        // A collection initializer expression
        //
-       public class CollectionElementInitializer : Expression
+       public class CollectionElementInitializer : Invocation
        {
                public class ElementInitializerArgument : Argument
                {
@@ -8856,49 +9072,61 @@ namespace Mono.CSharp {
                        }
                }
 
-               ArrayList arguments;
-
                public CollectionElementInitializer (Expression argument)
+                       : base (null, new ArrayList (1), true)
                {
-                       arguments = new ArrayList (1);
-                       arguments.Add (argument);
+                       Arguments.Add (argument);
                        this.loc = argument.Location;
                }
 
                public CollectionElementInitializer (ArrayList arguments, Location loc)
+                       : base (null, arguments, true)
                {
-                       this.arguments = arguments;
                        this.loc = loc;
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       ArrayList args = new ArrayList (2);
+                       args.Add (new Argument (mg.CreateExpressionTree (ec)));
+
+                       ArrayList expr_initializers = new ArrayList (Arguments.Count);
+                       foreach (Argument a in Arguments)
+                               expr_initializers.Add (a.Expr.CreateExpressionTree (ec));
+
+                       args.Add (new Argument (new ArrayCreation (
+                               CreateExpressionTypeExpression (loc), "[]", expr_initializers, loc)));
+                       return CreateExpressionFactoryCall ("ElementInit", args);
+               }
+
                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));
+
+                       target.Arguments = new ArrayList (Arguments.Count);
+                       foreach (Expression e in Arguments)
+                               target.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>
+                       if (eclass != ExprClass.Invalid)
+                               return this;
+
+                       // TODO: We could call a constructor which takes element count argument,
+                       // for known types like List<T>, Dictionary<T, U>
                        
-                       for (int i = 0; i < arguments.Count; ++i)
-                               arguments [i] = new ElementInitializerArgument ((Expression)arguments [i]);
+                       for (int i = 0; i < Arguments.Count; ++i) {
+                               Expression expr = ((Expression) Arguments [i]).Resolve (ec);
+                               if (expr == null)
+                                       return null;
 
-                       Expression add_method = new Invocation (
-                               new MemberAccess (ec.CurrentInitializerVariable, "Add", loc),
-                               arguments);
+                               Arguments [i] = new ElementInitializerArgument (expr);
+                       }
 
-                       add_method = add_method.Resolve (ec);
+                       base.expr = new MemberAccess (ec.CurrentInitializerVariable, "Add", loc);
 
-                       return add_method;
-               }
-               
-               public override void Emit (EmitContext ec)
-               {
-                       throw new NotSupportedException ("Should not be reached");
+                       return base.DoResolve (ec);
                }
        }
        
@@ -8924,6 +9152,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool IsCollectionInitializer {
+                       get {
+                               return type == typeof (CollectionOrObjectInitializers);
+                       }
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression target)
                {
                        CollectionOrObjectInitializers t = (CollectionOrObjectInitializers) target;
@@ -8932,9 +9166,24 @@ namespace Mono.CSharp {
                        foreach (Expression e in initializers)
                                t.initializers.Add (e.Clone (clonectx));
                }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       ArrayList expr_initializers = new ArrayList (initializers.Count);
+                       foreach (Expression e in initializers) {
+                               Expression expr = e.CreateExpressionTree (ec);
+                               if (expr != null)
+                                       expr_initializers.Add (expr);
+                       }
+
+                       return new ImplicitlyTypedArrayCreation ("[]", expr_initializers, loc);
+               }
                
                public override Expression DoResolve (EmitContext ec)
                {
+                       if (eclass != ExprClass.Invalid)
+                               return this;
+
                        bool is_elements_initialization = false;
                        ArrayList element_names = null;
                        for (int i = 0; i < initializers.Count; ++i) {
@@ -8982,7 +9231,7 @@ namespace Mono.CSharp {
                                        initializers [i] = e;
                        }
 
-                       type = typeof (CollectionOrObjectInitializers);
+                       type = is_elements_initialization ? typeof (ElementInitializer) : typeof (CollectionOrObjectInitializers);
                        eclass = ExprClass.Variable;
                        return this;
                }
@@ -9021,6 +9270,12 @@ namespace Mono.CSharp {
                                this.new_instance = newInstance;
                        }
 
+                       public override Expression CreateExpressionTree (EmitContext ec)
+                       {
+                               // Should not be reached
+                               throw new NotSupportedException ("ET");
+                       }
+
                        public override Expression DoResolve (EmitContext ec)
                        {
                                return this;
@@ -9062,6 +9317,17 @@ namespace Mono.CSharp {
                        target.initializers = (CollectionOrObjectInitializers) initializers.Clone (clonectx);
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       ArrayList args = new ArrayList (2);
+                       args.Add (new Argument (base.CreateExpressionTree (ec)));
+                       args.Add (new Argument (initializers.CreateExpressionTree (ec)));
+
+                       return CreateExpressionFactoryCall (
+                               initializers.IsCollectionInitializer ? "ListInit" : "MemberInit",
+                               args);
+               }
+
                public override Expression DoResolve (EmitContext ec)
                {
                        if (eclass != ExprClass.Invalid)
@@ -9244,6 +9510,11 @@ namespace Mono.CSharp {
                        t.initializer = initializer.Clone (clonectx);
                }
 
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       throw new NotSupportedException ("ET");
+               }
+
                public override bool Equals (object o)
                {
                        AnonymousTypeParameter other = o as AnonymousTypeParameter;