* ILTokenizer.cs: Handle comments first, handle whitespace in hex
[mono.git] / mcs / mcs / expression.cs
index 52fe6f4ef47066639324da45729432dc02581aae..7a743fb03f80cd8aa004e172b89d30f57d69d6c7 100755 (executable)
@@ -4,8 +4,8 @@
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
 //
-// (C) 2001 Ximian, Inc.
-//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+// (C) 2003, 2004 Novell, Inc.
 //
 #define USE_OLD
 
@@ -81,6 +81,28 @@ namespace Mono.CSharp {
                                ec.ig.Emit (OpCodes.Pop);
                }
        }
+
+       public class ParenthesizedExpression : Expression
+       {
+               public Expression Expr;
+
+               public ParenthesizedExpression (Expression expr, Location loc)
+               {
+                       this.Expr = expr;
+                       this.loc = loc;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       Expr = Expr.Resolve (ec);
+                       return Expr;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Should not happen");
+               }
+       }
        
        /// <summary>
        ///   Unary expressions.  
@@ -232,16 +254,16 @@ namespace Mono.CSharp {
 
                                        result = null;
                                        if (Convert.ImplicitConversionExists (ec, e, TypeManager.int32_type)){
-                                               result = new Cast (new TypeExpr (TypeManager.int32_type, loc), e, loc);
+                                               result = new Cast (new TypeExpression (TypeManager.int32_type, loc), e, loc);
                                                result = result.Resolve (ec);
                                        } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint32_type)){
-                                               result = new Cast (new TypeExpr (TypeManager.uint32_type, loc), e, loc);
+                                               result = new Cast (new TypeExpression (TypeManager.uint32_type, loc), e, loc);
                                                result = result.Resolve (ec);
                                        } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.int64_type)){
-                                               result = new Cast (new TypeExpr (TypeManager.int64_type, loc), e, loc);
+                                               result = new Cast (new TypeExpression (TypeManager.int64_type, loc), e, loc);
                                                result = result.Resolve (ec);
                                        } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint64_type)){
-                                               result = new Cast (new TypeExpr (TypeManager.uint64_type, loc), e, loc);
+                                               result = new Cast (new TypeExpression (TypeManager.uint64_type, loc), e, loc);
                                                result = result.Resolve (ec);
                                        }
 
@@ -406,6 +428,11 @@ namespace Mono.CSharp {
                                               "of a fixed statement initializer");
                                        return null;
                                }
+                               
+                               if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) {
+                                       Error (213, "You can not fix an already fixed expression");
+                                       return null;
+                               }
 
                                // According to the specs, a variable is considered definitely assigned if you take
                                // its address.
@@ -540,18 +567,36 @@ namespace Mono.CSharp {
                        return ResolveOperator (ec);
                }
 
+               public override Expression DoResolveLValue (EmitContext ec, Expression right)
+               {
+                       if (Oper == Operator.Indirection)
+                               return base.DoResolveLValue (ec, right);
+
+                       Error (131, "The left-hand side of an assignment must be a " +
+                              "variable, property or indexer");
+                       return null;
+               }
+
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
-                       Type expr_type = Expr.Type;
                        
                        switch (Oper) {
                        case Operator.UnaryPlus:
                                throw new Exception ("This should be caught by Resolve");
                                
                        case Operator.UnaryNegation:
-                               Expr.Emit (ec);
-                               ig.Emit (OpCodes.Neg);
+                               if (ec.CheckState) {
+                                       ig.Emit (OpCodes.Ldc_I4_0);
+                                       if (type == TypeManager.int64_type)
+                                               ig.Emit (OpCodes.Conv_U8);
+                                       Expr.Emit (ec);
+                                       ig.Emit (OpCodes.Sub_Ovf);
+                               } else {
+                                       Expr.Emit (ec);
+                                       ig.Emit (OpCodes.Neg);
+                               }
+                               
                                break;
                                
                        case Operator.LogicalNot:
@@ -575,16 +620,12 @@ namespace Mono.CSharp {
                        }
                }
 
-               /// <summary>
-               ///   This will emit the child expression for `ec' avoiding the logical
-               ///   not.  The parent will take care of changing brfalse/brtrue
-               /// </summary>
-               public void EmitLogicalNot (EmitContext ec)
+               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
                {
-                       if (Oper != Operator.LogicalNot)
-                               throw new Exception ("EmitLogicalNot can only be called with !expr");
-
-                       Expr.Emit (ec);
+                       if (Oper == Operator.LogicalNot)
+                               Expr.EmitBranchable (ec, target, !onTrue);
+                       else
+                               base.EmitBranchable (ec, target, onTrue);
                }
 
                public override string ToString ()
@@ -621,14 +662,14 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
 
                        if (temporary != null){
-                               if (have_temporary){
+                               if (have_temporary) {
                                        temporary.Emit (ec);
-                                       return;
+                               } else {
+                                       expr.Emit (ec);
+                                       ec.ig.Emit (OpCodes.Dup);
+                                       temporary.Store (ec);
+                                       have_temporary = true;
                                }
-                               expr.Emit (ec);
-                               ec.ig.Emit (OpCodes.Dup);
-                               temporary.Store (ec);
-                               have_temporary = true;
                        } else
                                expr.Emit (ec);
                        
@@ -678,7 +719,7 @@ namespace Mono.CSharp {
 
                public new void CacheTemporaries (EmitContext ec)
                {
-                       temporary = new LocalTemporary (ec, type);
+                       temporary = new LocalTemporary (ec, expr.Type);
                }
 
                public override string ToString ()
@@ -804,6 +845,9 @@ namespace Mono.CSharp {
                        //
                        type = expr_type;
                        if (expr.eclass == ExprClass.Variable){
+                               LocalVariableReference var = expr as LocalVariableReference;
+                               if ((var != null) && var.IsReadOnly)
+                                       Error (1604, "cannot assign to `" + var.Name + "' because it is readonly");
                                if (IsIncrementableNumber (expr_type) ||
                                    expr_type == TypeManager.decimal_type){
                                        return this;
@@ -942,6 +986,13 @@ namespace Mono.CSharp {
 
                        ia.CacheTemporaries (ec);
 
+                       //
+                       // NOTE: We should probably handle three cases:
+                       //
+                       //     * method invocation required.
+                       //     * direct stack manipulation possible
+                       //     * the object requires an "instance" field
+                       //
                        if (temp_storage == null){
                                //
                                // Temporary improvement: if we are dealing with something that does
@@ -950,9 +1001,8 @@ namespace Mono.CSharp {
                                // For now: only localvariables when not remapped
                                //
 
-                               if (method == null && 
-                                   (expr is LocalVariableReference && ec.RemapToProxy == false) ||
-                                   (expr is FieldExpr && ((FieldExpr) expr).FieldInfo.IsStatic)){
+                               if (method == null &&
+                                   ((expr is LocalVariableReference) ||(expr is FieldExpr && ((FieldExpr) expr).FieldInfo.IsStatic))){
                                        if (empty_expr == null)
                                                empty_expr = new EmptyExpression ();
                                        
@@ -1018,6 +1068,8 @@ namespace Mono.CSharp {
                                ia.EmitAssign (ec, temp_storage);
                                break;
                        }
+
+                       temp_storage.Release (ec);
                }
 
                public override void Emit (EmitContext ec)
@@ -1066,7 +1118,11 @@ namespace Mono.CSharp {
                        if (probe_type == null)
                                return null;
 
+                       CheckObsoleteAttribute (probe_type);
+
                        expr = expr.Resolve (ec);
+                       if (expr == null)
+                               return null;
                        
                        return this;
                }
@@ -1117,6 +1173,35 @@ namespace Mono.CSharp {
                        }
                        throw new Exception ("never reached");
                }
+               
+               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       switch (action){
+                       case Action.AlwaysFalse:
+                               if (! onTrue)
+                                       ig.Emit (OpCodes.Br, target);
+                               
+                               return;
+                       case Action.AlwaysTrue:
+                               if (onTrue)
+                                       ig.Emit (OpCodes.Br, target);
+                               
+                               return;
+                       case Action.LeaveOnStack:
+                               // the `e != null' rule.
+                               expr.Emit (ec);
+                               ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+                               return;
+                       case Action.Probe:
+                               expr.Emit (ec);
+                               ig.Emit (OpCodes.Isinst, probe_type);
+                               ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+                               return;
+                       }
+                       throw new Exception ("never reached");
+               }
 
                public override Expression DoResolve (EmitContext ec)
                {
@@ -1216,7 +1301,7 @@ namespace Mono.CSharp {
 
                        if (TypeManager.IsValueType (probe_type)){
                                Report.Error (77, loc, "The as operator should be used with a reference type only (" +
-                                             TypeManager.CSharpName (probe_type) + " is a value type");
+                                             TypeManager.CSharpName (probe_type) + " is a value type)");
                                return null;
                        
                        }
@@ -1323,7 +1408,7 @@ namespace Mono.CSharp {
                        Expression real_expr = expr;
                        if (real_expr is EnumConstant)
                                real_expr = ((EnumConstant) real_expr).Child;
-                               
+
                        if (real_expr is ByteConstant){
                                byte v = ((ByteConstant) real_expr).Value;
        
@@ -1694,9 +1779,9 @@ namespace Mono.CSharp {
                        if (real_expr is DoubleConstant){
                                double v = ((DoubleConstant) real_expr).Value;
        
-                               if (target_type == TypeManager.byte_type)
+                               if (target_type == TypeManager.byte_type){
                                        return new ByteConstant ((byte) v);
-                               if (target_type == TypeManager.sbyte_type)
+                               if (target_type == TypeManager.sbyte_type)
                                        return new SByteConstant ((sbyte) v);
                                if (target_type == TypeManager.short_type)
                                        return new ShortConstant ((short) v);
@@ -1766,13 +1851,13 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return null;
 
-                       int errors = Report.Errors;
-
                        type = ec.DeclSpace.ResolveType (target_type, false, Location);
                        
                        if (type == null)
                                return null;
 
+                       CheckObsoleteAttribute (type);
+
                        eclass = ExprClass.Value;
 
                        if (expr is Constant){
@@ -1782,6 +1867,10 @@ namespace Mono.CSharp {
                                        return e;
                        }
 
+                       if (type.IsPointer && !ec.InUnsafe) {
+                               UnsafeError (loc);
+                               return null;
+                       }
                        expr = Convert.ExplicitConversion (ec, expr, type, loc);
                        return expr;
                }
@@ -1816,15 +1905,6 @@ namespace Mono.CSharp {
                Operator oper;
                Expression left, right;
 
-               //
-               // After resolution, method might contain the operator overload
-               // method.
-               //
-               protected MethodBase method;
-               ArrayList  Arguments;
-
-               bool DelegateOperation;
-
                // This must be kept in sync with Operator!!!
                public static readonly string [] oper_names;
                
@@ -2026,7 +2106,7 @@ namespace Mono.CSharp {
                                                } else if (right is LongConstant){
                                                        long ll = ((LongConstant) right).Value;
 
-                                                       if (ll > 0)
+                                                       if (ll >= 0)
                                                                right = new ULongConstant ((ulong) ll);
                                                } else {
                                                        e = Convert.ImplicitNumericConversion (ec, right, l, loc);
@@ -2074,7 +2154,7 @@ namespace Mono.CSharp {
                                //
                                // If either operand is of type uint, and the other
                                // operand is of type sbyte, short or int, othe operands are
-                               // converted to type long.
+                               // converted to type long (unless we have an int constant).
                                //
                                Type other = null;
                                
@@ -2151,12 +2231,6 @@ namespace Mono.CSharp {
                        Error_OperatorCannotBeApplied (loc, OperName (oper), left.Type, right.Type);
                }
 
-               static bool is_32_or_64 (Type t)
-               {
-                       return (t == TypeManager.int32_type || t == TypeManager.uint32_type ||
-                               t == TypeManager.int64_type || t == TypeManager.uint64_type);
-               }
-
                static bool is_unsigned (Type t)
                {
                        return (t == TypeManager.uint32_type || t == TypeManager.uint64_type ||
@@ -2171,12 +2245,32 @@ namespace Mono.CSharp {
                        else
                                return false;
                }
+
+               Expression Make32or64 (EmitContext ec, Expression e)
+               {
+                       Type t= e.Type;
+                       
+                       if (t == TypeManager.int32_type || t == TypeManager.uint32_type ||
+                           t == TypeManager.int64_type || t == TypeManager.uint64_type)
+                               return e;
+                       Expression ee = Convert.ImplicitConversion (ec, e, TypeManager.int32_type, loc);
+                       if (ee != null)
+                               return ee;
+                       ee = Convert.ImplicitConversion (ec, e, TypeManager.uint32_type, loc);
+                       if (ee != null)
+                               return ee;
+                       ee = Convert.ImplicitConversion (ec, e, TypeManager.int64_type, loc);
+                       if (ee != null)
+                               return ee;
+                       ee = Convert.ImplicitConversion (ec, e, TypeManager.uint64_type, loc);
+                       if (ee != null)
+                               return ee;
+                       return null;
+               }
                                        
                Expression CheckShiftArguments (EmitContext ec)
                {
                        Expression e;
-                       Type l = left.Type;
-                       Type r = right.Type;
 
                        e = ForceConversion (ec, right, TypeManager.int32_type);
                        if (e == null){
@@ -2192,6 +2286,14 @@ namespace Mono.CSharp {
                                left = e;
                                type = e.Type;
 
+                               if (type == TypeManager.int32_type || type == TypeManager.uint32_type){
+                                       right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (31), loc);
+                                       right = right.DoResolve (ec);
+                               } else {
+                                       right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (63), loc);
+                                       right = right.DoResolve (ec);
+                               }
+
                                return this;
                        }
                        Error_OperatorCannotBeApplied ();
@@ -2215,6 +2317,13 @@ namespace Mono.CSharp {
                                        
                                        return this;
                                }
+                               
+                               // IntPtr equality
+                               if (l == TypeManager.intptr_type && r == TypeManager.intptr_type) {
+                                       Type = TypeManager.bool_type;
+                                       
+                                       return this;
+                               }
                        }
 
                        //
@@ -2239,26 +2348,21 @@ namespace Mono.CSharp {
                                        union = (MethodGroupExpr) left_expr;
                                
                                if (union != null) {
-                                       Arguments = new ArrayList ();
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+                                       ArrayList args = new ArrayList (2);
+                                       args.Add (new Argument (left, Argument.AType.Expression));
+                                       args.Add (new Argument (right, Argument.AType.Expression));
                                        
-                                       method = Invocation.OverloadResolve (ec, union, Arguments, Location.Null);
+                                       MethodBase method = Invocation.OverloadResolve (ec, union, args, Location.Null);
                                        if (method != null) {
                                                MethodInfo mi = (MethodInfo) method;
                                                
-                                               type = mi.ReturnType;
-                                               return this;
+                                               return new BinaryMethod (mi.ReturnType, method, args);
                                        } else {
                                                overload_failed = true;
                                        }
                                }
                        }
                        
-                       //
-                       // Step 2: Default operations on CLI native types.
-                       //
-
                        //
                        // Step 0: String concatenation (because overloading will get this wrong)
                        //
@@ -2267,94 +2371,35 @@ namespace Mono.CSharp {
                                // If any of the arguments is a string, cast to string
                                //
                                
-                               if (l == TypeManager.string_type){
-                                       
-                                       if (r == TypeManager.void_type) {
+                               // Simple constant folding
+                               if (left is StringConstant && right is StringConstant)
+                                       return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value);
+                               
+                               if (l == TypeManager.string_type || r == TypeManager.string_type) {
+
+                                       if (r == TypeManager.void_type || l == TypeManager.void_type) {
                                                Error_OperatorCannotBeApplied ();
                                                return null;
                                        }
                                        
-                                       if (r == TypeManager.string_type){
-                                               if (left is Constant && right is Constant){
-                                                       StringConstant ls = (StringConstant) left;
-                                                       StringConstant rs = (StringConstant) right;
-                                                       
-                                                       return new StringConstant (
-                                                               ls.Value + rs.Value);
-                                               }
-
-                                               if (left is Binary){
-                                                       Binary b = (Binary) left;
-
-                                                       //
-                                                       // Call String.Concat (string, string, string) or
-                                                       // String.Concat (string, string, string, string)
-                                                       // if possible.
-                                                       //
-                                                       if (b.oper == Operator.Addition &&
-                                                           (b.method == TypeManager.string_concat_string_string ||
-                                                            b.method == TypeManager.string_concat_string_string_string)){
-                                                               ArrayList bargs = b.Arguments;
-                                                               int count = bargs.Count;
-                                                               
-                                                               if (count == 2){
-                                                                       Arguments = bargs;
-                                                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
-                                                                       type = TypeManager.string_type;
-                                                                       method = TypeManager.string_concat_string_string_string;
-                                                                       
-                                                                       return this;
-                                                               } else if (count == 3){
-                                                                       Arguments = bargs;
-                                                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
-                                                                       type = TypeManager.string_type;
-                                                                       method = TypeManager.string_concat_string_string_string_string;                                                                 
-                                                                       return this;
-                                                               }
-                                                       }
-                                               }
+                                       // try to fold it in on the left
+                                       if (left is StringConcat) {
 
-                                               // string + string
-                                               method = TypeManager.string_concat_string_string;
-                                       } else {
-                                               // string + object
-                                               method = TypeManager.string_concat_object_object;
-                                               right = Convert.ImplicitConversion (
-                                                       ec, right, TypeManager.object_type, loc);
-                                               if (right == null){
-                                                       Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
-                                                       return null;
+                                               //
+                                               // We have to test here for not-null, since we can be doubly-resolved
+                                               // take care of not appending twice
+                                               //
+                                               if (type == null){
+                                                       type = TypeManager.string_type;
+                                                       ((StringConcat) left).Append (ec, right);
+                                                       return left.Resolve (ec);
+                                               } else {
+                                                       return left;
                                                }
                                        }
-                                       type = TypeManager.string_type;
-
-                                       Arguments = new ArrayList ();
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
-
-                                       return this;
                                        
-                               } else if (r == TypeManager.string_type){
-                                       // object + string
-
-                                       if (l == TypeManager.void_type) {
-                                               Error_OperatorCannotBeApplied ();
-                                               return null;
-                                       }
-                                       
-                                       method = TypeManager.string_concat_object_object;
-                                       left = Convert.ImplicitConversion (ec, left, TypeManager.object_type, loc);
-                                       if (left == null){
-                                               Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
-                                               return null;
-                                       }
-                                       Arguments = new ArrayList ();
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
-
-                                       type = TypeManager.string_type;
-
-                                       return this;
+                                       // Otherwise, start a new concat expression
+                                       return new StringConcat (ec, loc, left, right).Resolve (ec);
                                }
 
                                //
@@ -2436,28 +2481,37 @@ namespace Mono.CSharp {
                        // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
                        //
                        if (oper == Operator.Addition || oper == Operator.Subtraction) {
-                               if (l.IsSubclassOf (TypeManager.delegate_type) &&
-                                   r.IsSubclassOf (TypeManager.delegate_type)) {
-                                       
-                                       Arguments = new ArrayList ();
-                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
-                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
-                                       
-                                       if (oper == Operator.Addition)
-                                               method = TypeManager.delegate_combine_delegate_delegate;
-                                       else
-                                               method = TypeManager.delegate_remove_delegate_delegate;
-
-                                       if (l != r) {
-                                               Error_OperatorCannotBeApplied ();
-                                               return null;
+                               if (l.IsSubclassOf (TypeManager.delegate_type)){
+                                       if (right.eclass == ExprClass.MethodGroup && RootContext.V2){
+                                               Expression tmp = Convert.ImplicitConversionRequired (ec, right, l, loc);
+                                               if (tmp == null)
+                                                       return null;
+                                               right = tmp;
+                                               r = right.Type;
+                                       }
+                               
+                                       if (r.IsSubclassOf (TypeManager.delegate_type)){
+                                               MethodInfo method;
+                                               ArrayList args = new ArrayList (2);
+                                               
+                                               args = new ArrayList (2);
+                                               args.Add (new Argument (left, Argument.AType.Expression));
+                                               args.Add (new Argument (right, Argument.AType.Expression));
+                                               
+                                               if (oper == Operator.Addition)
+                                                       method = TypeManager.delegate_combine_delegate_delegate;
+                                               else
+                                                       method = TypeManager.delegate_remove_delegate_delegate;
+                                               
+                                               if (l != r) {
+                                                       Error_OperatorCannotBeApplied ();
+                                                       return null;
+                                               }
+                                               
+                                               return new BinaryDelegate (l, method, args);
                                        }
-
-                                       DelegateOperation = true;
-                                       type = l;
-                                       return this;
                                }
-
+                               
                                //
                                // Pointer arithmetic:
                                //
@@ -2484,12 +2538,16 @@ namespace Mono.CSharp {
                                                        return new PointerArithmetic (
                                                                false, left, right, TypeManager.int64_type,
                                                                loc);
-                                       } else if (is_32_or_64 (r))
-                                               return new PointerArithmetic (
-                                                       oper == Operator.Addition, left, right, l, loc);
-                               } else if (r.IsPointer && is_32_or_64 (l) && oper == Operator.Addition)
-                                       return new PointerArithmetic (
-                                               true, right, left, r, loc);
+                                       } else {
+                                               Expression t = Make32or64 (ec, right);
+                                               if (t != null)
+                                                       return new PointerArithmetic (oper == Operator.Addition, left, t, l, loc);
+                                       }
+                               } else if (r.IsPointer && oper == Operator.Addition){
+                                       Expression t = Make32or64 (ec, left);
+                                       if (t != null)
+                                               return new PointerArithmetic (true, right, t, r, loc);
+                               }
                        }
                        
                        //
@@ -2501,13 +2559,15 @@ namespace Mono.CSharp {
                                Expression temp;
 
                                // U operator - (E e, E f)
-                               if (lie && rie && oper == Operator.Subtraction){
-                                       if (l == r){
-                                               type = TypeManager.EnumToUnderlying (l);
-                                               return this;
-                                       } 
-                                       Error_OperatorCannotBeApplied ();
-                                       return null;
+                               if (lie && rie){
+                                       if (oper == Operator.Subtraction){
+                                               if (l == r){
+                                                       type = TypeManager.EnumToUnderlying (l);
+                                                       return this;
+                                               }
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
                                }
                                        
                                //
@@ -2518,9 +2578,18 @@ namespace Mono.CSharp {
                                        Type enum_type = lie ? l : r;
                                        Type other_type = lie ? r : l;
                                        Type underlying_type = TypeManager.EnumToUnderlying (enum_type);
-;
                                        
                                        if (underlying_type != other_type){
+                                               temp = Convert.ImplicitConversion (ec, lie ? right : left, underlying_type, loc);
+                                               if (temp != null){
+                                                       if (lie)
+                                                               right = temp;
+                                                       else
+                                                               left = temp;
+                                                       type = enum_type;
+                                                       return this;
+                                               }
+                                                       
                                                Error_OperatorCannotBeApplied ();
                                                return null;
                                        }
@@ -2642,13 +2711,17 @@ namespace Mono.CSharp {
                            oper == Operator.BitwiseOr ||
                            oper == Operator.ExclusiveOr){
                                if (l == r){
-                                       if (!((l == TypeManager.int32_type) ||
-                                             (l == TypeManager.uint32_type) ||
-                                             (l == TypeManager.short_type) ||
-                                             (l == TypeManager.ushort_type) ||
-                                             (l == TypeManager.int64_type) ||
-                                             (l == TypeManager.uint64_type)))
+                                       if (((l == TypeManager.int32_type) ||
+                                            (l == TypeManager.uint32_type) ||
+                                            (l == TypeManager.short_type) ||
+                                            (l == TypeManager.ushort_type) ||
+                                            (l == TypeManager.int64_type) ||
+                                            (l == TypeManager.uint64_type))){
                                                type = l;
+                                       } else {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
                                } else {
                                        Error_OperatorCannotBeApplied ();
                                        return null;
@@ -2669,7 +2742,18 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       left = left.Resolve (ec);
+                       if ((oper == Operator.Subtraction) && (left is ParenthesizedExpression)) {
+                               left = ((ParenthesizedExpression) left).Expr;
+                               left = left.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type);
+                               if (left == null)
+                                       return null;
+
+                               if (left.eclass == ExprClass.Type) {
+                                       Error (75, "Casting a negative value needs to have the value in parentheses.");
+                                       return null;
+                               }
+                       } else
+                               left = left.Resolve (ec);
                        right = right.Resolve (ec);
 
                        if (left == null || right == null)
@@ -2698,11 +2782,8 @@ namespace Mono.CSharp {
                ///   The expression's code is generated, and we will generate a branch to `target'
                ///   if the resulting expression value is equal to isTrue
                /// </remarks>
-               public bool EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
                {
-                       if (method != null)
-                               return false;
-
                        ILGenerator ig = ec.ig;
 
                        //
@@ -2711,136 +2792,78 @@ namespace Mono.CSharp {
                        // but on top of that we want for == and != to use a special path
                        // if we are comparing against null
                        //
-                       if (oper == Operator.Equality || oper == Operator.Inequality){
+                       if ((oper == Operator.Equality || oper == Operator.Inequality) && (left is Constant || right is Constant)) {
                                bool my_on_true = oper == Operator.Inequality ? onTrue : !onTrue;
-
-                               if (left is NullLiteral){
-                                       right.Emit (ec);
-                                       if (my_on_true)
-                                               ig.Emit (OpCodes.Brtrue, target);
-                                       else
-                                               ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
-                               } else if (right is NullLiteral){
+                               
+                               //
+                               // put the constant on the rhs, for simplicity
+                               //
+                               if (left is Constant) {
+                                       Expression swap = right;
+                                       right = left;
+                                       left = swap;
+                               }
+                               
+                               if (((Constant) right).IsZeroInteger) {
                                        left.Emit (ec);
                                        if (my_on_true)
                                                ig.Emit (OpCodes.Brtrue, target);
                                        else
                                                ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
-                               } else if (left is BoolConstant){
-                                       right.Emit (ec);
-                                       if (my_on_true != ((BoolConstant) left).Value)
-                                               ig.Emit (OpCodes.Brtrue, target);
-                                       else
-                                               ig.Emit (OpCodes.Brfalse, target);
-                                       return true;
-                               } else if (right is BoolConstant){
+                                       
+                                       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);
-                                       return true;
+                                       
+                                       return;
                                }
 
-                       } else if (oper == Operator.LogicalAnd){
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
+                       } else if (oper == Operator.LogicalAnd) {
 
-                                       if (onTrue){
-                                               Label tests_end = ig.DefineLabel ();
-                                               
-                                               if (left_binary.EmitBranchable (ec, tests_end, false)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
-
-                                                               if (right_binary.EmitBranchable (ec, target, true)){
-                                                                       ig.MarkLabel (tests_end);
-                                                                       return true;
-                                                               }
-                                                       }
-                                                       right.Emit (ec);
-                                                       ig.Emit (OpCodes.Brtrue, target);
-                                                       ig.MarkLabel (tests_end);
-                                                       return true;
-                                               }
-                                       } else {
-                                               if (left_binary.EmitBranchable (ec, target, false)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
-                                                               
-                                                               if (right_binary.EmitBranchable (ec, target, false))
-                                                                       return true;
-                                                       }
-                                                       right.Emit (ec);
-                                                       if (onTrue)
-                                                               ig.Emit (OpCodes.Brtrue, target);
-                                                       else
-                                                               ig.Emit (OpCodes.Brfalse, target);
-                                                       return true;
-                                               }
-                                       }
-                                       //
-                                       // Give up, and let the regular Emit work, but we could
-                                       // also optimize the left-non-Branchable, but-right-Branchable
-                                       //
+                               if (onTrue) {
+                                       Label tests_end = ig.DefineLabel ();
+                                       
+                                       left.EmitBranchable (ec, tests_end, false);
+                                       right.EmitBranchable (ec, target, true);
+                                       ig.MarkLabel (tests_end);                                       
+                               } else {
+                                       left.EmitBranchable (ec, target, false);
+                                       right.EmitBranchable (ec, target, false);
                                }
-                               return false;
+                               
+                               return;
+                               
                        } else if (oper == Operator.LogicalOr){
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
-
-                                       if (onTrue){
-                                               if (left_binary.EmitBranchable (ec, target, true)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
-                                                               
-                                                               if (right_binary.EmitBranchable (ec, target, true))
-                                                                       return true;
-                                                       }
-                                                       right.Emit (ec);
-                                                       ig.Emit (OpCodes.Brtrue, target);
-                                                       return true;
-                                               }
-                                               
-                                               //
-                                               // Give up, and let the regular Emit work, but we could
-                                               // also optimize the left-non-Branchable, but-right-Branchable
-                                               //
-                                       } else {
-                                               Label tests_end = ig.DefineLabel ();
-                                               
-                                               if (left_binary.EmitBranchable (ec, tests_end, true)){
-                                                       if (right is Binary){
-                                                               Binary right_binary = (Binary) right;
-
-                                                               if (right_binary.EmitBranchable (ec, target, false)){
-                                                                       ig.MarkLabel (tests_end);
-                                                                       return true;
-                                                               }
-                                                       }
-                                                       right.Emit (ec);
-                                                       ig.Emit (OpCodes.Brfalse, target);
-                                                       ig.MarkLabel (tests_end);
-                                                       return true;
-                                               }
-                                       }
+                               if (onTrue) {
+                                       left.EmitBranchable (ec, target, true);
+                                       right.EmitBranchable (ec, target, true);
+                                       
+                               } else {
+                                       Label tests_end = ig.DefineLabel ();
+                                       left.EmitBranchable (ec, tests_end, true);
+                                       right.EmitBranchable (ec, target, false);
+                                       ig.MarkLabel (tests_end);
                                }
                                
-                               return false;
-                       } else if (!(oper == Operator.LessThan ||
-                               oper == Operator.GreaterThan ||
-                               oper == Operator.LessThanOrEqual ||
-                               oper == Operator.GreaterThanOrEqual))
-                               return false;
+                               return;
+                               
+                       } else if (!(oper == Operator.LessThan        || oper == Operator.GreaterThan ||
+                                    oper == Operator.LessThanOrEqual || oper == Operator.GreaterThanOrEqual ||
+                                    oper == Operator.Equality        || oper == Operator.Inequality)) {
+                               base.EmitBranchable (ec, target, onTrue);
+                               return;
+                       }
                        
                        left.Emit (ec);
                        right.Emit (ec);
 
                        Type t = left.Type;
-                       bool isUnsigned = is_unsigned (t);
-
+                       bool isUnsigned = is_unsigned (t) || t == TypeManager.double_type || t == TypeManager.float_type;
+                       
                        switch (oper){
                        case Operator.Equality:
                                if (onTrue)
@@ -2883,9 +2906,6 @@ namespace Mono.CSharp {
                                break;
 
                        case Operator.LessThanOrEqual:
-                               if (t == TypeManager.double_type || t == TypeManager.float_type)
-                                       isUnsigned = true;
-
                                if (onTrue)
                                        if (isUnsigned)
                                                ig.Emit (OpCodes.Ble_Un, target);
@@ -2900,8 +2920,6 @@ namespace Mono.CSharp {
 
 
                        case Operator.GreaterThanOrEqual:
-                               if (t == TypeManager.double_type || t == TypeManager.float_type)
-                                       isUnsigned = true;
                                if (onTrue)
                                        if (isUnsigned)
                                                ig.Emit (OpCodes.Bge_Un, target);
@@ -2913,100 +2931,53 @@ namespace Mono.CSharp {
                                        else
                                                ig.Emit (OpCodes.Blt, target);
                                break;
-
                        default:
-                               return false;
+                               Console.WriteLine (oper);
+                               throw new Exception ("what is THAT");
                        }
-                       
-                       return true;
                }
                
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
                        Type l = left.Type;
-                       Type r = right.Type;
                        OpCode opcode;
 
-                       if (method != null) {
-
-                               // Note that operators are static anyway
-                               
-                               if (Arguments != null) 
-                                       Invocation.EmitArguments (ec, method, Arguments);
-                               
-                               if (method is MethodInfo)
-                                       ig.Emit (OpCodes.Call, (MethodInfo) method);
-                               else
-                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);
-
-                               if (DelegateOperation)
-                                       ig.Emit (OpCodes.Castclass, type);
-                                       
-                               return;
-                       }
-
                        //
                        // Handle short-circuit operators differently
                        // than the rest
                        //
-                       if (oper == Operator.LogicalAnd){
+                       if (oper == Operator.LogicalAnd) {
                                Label load_zero = ig.DefineLabel ();
                                Label end = ig.DefineLabel ();
-                               bool process = true;
-
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
-
-                                       if (left_binary.EmitBranchable (ec, load_zero, false)){
-                                               right.Emit (ec);
-                                               ig.Emit (OpCodes.Br, end);
-                                               process = false;
-                                       }
-                               }
-
-                               if (process){
-                                       left.Emit (ec);
-                                       ig.Emit (OpCodes.Brfalse, load_zero);
-                                       right.Emit (ec);
-                                       ig.Emit (OpCodes.Br, end);
-                               }
+                                                               
+                               left.EmitBranchable (ec, load_zero, false);
+                               right.Emit (ec);
+                               ig.Emit (OpCodes.Br, end);
+                               
                                ig.MarkLabel (load_zero);
                                ig.Emit (OpCodes.Ldc_I4_0);
                                ig.MarkLabel (end);
                                return;
-                       } else if (oper == Operator.LogicalOr){
+                       } else if (oper == Operator.LogicalOr) {
                                Label load_one = ig.DefineLabel ();
                                Label end = ig.DefineLabel ();
-                               bool process = true;
-                               
-                               if (left is Binary){
-                                       Binary left_binary = (Binary) left;
 
-                                       if (left_binary.EmitBranchable (ec, load_one, true)){
-                                               right.Emit (ec);
-                                               ig.Emit (OpCodes.Br, end);
-                                               process = false;
-                                       } 
-                               }
-
-                               if (process){
-                                       left.Emit (ec);
-                                       ig.Emit (OpCodes.Brtrue, load_one);
-                                       right.Emit (ec);
-                                       ig.Emit (OpCodes.Br, end);
-                               }
+                               left.EmitBranchable (ec, load_one, true);
+                               right.Emit (ec);
+                               ig.Emit (OpCodes.Br, end);
+                               
                                ig.MarkLabel (load_one);
                                ig.Emit (OpCodes.Ldc_I4_1);
                                ig.MarkLabel (end);
                                return;
                        }
-                       
+
                        left.Emit (ec);
                        right.Emit (ec);
 
                        bool isUnsigned = is_unsigned (left.Type);
-
+                       
                        switch (oper){
                        case Operator.Multiply:
                                if (ec.CheckState){
@@ -3115,9 +3086,9 @@ namespace Mono.CSharp {
                                else
                                        ig.Emit (OpCodes.Clt);
                                
-                               ig.Emit (OpCodes.Ldc_I4_1);
+                               ig.Emit (OpCodes.Ldc_I4_0);
                                
-                               opcode = OpCodes.Sub;
+                               opcode = OpCodes.Ceq;
                                break;
 
                        case Operator.BitwiseOr:
@@ -3139,14 +3110,218 @@ namespace Mono.CSharp {
 
                        ig.Emit (opcode);
                }
+       }
 
-               public bool IsBuiltinOperator {
-                       get {
-                               return method == null;
+       //
+       // Object created by Binary when the binary operator uses an method instead of being
+       // a binary operation that maps to a CIL binary operation.
+       //
+       public class BinaryMethod : Expression {
+               public MethodBase method;
+               public ArrayList  Arguments;
+               
+               public BinaryMethod (Type t, MethodBase m, ArrayList args)
+               {
+                       method = m;
+                       Arguments = args;
+                       type = t;
+                       eclass = ExprClass.Value;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       if (Arguments != null) 
+                               Invocation.EmitArguments (ec, method, Arguments);
+                       
+                       if (method is MethodInfo)
+                               ig.Emit (OpCodes.Call, (MethodInfo) method);
+                       else
+                               ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+               }
+       }
+       
+       //
+       // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string
+       // b, c, d... may be strings or objects.
+       //
+       public class StringConcat : Expression {
+               ArrayList operands;
+               bool invalid = false;
+               
+               
+               public StringConcat (EmitContext ec, Location loc, Expression left, Expression right)
+               {
+                       this.loc = loc;
+                       type = TypeManager.string_type;
+                       eclass = ExprClass.Value;
+               
+                       operands = new ArrayList (2);
+                       Append (ec, left);
+                       Append (ec, right);
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (invalid)
+                               return null;
+                       
+                       return this;
+               }
+               
+               public void Append (EmitContext ec, Expression operand)
+               {
+                       //
+                       // Constant folding
+                       //
+                       if (operand is StringConstant && operands.Count != 0) {
+                               StringConstant last_operand = operands [operands.Count - 1] as StringConstant;
+                               if (last_operand != null) {
+                                       operands [operands.Count - 1] = new StringConstant (last_operand.Value + ((StringConstant) operand).Value);
+                                       return;
+                               }
+                       }
+                       
+                       //
+                       // Conversion to object
+                       //
+                       if (operand.Type != TypeManager.string_type) {
+                               Expression no = Convert.ImplicitConversion (ec, operand, TypeManager.object_type, loc);
+                               
+                               if (no == null) {
+                                       Binary.Error_OperatorCannotBeApplied (loc, "+", TypeManager.string_type, operand.Type);
+                                       invalid = true;
+                               }
+                               operand = no;
+                       }
+                       
+                       operands.Add (operand);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       MethodInfo concat_method = null;
+                       
+                       //
+                       // Are we also concating objects?
+                       //
+                       bool is_strings_only = true;
+                       
+                       //
+                       // Do conversion to arguments; check for strings only
+                       //
+                       for (int i = 0; i < operands.Count; i ++) {
+                               Expression e = (Expression) operands [i];
+                               is_strings_only &= e.Type == TypeManager.string_type;
+                       }
+                       
+                       for (int i = 0; i < operands.Count; i ++) {
+                               Expression e = (Expression) operands [i];
+                               
+                               if (! is_strings_only && e.Type == TypeManager.string_type) {
+                                       // need to make sure this is an object, because the EmitParams
+                                       // method might look at the type of this expression, see it is a
+                                       // string and emit a string [] when we want an object [];
+                                       
+                                       e = Convert.ImplicitConversion (ec, e, TypeManager.object_type, loc);
+                               }
+                               operands [i] = new Argument (e, Argument.AType.Expression);
+                       }
+                       
+                       //
+                       // Find the right method
+                       //
+                       switch (operands.Count) {
+                       case 1:
+                               //
+                               // This should not be possible, because simple constant folding
+                               // is taken care of in the Binary code.
+                               //
+                               throw new Exception ("how did you get here?");
+                       
+                       case 2:
+                               concat_method = is_strings_only ? 
+                                       TypeManager.string_concat_string_string :
+                                       TypeManager.string_concat_object_object ;
+                               break;
+                       case 3:
+                               concat_method = is_strings_only ? 
+                                       TypeManager.string_concat_string_string_string :
+                                       TypeManager.string_concat_object_object_object ;
+                               break;
+                       case 4:
+                               //
+                               // There is not a 4 param overlaod for object (the one that there is
+                               // is actually a varargs methods, and is only in corlib because it was
+                               // introduced there before.).
+                               //
+                               if (!is_strings_only)
+                                       goto default;
+                               
+                               concat_method = TypeManager.string_concat_string_string_string_string;
+                               break;
+                       default:
+                               concat_method = is_strings_only ? 
+                                       TypeManager.string_concat_string_dot_dot_dot :
+                                       TypeManager.string_concat_object_dot_dot_dot ;
+                               break;
                        }
+                       
+                       Invocation.EmitArguments (ec, concat_method, operands);
+                       ec.ig.Emit (OpCodes.Call, concat_method);
                }
        }
 
+       //
+       // Object created with +/= on delegates
+       //
+       public class BinaryDelegate : Expression {
+               MethodInfo method;
+               ArrayList  args;
+
+               public BinaryDelegate (Type t, MethodInfo mi, ArrayList args)
+               {
+                       method = mi;
+                       this.args = args;
+                       type = t;
+                       eclass = ExprClass.Value;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       Invocation.EmitArguments (ec, method, args);
+                       
+                       ig.Emit (OpCodes.Call, (MethodInfo) method);
+                       ig.Emit (OpCodes.Castclass, type);
+               }
+
+               public Expression Right {
+                       get {
+                               Argument arg = (Argument) args [1];
+                               return arg.Expr;
+                       }
+               }
+
+               public bool IsAddition {
+                       get {
+                               return method == TypeManager.delegate_combine_delegate_delegate;
+                       }
+               }
+       }
+       
        //
        // User-defined conditional logical operator
        public class ConditionalLogicalOperator : Expression {
@@ -3175,6 +3350,7 @@ namespace Mono.CSharp {
                }
 
                Expression op_true, op_false, op;
+               LocalTemporary left_temp;
 
                public override Expression DoResolve (EmitContext ec)
                {
@@ -3187,8 +3363,10 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       left_temp = new LocalTemporary (ec, type);
+
                        ArrayList arguments = new ArrayList ();
-                       arguments.Add (new Argument (left, Argument.AType.Expression));
+                       arguments.Add (new Argument (left_temp, Argument.AType.Expression));
                        arguments.Add (new Argument (right, Argument.AType.Expression));
                        method = Invocation.OverloadResolve (ec, (MethodGroupExpr) operator_group, arguments, loc) as MethodInfo;
                        if ((method == null) || (method.ReturnType != type)) {
@@ -3198,8 +3376,8 @@ namespace Mono.CSharp {
 
                        op = new StaticCallExpr (method, arguments, loc);
 
-                       op_true = GetOperatorTrue (ec, left, loc);
-                       op_false = GetOperatorFalse (ec, left, loc);
+                       op_true = GetOperatorTrue (ec, left_temp, loc);
+                       op_false = GetOperatorFalse (ec, left_temp, loc);
                        if ((op_true == null) || (op_false == null)) {
                                Error218 ();
                                return null;
@@ -3216,8 +3394,11 @@ namespace Mono.CSharp {
 
                        ig.Emit (OpCodes.Nop);
 
-                       Statement.EmitBoolExpression (ec, is_and ? op_false : op_true, false_target, false);
                        left.Emit (ec);
+                       left_temp.Store (ec);
+
+                       (is_and ? op_false : op_true).EmitBranchable (ec, false_target, false);
+                       left_temp.Emit (ec);
                        ig.Emit (OpCodes.Br, end_target);
                        ig.MarkLabel (false_target);
                        op.Emit (ec);
@@ -3420,7 +3601,7 @@ namespace Mono.CSharp {
                        Label false_target = ig.DefineLabel ();
                        Label end_target = ig.DefineLabel ();
 
-                       Statement.EmitBoolExpression (ec, expr, false_target, false);
+                       expr.EmitBranchable (ec, false_target, false);
                        trueExpr.Emit (ec);
                        ig.Emit (OpCodes.Br, end_target);
                        ig.MarkLabel (false_target);
@@ -3437,7 +3618,6 @@ namespace Mono.CSharp {
                public readonly string Name;
                public readonly Block Block;
                LocalInfo local_info;
-               VariableInfo variable_info;
                bool is_readonly;
                
                public LocalVariableReference (Block block, string name, Location l)
@@ -3459,7 +3639,7 @@ namespace Mono.CSharp {
                }
 
                public VariableInfo VariableInfo {
-                       get { return variable_info; }
+                       get { return local_info.VariableInfo; }
                }
 
                public bool IsReadOnly {
@@ -3475,14 +3655,15 @@ namespace Mono.CSharp {
                                is_readonly = local_info.ReadOnly;
                        }
 
-                       variable_info = Block.GetVariableInfo (local_info);
                        type = local_info.VariableType;
+#if false
+                       if (ec.InAnonymousMethod)
+                               Block.LiftVariable (local_info);
+#endif
                }
-               
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       DoResolveBase (ec);
 
+               protected Expression DoResolve (EmitContext ec, bool is_lvalue)
+               {
                        Expression e = Block.GetConstantExpression (Name);
                        if (e != null) {
                                local_info.Used = true;
@@ -3490,20 +3671,35 @@ namespace Mono.CSharp {
                                return e;
                        }
 
+                       VariableInfo variable_info = local_info.VariableInfo; 
                        if ((variable_info != null) && !variable_info.IsAssigned (ec, loc))
                                return null;
 
-                       return this;
+                       if (!is_lvalue)
+                               local_info.Used = true;
+
+                       if (local_info.LocalBuilder == null)
+                               return ec.RemapLocal (local_info);
+                       
+                       return this;
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       DoResolveBase (ec);
+
+                       return DoResolve (ec, false);
                }
 
                override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
                        DoResolveBase (ec);
 
+                       VariableInfo variable_info = local_info.VariableInfo; 
                        if (variable_info != null)
                                variable_info.SetAssigned (ec);
 
-                       Expression e = DoResolve (ec);
+                       Expression e = DoResolve (ec, true);
 
                        if (e == null)
                                return null;
@@ -3512,6 +3708,11 @@ namespace Mono.CSharp {
                                Error (1604, "cannot assign to `" + Name + "' because it is readonly");
                                return null;
                        }
+
+                       CheckObsoleteAttribute (e.Type);
+
+                       if (local_info.LocalBuilder == null)
+                               return ec.RemapLocalLValue (local_info, right_side);
                        
                        return this;
                }
@@ -3525,40 +3726,22 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
 
-                       if (local_info.LocalBuilder == null){
-                               ig.Emit (OpCodes.Ldarg_0);
-                               ig.Emit (OpCodes.Ldfld, local_info.FieldBuilder);
-                       } else 
-                               ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
-                       
-                       local_info.Used = true;
+                       ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
                }
                
                public void EmitAssign (EmitContext ec, Expression source)
                {
                        ILGenerator ig = ec.ig;
 
-                       local_info.Assigned = true;
-
-                       if (local_info.LocalBuilder == null){
-                               ig.Emit (OpCodes.Ldarg_0);
-                               source.Emit (ec);
-                               ig.Emit (OpCodes.Stfld, local_info.FieldBuilder);
-                       } else {
-                               source.Emit (ec);
-                               ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
-                       }
+                       source.Emit (ec);
+                       ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
                }
                
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        ILGenerator ig = ec.ig;
                        
-                       if (local_info.LocalBuilder == null){
-                               ig.Emit (OpCodes.Ldarg_0);
-                               ig.Emit (OpCodes.Ldflda, local_info.FieldBuilder);
-                       } else
-                               ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
+                       ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
                }
 
                public override string ToString ()
@@ -3663,6 +3846,9 @@ namespace Mono.CSharp {
                        if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc))
                                return null;
 
+                       if (ec.RemapToProxy)
+                               return ec.RemapParameter (idx);
+                       
                        return this;
                }
 
@@ -3672,6 +3858,9 @@ namespace Mono.CSharp {
 
                        SetAssigned (ec);
 
+                       if (ec.RemapToProxy)
+                               return ec.RemapParameterLValue (idx, right_side);
+                       
                        return this;
                }
 
@@ -3710,12 +3899,6 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
                        
-                       if (ec.RemapToProxy){
-                               ig.Emit (OpCodes.Ldarg_0);
-                               ec.EmitArgument (idx);
-                               return;
-                       }
-                       
                        int arg_idx = idx;
 
                        if (!ec.IsStatic)
@@ -3737,13 +3920,6 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
                        
-                       if (ec.RemapToProxy){
-                               ig.Emit (OpCodes.Ldarg_0);
-                               source.Emit (ec);
-                               ec.EmitStoreArgument (idx);
-                               return;
-                       }
-                       
                        int arg_idx = idx;
 
                        if (!ec.IsStatic)
@@ -3766,11 +3942,6 @@ namespace Mono.CSharp {
 
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
-                       if (ec.RemapToProxy){
-                               Report.Error (-1, "Report this: Taking the address of a remapped parameter not supported");
-                               return;
-                       }
-                       
                        int arg_idx = idx;
 
                        if (!ec.IsStatic)
@@ -3869,6 +4040,24 @@ namespace Mono.CSharp {
 
                        if (ArgType == AType.Expression)
                                return true;
+                       else {
+                               //
+                               // Catch errors where fields of a MarshalByRefObject are passed as ref or out
+                               // This is only allowed for `this'
+                               //
+                               FieldExpr fe = Expr as FieldExpr;
+                               if (fe != null && !fe.IsStatic){
+                                       Expression instance = fe.InstanceExpression;
+
+                                       if (instance.GetType () != typeof (This)){
+                                               if (fe.InstanceExpression.Type.IsSubclassOf (TypeManager.mbr_type)){
+                                                       Report.Error (197, loc,
+                                                                     "Can not pass a type that derives from MarshalByRefObject with out or ref");
+                                                       return false;
+                                               }
+                                       }
+                               }
+                       }
 
                        if (Expr.eclass != ExprClass.Variable){
                                //
@@ -3914,8 +4103,9 @@ namespace Mono.CSharp {
                                                
                                                pr.AddressOf (ec, mode);
                                        }
-                               } else
+                               } else {
                                        ((IMemoryLocation)Expr).AddressOf (ec, mode);
+                               }
                        } else
                                Expr.Emit (ec);
                }
@@ -3986,9 +4176,10 @@ namespace Mono.CSharp {
                }
 
                /// <summary>
-               ///  Determines "better conversion" as specified in 7.4.2.3
-               ///  Returns : 1 if a->p is better
-               ///            0 if a->q or neither is better 
+               ///   Determines "better conversion" as specified in 7.4.2.3
+               ///
+                ///    Returns : 1 if a->p is better
+               ///              0 if a->q or neither is better 
                /// </summary>
                static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc)
                {
@@ -3996,17 +4187,40 @@ namespace Mono.CSharp {
                        Expression argument_expr = a.Expr;
 
                        if (argument_type == null)
-                               throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
+                               throw new Exception ("Expression of type " + a.Expr +
+                                                     " does not resolve its type");
 
                        //
-                       // This is a special case since csc behaves this way. I can't find
-                       // it anywhere in the spec but oh well ...
+                       // This is a special case since csc behaves this way.
                        //
-                       if (argument_expr is NullLiteral && p == TypeManager.string_type && q == TypeManager.object_type)
+                       if (argument_expr is NullLiteral &&
+                            p == TypeManager.string_type &&
+                            q == TypeManager.object_type)
                                return 1;
-                       else if (argument_expr is NullLiteral && p == TypeManager.object_type && q == TypeManager.string_type)
+                       else if (argument_expr is NullLiteral &&
+                                 p == TypeManager.object_type &&
+                                 q == TypeManager.string_type)
                                return 0;
                        
+                        //
+                        // csc behaves this way so we emulate it. Basically, if the argument
+                        // is null and one of the types to compare is 'object' and the other
+                        // is a reference type, we prefer the other.
+                        //
+                        // I can't find this anywhere in the spec but we can interpret this
+                        // to mean that null can be of any type you wish in such a context
+                        //
+                        if (p != null && q != null) {
+                                if (argument_expr is NullLiteral &&
+                                    !p.IsValueType &&
+                                    q == TypeManager.object_type)
+                                        return 1;
+                                else if (argument_expr is NullLiteral &&
+                                         !q.IsValueType &&
+                                         p == TypeManager.object_type)
+                                        return 0;
+                        }
+                                
                        if (p == q)
                                return 0;
                        
@@ -4071,6 +4285,14 @@ namespace Mono.CSharp {
                                        // we can optimize this case: a positive int32
                                        // always fits on a uint64
                                        //
+
+                                        //
+                                        // This special case is needed because csc behaves like this.
+                                        // int -> uint is better than int -> ulong!
+                                        //
+                                        if (q == TypeManager.uint32_type)
+                                                return 0;
+                                        
                                        if (q == TypeManager.int64_type)
                                                return 0;
                                        else if (value >= 0)
@@ -4125,16 +4347,18 @@ namespace Mono.CSharp {
                }
                
                /// <summary>
-               ///  Determines "Better function"
+               ///   Determines "Better function" between candidate
+                ///   and the current best match
                /// </summary>
                /// <remarks>
-               ///    and returns an integer indicating :
-               ///    0 if candidate ain't better
-               ///    1 if candidate is better than the current best match
+               ///    Returns an integer indicating :
+               ///     0 if candidate ain't better
+               ///     1 if candidate is better than the current best match
                /// </remarks>
                static int BetterFunction (EmitContext ec, ArrayList args,
-                                          MethodBase candidate, MethodBase best,
-                                          bool expanded_form, Location loc)
+                                          MethodBase candidate, bool candidate_params,
+                                           MethodBase best, bool best_params,
+                                          Location loc)
                {
                        ParameterData candidate_pd = GetParameterData (candidate);
                        ParameterData best_pd;
@@ -4146,14 +4370,35 @@ namespace Mono.CSharp {
                                argument_count = args.Count;
 
                        int cand_count = candidate_pd.Count;
-
+                       
+                       //
+                       // If there is no best method, than this one
+                       // is better, however, if we already found a
+                       // best method, we cant tell. This happens
+                       // if we have:
+                       // 
+                       //      interface IFoo {
+                       //              void DoIt ();
+                       //      }
+                       //      
+                       //      interface IBar {
+                       //              void DoIt ();
+                       //      }
+                       //      
+                       //      interface IFooBar : IFoo, IBar {}
+                       //
+                       // We cant tell if IFoo.DoIt is better than IBar.DoIt
+                       //
+                       // However, we have to consider that
+                       // Trim (); is better than Trim (params char[] chars);
+                        //
                        if (cand_count == 0 && argument_count == 0)
-                               return 1;
+                               return best == null || best_params ? 1 : 0;
 
                        if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)
                                if (cand_count != argument_count)
                                        return 0;
-                       
+
                        if (best == null) {
                                int x = 0;
 
@@ -4161,14 +4406,13 @@ namespace Mono.CSharp {
                                    candidate_pd.ParameterModifier (cand_count - 1) == Parameter.Modifier.PARAMS)
                                        return 1;
                                
-                               for (int j = argument_count; j > 0;) {
-                                       j--;
+                               for (int j = 0; j < argument_count; ++j) {
 
                                        Argument a = (Argument) args [j];
                                        Type t = candidate_pd.ParameterType (j);
 
                                        if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
-                                               if (expanded_form)
+                                               if (candidate_params)
                                                        t = TypeManager.GetElementType (t);
 
                                        x = BetterConversion (ec, a, t, null, loc);
@@ -4196,13 +4440,13 @@ namespace Mono.CSharp {
                                Type bt = best_pd.ParameterType (j);
 
                                if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
-                                       if (expanded_form)
+                                       if (candidate_params)
                                                ct = TypeManager.GetElementType (ct);
 
                                if (best_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
-                                       if (expanded_form)
+                                       if (best_params)
                                                bt = TypeManager.GetElementType (bt);
-                               
+
                                x = BetterConversion (ec, a, ct, bt, loc);
                                y = BetterConversion (ec, a, bt, ct, loc);
 
@@ -4213,6 +4457,16 @@ namespace Mono.CSharp {
                                rating2 += y;
                        }
 
+                        //
+                        // If a method (in the normal form) with the
+                        // same signature as the expanded form of the
+                        // current best params method already exists,
+                        // the expanded form is not applicable so we
+                        // force it to select the candidate
+                        //
+                        if (!candidate_params && best_params && cand_count == argument_count)
+                                return 1;
+
                        if (rating1 > rating2)
                                return 1;
                        else
@@ -4223,6 +4477,9 @@ namespace Mono.CSharp {
                {
                        string ret_type = "";
 
+                        if (mb == null)
+                                return "";
+
                        if (mb is MethodInfo)
                                ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType);
                        
@@ -4254,7 +4511,7 @@ namespace Mono.CSharp {
                        MemberInfo [] miset;
                        MethodGroupExpr union;
 
-                       if (mg1 == null){
+                       if (mg1 == null) {
                                if (mg2 == null)
                                        return null;
                                return (MethodGroupExpr) mg2;
@@ -4274,33 +4531,29 @@ namespace Mono.CSharp {
                        
                        ArrayList common = new ArrayList ();
 
-                       foreach (MethodBase l in left_set.Methods){
-                               foreach (MethodBase r in right_set.Methods){
-                                       if (l != r)
-                                               continue;
+                       foreach (MethodBase r in right_set.Methods){
+                               if (TypeManager.ArrayContainsMethod (left_set.Methods, r))
                                        common.Add (r);
-                                       break;
-                               }
                        }
-                       
+
                        miset = new MemberInfo [length1 + length2 - common.Count];
                        left_set.Methods.CopyTo (miset, 0);
                        
                        int k = length1;
 
-                       foreach (MemberInfo mi in right_set.Methods){
-                               if (!common.Contains (mi))
-                                       miset [k++] = mi;
+                       foreach (MethodBase r in right_set.Methods) {
+                               if (!common.Contains (r))
+                                       miset [k++] = r;
                        }
-                       
+
                        union = new MethodGroupExpr (miset, loc);
                        
                        return union;
                }
 
                /// <summary>
-               ///  Determines is the candidate method, if a params method, is applicable
-               ///  in its expanded form to the given set of arguments
+               ///   Determines if the candidate method, if a params method, is applicable
+               ///   in its expanded form to the given set of arguments
                /// </summary>
                static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
                {
@@ -4328,8 +4581,9 @@ namespace Mono.CSharp {
                                return true;
 
                        //
-                       // If we have come this far, the case which remains is when the number of parameters
-                       // is less than or equal to the argument count.
+                       // If we have come this far, the case which
+                       // remains is when the number of parameters is
+                       // less than or equal to the argument count.
                        //
                        for (int i = 0; i < pd_count - 1; ++i) {
 
@@ -4343,7 +4597,9 @@ namespace Mono.CSharp {
                                if (a_mod == p_mod) {
 
                                        if (a_mod == Parameter.Modifier.NONE)
-                                               if (!Convert.ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i)))
+                                               if (!Convert.ImplicitConversionExists (ec,
+                                                                                       a.Expr,
+                                                                                       pd.ParameterType (i)))
                                                        return false;
                                                                                
                                        if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
@@ -4365,7 +4621,7 @@ namespace Mono.CSharp {
                        for (int i = pd_count - 1; i < arg_count; i++) {
                                Argument a = (Argument) arguments [i];
                                
-                               if (!Convert.ImplicitStandardConversionExists (a.Expr, element_type))
+                               if (!Convert.ImplicitConversionExists (ec, a.Expr, element_type))
                                        return false;
                        }
                        
@@ -4373,8 +4629,8 @@ namespace Mono.CSharp {
                }
 
                /// <summary>
-               ///  Determines if the candidate method is applicable (section 14.4.2.1)
-               ///  to the given set of arguments
+               ///   Determines if the candidate method is applicable (section 14.4.2.1)
+               ///   to the given set of arguments
                /// </summary>
                static bool IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
                {
@@ -4388,8 +4644,6 @@ namespace Mono.CSharp {
 
                        ParameterData pd = GetParameterData (candidate);
 
-                       int pd_count = pd.Count;
-
                        if (arg_count != pd.Count)
                                return false;
 
@@ -4407,8 +4661,9 @@ namespace Mono.CSharp {
                                if (a_mod == p_mod ||
                                    (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) {
                                        if (a_mod == Parameter.Modifier.NONE) {
-                                                 if (!Convert.ImplicitConversionExists (ec,
-                                                                                       a.Expr, pd.ParameterType (i)))
+                                                if (!Convert.ImplicitConversionExists (ec,
+                                                                                       a.Expr,
+                                                                                       pd.ParameterType (i)))
                                                        return false;
                                         }
                                        
@@ -4417,7 +4672,7 @@ namespace Mono.CSharp {
 
                                                if (!pt.IsByRef)
                                                        pt = TypeManager.GetReferenceType (pt);
-
+                                                
                                                if (pt != a.Type)
                                                        return false;
                                        }
@@ -4428,8 +4683,6 @@ namespace Mono.CSharp {
                        return true;
                }
                
-               
-
                /// <summary>
                ///   Find the Applicable Function Members (7.4.2.1)
                ///
@@ -4455,9 +4708,17 @@ namespace Mono.CSharp {
                        ArrayList candidates = new ArrayList ();
 
                         //
-                        // First we construct the set of applicable methods
+                        // Used to keep a map between the candidate
+                        // and whether it is being considered in its
+                        // normal or expanded form
                         //
+                        // false is normal form, true is expanded form
+                        //
+                        Hashtable candidate_to_form = null;
+
 
+                        //
+                        // First we construct the set of applicable methods
                         //
                         // We start at the top of the type hierarchy and
                         // go down to find applicable methods
@@ -4469,9 +4730,9 @@ namespace Mono.CSharp {
                                 return null;
                         }
 
-
                         bool found_applicable = false;
-                       foreach (MethodBase candidate in me.Methods) {
+
+                       foreach (MethodBase candidate in me.Methods){
                                 Type decl_type = candidate.DeclaringType;
 
                                 //
@@ -4486,21 +4747,41 @@ namespace Mono.CSharp {
 
 
                                // Check if candidate is applicable (section 14.4.2.1)
-                               if (!IsApplicable (ec, Arguments, candidate))
-                                       continue;
-
-                               candidates.Add (candidate);
-                                applicable_type = candidate.DeclaringType;
-                                found_applicable = true;
-
+                               if (IsApplicable (ec, Arguments, candidate)) {
+                                        // Candidate is applicable in normal form
+                                        candidates.Add (candidate);
+                                        applicable_type = candidate.DeclaringType;
+                                        found_applicable = true;
+                                } else if (IsParamsMethodApplicable (ec, Arguments, candidate)) {
+                                       if (candidate_to_form == null)
+                                               candidate_to_form = new PtrHashtable ();
+                                       
+                                       // Candidate is applicable in expanded form
+                                       candidates.Add (candidate);
+                                       applicable_type = candidate.DeclaringType;
+                                       found_applicable = true; 
+                                       candidate_to_form [candidate] = candidate;
+                               }
                        }
-
+                        
 
                         //
                         // Now we actually find the best method
                         //
-                        foreach (MethodBase candidate in candidates) {
-                                int x = BetterFunction (ec, Arguments, candidate, method, false, loc);
+                       int candidate_top = candidates.Count;
+                       for (int ix = 0; ix < candidate_top; ix++){
+                               MethodBase candidate = (MethodBase) candidates [ix];
+
+                                bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
+                                bool method_params = false;
+
+                                if (method != null)
+                                        method_params = candidate_to_form != null && candidate_to_form.Contains (method);
+                                
+                                int x = BetterFunction (ec, Arguments,
+                                                        candidate, cand_params,
+                                                        method, method_params,
+                                                        loc);
                                 
                                 if (x == 0)
                                         continue;
@@ -4508,36 +4789,11 @@ namespace Mono.CSharp {
                                 method = candidate;
                         }
 
-
                        if (Arguments == null)
                                argument_count = 0;
                        else
                                argument_count = Arguments.Count;
                        
-                       //
-                       // Now we see if we can find params functions,
-                       // applicable in their expanded form since if
-                       // they were applicable in their normal form,
-                       // they would have been selected above anyways
-                       //
-                       bool chose_params_expanded = false;
-                       
-                       if (method == null) {
-                               candidates = new ArrayList ();
-                               foreach (MethodBase candidate in me.Methods){
-                                       if (!IsParamsMethodApplicable (ec, Arguments, candidate))
-                                               continue;
-
-                                       candidates.Add (candidate);
-
-                                       int x = BetterFunction (ec, Arguments, candidate, method, true, loc);
-                                       if (x == 0)
-                                               continue;
-
-                                       method = candidate; 
-                                       chose_params_expanded = true;
-                               }
-                       }
 
                        if (method == null) {
                                //
@@ -4554,6 +4810,7 @@ namespace Mono.CSharp {
 
                                        VerifyArgumentsCompat (ec, Arguments, argument_count, c, false,
                                                               null, loc);
+                                        break;
                                }
 
                                 if (!Location.IsNull (loc)) {
@@ -4571,11 +4828,14 @@ namespace Mono.CSharp {
                        // Now check that there are no ambiguities i.e the selected method
                        // should be better than all the others
                        //
+                        bool best_params = candidate_to_form != null && candidate_to_form.Contains (method);
 
-                       foreach (MethodBase candidate in candidates){
-                               if (candidate == method)
-                                       continue;
+                       for (int ix = 0; ix < candidate_top; ix++){
+                               MethodBase candidate = (MethodBase) candidates [ix];
 
+                                if (candidate == method)
+                                        continue;
+                                               
                                //
                                // If a normal method is applicable in
                                // the sense that it has the same
@@ -4584,13 +4844,15 @@ namespace Mono.CSharp {
                                // applicable so we debar the params
                                // method.
                                //
-
-                                if (IsParamsMethodApplicable (ec, Arguments, candidate) &&
-                                   IsApplicable (ec, Arguments, method))
-                                       continue;
-                                       
-                               int x = BetterFunction (ec, Arguments, method, candidate,
-                                                       chose_params_expanded, loc);
+                                // if ((IsParamsMethodApplicable (ec, Arguments, candidate) &&
+//                                      IsApplicable (ec, Arguments, method)))
+//                                         continue;
+                                
+                                bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
+                               int x = BetterFunction (ec, Arguments,
+                                                        method, best_params,
+                                                        candidate, cand_params,
+                                                       loc);
 
                                if (x != 1) {
                                        Report.Error (
@@ -4606,9 +4868,8 @@ namespace Mono.CSharp {
                        // necessary etc. and return if everything is
                        // all right
                        //
-
-                       if (!VerifyArgumentsCompat (ec, Arguments, argument_count, method,
-                                                  chose_params_expanded, null, loc))
+                        if (!VerifyArgumentsCompat (ec, Arguments, argument_count, method,
+                                                    best_params, null, loc))
                                return null;
 
                        return method;
@@ -4661,8 +4922,6 @@ namespace Mono.CSharp {
                                Parameter.Modifier pm = pd.ParameterModifier (j);
                                
                                if (pm == Parameter.Modifier.PARAMS){
-                                       Parameter.Modifier am = a.GetParameterModifier ();
-
                                        if ((pm & ~Parameter.Modifier.PARAMS) != a.GetParameterModifier ()) {
                                                if (!Location.IsNull (loc))
                                                        Error_InvalidArguments (
@@ -4717,9 +4976,6 @@ namespace Mono.CSharp {
                                if (a_mod != p_mod &&
                                    pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
                                        if (!Location.IsNull (loc)) {
-                                               Console.WriteLine ("A:P: " + a.GetParameterModifier ());
-                                               Console.WriteLine ("PP:: " + pd.ParameterModifier (j));
-                                               Console.WriteLine ("PT:  " + parameter_type.IsByRef);
                                                Report.Error (1502, loc,
                                                       "The best overloaded match for method '" + FullMethodDesc (method)+
                                                       "' has some invalid arguments");
@@ -4745,8 +5001,6 @@ namespace Mono.CSharp {
                        if (expr is BaseAccess)
                                is_base = true;
 
-                       Expression old = expr;
-                       
                        expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
                        if (expr == null)
                                return null;
@@ -4785,12 +5039,24 @@ namespace Mono.CSharp {
                                       "Could not find any applicable function for this argument list");
                                return null;
                        }
-
+                       
                        MethodInfo mi = method as MethodInfo;
                        if (mi != null) {
                                type = TypeManager.TypeToCoreType (mi.ReturnType);
-                               if (!mi.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null))
+                               if (!mi.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null)) {
                                        SimpleName.Error_ObjectRefRequired (ec, loc, mi.Name);
+                                       return null;
+                               }
+
+                               Expression iexpr = mg.InstanceExpression;
+                               if (mi.IsStatic && (iexpr != null) && !(iexpr is This)) {
+                                       if (mg.IdenticalTypeName)
+                                               mg.InstanceExpression = null;
+                                       else {
+                                               MemberAccess.error176 (loc, mi.Name);
+                                               return null;
+                                       }
+                               }
                        }
 
                        if (type.IsPointer){
@@ -4827,19 +5093,15 @@ namespace Mono.CSharp {
                        int count = arguments.Count - idx;
                        Argument a = (Argument) arguments [idx];
                        Type t = a.Expr.Type;
-                       string array_type = t.FullName + "[]";
-                       LocalBuilder array;
-
-                       array = ig.DeclareLocal (TypeManager.LookupType (array_type));
+                       
                        IntConstant.EmitInt (ig, count);
                        ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
-                       ig.Emit (OpCodes.Stloc, array);
 
                        int top = arguments.Count;
                        for (int j = idx; j < top; j++){
                                a = (Argument) arguments [j];
                                
-                               ig.Emit (OpCodes.Ldloc, array);
+                               ig.Emit (OpCodes.Dup);
                                IntConstant.EmitInt (ig, j - idx);
 
                                bool is_stobj;
@@ -4854,7 +5116,6 @@ namespace Mono.CSharp {
                                else
                                        ig.Emit (op);
                        }
-                       ig.Emit (OpCodes.Ldloc, array);
                }
                
                /// <summary>
@@ -4920,6 +5181,26 @@ namespace Mono.CSharp {
                        }
                }
 
+               /// <summary>
+               /// This checks the ConditionalAttribute on the method 
+               /// </summary>
+               static bool IsMethodExcluded (MethodBase method, EmitContext ec)
+               {
+                       if (method.IsConstructor)
+                               return false;
+
+                       IMethodData md = TypeManager.GetMethod (method);
+                       if (md != null)
+                               return md.IsExcluded (ec);
+
+                       // For some methods (generated by delegate class) GetMethod returns null
+                       // because they are not included in builder_to_method table
+                       if (method.DeclaringType is TypeBuilder)
+                               return false;
+
+                       return AttributeTester.IsConditionalMethodExcluded (method);
+               }
+
                /// <remarks>
                ///   is_base tells whether we want to force the use of the `call'
                ///   opcode instead of using callvirt.  Call is required to call
@@ -4941,6 +5222,7 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
                        bool struct_call = false;
+                       bool this_call = false;
 
                        Type decl_type = method.DeclaringType;
 
@@ -4964,14 +5246,20 @@ namespace Mono.CSharp {
                        }
 
                        //
-                       // This checks the `ConditionalAttribute' on the method, and the
-                       // ObsoleteAttribute
+                       // This checks ObsoleteAttribute on the method and on the declaring type
                        //
-                       TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (method, loc);
-                       if ((flags & TypeManager.MethodFlags.IsObsoleteError) != 0)
-                               return;
-                       if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
-                               return;
+                       ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (method);
+                       if (oa != null)
+                               AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (method), loc);
+
+
+                       oa = AttributeTester.GetObsoleteAttribute (method.DeclaringType);
+                       if (oa != null) {
+                               AttributeTester.Report_ObsoleteMessage (oa, method.DeclaringType.FullName, loc);
+                       }
+
+                       if (IsMethodExcluded (method, ec))
+                return; 
                        
                        if (!is_static){
                                if (decl_type.IsValueType)
@@ -4979,7 +5267,8 @@ namespace Mono.CSharp {
                                //
                                // If this is ourselves, push "this"
                                //
-                               if (instance_expr == null){
+                               if (instance_expr == null) {
+                                       this_call = true;
                                        ig.Emit (OpCodes.Ldarg_0);
                                } else {
                                        //
@@ -5022,8 +5311,13 @@ namespace Mono.CSharp {
                        }
 
                        EmitArguments (ec, method, Arguments);
-
-                       if (is_static || struct_call || is_base){
+                       //
+                       // If you have:
+                       // this.DoFoo ();
+                       // and DoFoo is not virtual, you can omit the callvirt,
+                       // because you don't need the null checking behavior.
+                       //
+                       if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)){
                                if (method is MethodInfo) {
                                        ig.Emit (OpCodes.Call, (MethodInfo) method);
                                } else
@@ -5077,7 +5371,7 @@ namespace Mono.CSharp {
                        //
                        type = ec.DeclSpace.ResolveType (expr, true, loc);
                        if (type != null) {
-                               Cast cast = new Cast (new TypeExpr (type, loc), argument, loc);
+                               Cast cast = new Cast (new TypeExpression (type, loc), argument, loc);
                                return cast.Resolve (ec);
                        }
 
@@ -5093,7 +5387,7 @@ namespace Mono.CSharp {
                        // Ok, so it's a Cast.
                        //
                        if (expr.eclass == ExprClass.Type) {
-                               Cast cast = new Cast (new TypeExpr (expr.Type, loc), argument, loc);
+                               Cast cast = new Cast (new TypeExpression (expr.Type, loc), argument, loc);
                                return cast.Resolve (ec);
                        }
 
@@ -5179,7 +5473,13 @@ namespace Mono.CSharp {
        /// </summary>
        public class New : ExpressionStatement, IMemoryLocation {
                public readonly ArrayList Arguments;
-               public readonly Expression RequestedType;
+
+               //
+               // During bootstrap, it contains the RequestedType,
+               // but if `type' is not null, it *might* contain a NewDelegate
+               // (because of field multi-initialization)
+               //
+               public Expression RequestedType;
 
                MethodBase method = null;
 
@@ -5245,18 +5545,28 @@ namespace Mono.CSharp {
                        //
                        // This leads to bugs (#37014)
                        //
-                       if (type != null)
+                       if (type != null){
+                               if (RequestedType is NewDelegate)
+                                       return RequestedType;
                                return this;
+                       }
                        
                        type = ec.DeclSpace.ResolveType (RequestedType, false, loc);
                        
                        if (type == null)
                                return null;
                        
+                       CheckObsoleteAttribute (type);
+
                        bool IsDelegate = TypeManager.IsDelegateType (type);
                        
-                       if (IsDelegate)
-                               return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
+                       if (IsDelegate){
+                               RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec);
+                               if (RequestedType != null)
+                                       if (!(RequestedType is NewDelegate))
+                                               throw new Exception ("NewDelegate.Resolve returned a non NewDelegate: " + RequestedType.GetType ());
+                               return RequestedType;
+                       }
 
                        if (type.IsInterface || type.IsAbstract){
                                Error (144, "It is not possible to create instances of interfaces or abstract classes");
@@ -5274,7 +5584,8 @@ namespace Mono.CSharp {
                                return this;
                        
                        Expression ml;
-                       ml = MemberLookupFinal (ec, null, type, ".ctor",
+                       // For member-lookup, treat 'new Foo (bar)' as call to 'foo.ctor (bar)', where 'foo' is of type 'Foo'.
+                       ml = MemberLookupFinal (ec, type, type, ".ctor",
                                                MemberTypes.Constructor,
                                                AllBindingFlags | BindingFlags.DeclaredOnly, loc);
 
@@ -5423,7 +5734,7 @@ namespace Mono.CSharp {
        ///   initialization data and the other which does not need dimensions
        ///   specified but where initialization data is mandatory.
        /// </remarks>
-       public class ArrayCreation : ExpressionStatement {
+       public class ArrayCreation : Expression {
                Expression requested_base_type;
                ArrayList initializers;
 
@@ -5481,9 +5792,9 @@ namespace Mono.CSharp {
                        this.rank = rank;
                        loc = l;
 
-                       //this.rank = rank.Substring (0, rank.LastIndexOf ("["));
+                       //this.rank = rank.Substring (0, rank.LastIndexOf ('['));
                        //
-                       //string tmp = rank.Substring (rank.LastIndexOf ("["));
+                       //string tmp = rank.Substring (rank.LastIndexOf ('['));
                        //
                        //dimensions = tmp.Length - 1;
                        expect_initializers = true;
@@ -5569,10 +5880,15 @@ namespace Mono.CSharp {
                                        
                                        if (conv == null) 
                                                return false;
-
-                                       if (conv is StringConstant)
+                                       
+                                       if (conv is StringConstant || conv is DecimalConstant || conv is NullCast) {
+                                               // These are subclasses of Constant that can appear as elements of an
+                                               // array that cannot be statically initialized (with num_automatic_initializers
+                                               // > max_automatic_initializers), so num_automatic_initializers should be left as zero.
                                                array_data.Add (conv);
-                                       else if (conv is Constant) {
+                                       } else if (conv is Constant) {
+                                               // These are the types of Constant that can appear in arrays that can be
+                                               // statically allocated.
                                                array_data.Add (conv);
                                                num_automatic_initializers++;
                                        } else
@@ -5805,7 +6121,7 @@ namespace Mono.CSharp {
                                eclass = ExprClass.Value;
                                return this;
                        } else {
-                               ModuleBuilder mb = CodeGen.ModuleBuilder;
+                               ModuleBuilder mb = CodeGen.Module.Builder;
                                ArrayList args = new ArrayList ();
                                
                                if (arguments != null) {
@@ -5981,7 +6297,7 @@ namespace Mono.CSharp {
                //
                // Emits the initializers for the array
                //
-               void EmitStaticInitializers (EmitContext ec, bool is_expression)
+               void EmitStaticInitializers (EmitContext ec)
                {
                        //
                        // First, the static data
@@ -5993,35 +6309,31 @@ namespace Mono.CSharp {
 
                        fb = RootContext.MakeStaticData (data);
 
-                       if (is_expression)
-                               ig.Emit (OpCodes.Dup);
+                       ig.Emit (OpCodes.Dup);
                        ig.Emit (OpCodes.Ldtoken, fb);
                        ig.Emit (OpCodes.Call,
                                 TypeManager.void_initializearray_array_fieldhandle);
                }
-               
+
                //
                // Emits pieces of the array that can not be computed at compile
                // time (variables and string locations).
                //
                // This always expect the top value on the stack to be the array
                //
-               void EmitDynamicInitializers (EmitContext ec, bool is_expression)
+               void EmitDynamicInitializers (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
                        int dims = bounds.Count;
                        int [] current_pos = new int [dims];
                        int top = array_data.Count;
-                       LocalBuilder temp = ig.DeclareLocal (type);
-
-                       ig.Emit (OpCodes.Stloc, temp);
 
                        MethodInfo set = null;
 
                        if (dims != 1){
                                Type [] args;
                                ModuleBuilder mb = null;
-                               mb = CodeGen.ModuleBuilder;
+                               mb = CodeGen.Module.Builder;
                                args = new Type [dims + 1];
 
                                int j;
@@ -6056,7 +6368,7 @@ namespace Mono.CSharp {
                                            num_automatic_initializers <= max_automatic_initializers) {
                                                Type etype = e.Type;
                                                
-                                               ig.Emit (OpCodes.Ldloc, temp);
+                                               ig.Emit (OpCodes.Dup);
 
                                                for (int idx = 0; idx < dims; idx++) 
                                                        IntConstant.EmitInt (ig, current_pos [idx]);
@@ -6065,9 +6377,9 @@ namespace Mono.CSharp {
                                                // If we are dealing with a struct, get the
                                                // address of it, so we can store it.
                                                //
-                                               if ((dims == 1) &&
+                                               if ((dims == 1) && 
                                                    etype.IsSubclassOf (TypeManager.value_type) &&
-                                                   (!TypeManager.IsBuiltinType (etype) ||
+                                                   (!TypeManager.IsBuiltinOrEnum (etype) ||
                                                     etype == TypeManager.decimal_type)) {
                                                        if (e is New){
                                                                New n = (New) e;
@@ -6084,12 +6396,12 @@ namespace Mono.CSharp {
 
                                                e.Emit (ec);
 
-                                                if (dims == 1)
-                                                        ArrayAccess.EmitStoreOpcode (ig, array_element_type);
-                                                else 
-                                                        ig.Emit (OpCodes.Call, set);
-                                                
-                                        }
+                                               if (dims == 1)
+                                                       ArrayAccess.EmitStoreOpcode (ig, array_element_type);
+                                               else 
+                                                       ig.Emit (OpCodes.Call, set);
+
+                                       }
                                }
                                
                                //
@@ -6102,9 +6414,6 @@ namespace Mono.CSharp {
                                        current_pos [j] = 0;
                                }
                        }
-
-                       if (is_expression)
-                               ig.Emit (OpCodes.Ldloc, temp);
                }
 
                void EmitArrayArguments (EmitContext ec)
@@ -6122,7 +6431,7 @@ namespace Mono.CSharp {
                        }
                }
                
-               void DoEmit (EmitContext ec, bool is_statement)
+               public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
                        
@@ -6142,27 +6451,16 @@ namespace Mono.CSharp {
                                // 
                                bool dynamic_initializers = true;
 
-                               if (underlying_type != TypeManager.string_type &&
-                                   underlying_type != TypeManager.decimal_type &&
-                                   underlying_type != TypeManager.object_type) {
-                                       if (num_automatic_initializers > max_automatic_initializers)
-                                               EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
-                               }
+                               // This will never be true for array types that cannot be statically
+                               // initialized. num_automatic_initializers will always be zero.  See
+                               // CheckIndices.
+                               if (num_automatic_initializers > max_automatic_initializers)
+                                       EmitStaticInitializers (ec);
                                
                                if (dynamic_initializers)
-                                       EmitDynamicInitializers (ec, !is_statement);
+                                       EmitDynamicInitializers (ec);
                        }
                }
-               
-               public override void Emit (EmitContext ec)
-               {
-                       DoEmit (ec, false);
-               }
-
-               public override void EmitStatement (EmitContext ec)
-               {
-                       DoEmit (ec, true);
-               }
 
                public object EncodeAsAttribute ()
                {
@@ -6191,6 +6489,16 @@ namespace Mono.CSharp {
                        }
                        return ret;
                }
+
+               public Expression TurnIntoConstant ()
+               {
+                       //
+                       // Should use something like the above attribute thing.
+                       // It should return a subclass of Constant that just returns
+                       // the computed value of the array
+                       //
+                       throw new Exception ("Does not support yet Turning array into a Constant");
+               }
        }
        
        /// <summary>
@@ -6235,7 +6543,7 @@ namespace Mono.CSharp {
                        }
 
                        if ((block != null) && (block.ThisVariable != null))
-                               variable_info = block.GetVariableInfo (block.ThisVariable);
+                               variable_info = block.ThisVariable.VariableInfo;
 
                        return true;
                }
@@ -6280,8 +6588,8 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
-                       
-                       ig.Emit (OpCodes.Ldarg_0);
+
+                       ec.EmitThis ();
                        if (ec.TypeContainer is Struct)
                                ig.Emit (OpCodes.Ldobj, type);
                }
@@ -6291,7 +6599,7 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        
                        if (ec.TypeContainer is Struct){
-                               ig.Emit (OpCodes.Ldarg_0);
+                               ec.EmitThis ();
                                source.Emit (ec);
                                ig.Emit (OpCodes.Stobj, type);
                        } else {
@@ -6302,7 +6610,7 @@ namespace Mono.CSharp {
 
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
-                       ec.ig.Emit (OpCodes.Ldarg_0);
+                       ec.EmitThis ();
 
                        // FIMXE
                        // FIGURE OUT WHY LDARG_S does not work
@@ -6315,12 +6623,35 @@ 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>
        public class TypeOf : Expression {
                public readonly Expression QueriedType;
-               Type typearg;
+               protected Type typearg;
                
                public TypeOf (Expression queried_type, Location l)
                {
@@ -6341,6 +6672,8 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       CheckObsoleteAttribute (typearg);
+
                        type = TypeManager.type_type;
                        eclass = ExprClass.Type;
                        return this;
@@ -6360,8 +6693,8 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Implements the `typeof (void)' operator
        /// </summary>
-       public class TypeOfVoid : Expression {
-               public TypeOfVoid (Location l)
+       public class TypeOfVoid : TypeOf {
+               public TypeOfVoid (Location l) : base (null, l)
                {
                        loc = l;
                }
@@ -6369,19 +6702,10 @@ namespace Mono.CSharp {
                public override Expression DoResolve (EmitContext ec)
                {
                        type = TypeManager.type_type;
+                       typearg = TypeManager.void_type;
                        eclass = ExprClass.Type;
                        return this;
                }
-
-               public override void Emit (EmitContext ec)
-               {
-                       ec.ig.Emit (OpCodes.Ldtoken, TypeManager.void_type);
-                       ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
-               }
-
-               public Type TypeArg { 
-                       get { return TypeManager.void_type; }
-               }
        }
 
        /// <summary>
@@ -6410,6 +6734,8 @@ namespace Mono.CSharp {
                        if (type_queried == null)
                                return null;
 
+                       CheckObsoleteAttribute (type_queried);
+
                        if (!TypeManager.IsUnmanagedType (type_queried)){
                                Report.Error (208, loc, "Cannot take the size of an unmanaged type (" + TypeManager.CSharpName (type_queried) + ")");
                                return null;
@@ -6451,7 +6777,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               static void error176 (Location loc, string name)
+               public static void error176 (Location loc, string name)
                {
                        Report.Error (176, loc, "Static member `" +
                                      name + "' cannot be accessed " +
@@ -6459,21 +6785,13 @@ namespace Mono.CSharp {
                                      "type name instead");
                }
 
-               static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Location loc)
+               static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Expression left, Location loc)
                {
-                       if (left_original == null)
-                               return false;
-
-                       if (!(left_original is SimpleName))
+                       SimpleName sn = left_original as SimpleName;
+                       if (sn == null || left == null || left.Type.Name != sn.Name)
                                return false;
 
-                       SimpleName sn = (SimpleName) left_original;
-
-                       Type t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc);
-                       if (t != null)
-                               return true;
-
-                       return false;
+                       return RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc) != null;
                }
                
                public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup,
@@ -6505,10 +6823,10 @@ namespace Mono.CSharp {
                                        Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
                                        
                                        if (c != null) {
-                                               object o = c.LookupConstantValue ();
-                                               if (o == null)
+                                               object o;
+                                               if (!c.LookupConstantValue (out o))
                                                        return null;
-                                               
+
                                                object real_value = ((Constant) c.Expr).GetValue ();
 
                                                return Constantify (real_value, fi.FieldType);
@@ -6527,7 +6845,7 @@ namespace Mono.CSharp {
                                        
                                        if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
                                                if (left_is_explicit && !left_is_type &&
-                                                   !IdenticalNameAndTypeName (ec, left_original, loc)) {
+                                                   !IdenticalNameAndTypeName (ec, left_original, member_lookup, loc)) {
                                                        error176 (loc, fe.FieldInfo.Name);
                                                        return null;
                                                }                                       
@@ -6571,7 +6889,8 @@ namespace Mono.CSharp {
                                // a FieldExpr
                                //
 
-                               if (ee.EventInfo.DeclaringType == ec.ContainerType) {
+                               if (ee.EventInfo.DeclaringType == ec.ContainerType ||
+                                   TypeManager.IsNestedChildOf(ec.ContainerType, ee.EventInfo.DeclaringType)) {
                                        MemberInfo mi = GetFieldFromEvent (ee);
 
                                        if (mi == null) {
@@ -6580,6 +6899,7 @@ namespace Mono.CSharp {
                                                // accessors and private field etc so there's no need
                                                // to transform ourselves.
                                                //
+                                               ee.InstanceExpression = left;
                                                return ee;
                                        }
 
@@ -6592,38 +6912,40 @@ namespace Mono.CSharp {
 
                                        if (!left_is_explicit)
                                                left = null;
-                                       
+
+                                       ee.InstanceExpression = left;
+
                                        return ResolveMemberAccess (ec, ml, left, loc, left_original);
                                }
                        }
 
                        if (member_lookup is IMemberExpr) {
                                IMemberExpr me = (IMemberExpr) member_lookup;
+                               MethodGroupExpr mg = me as MethodGroupExpr;
 
                                if (left_is_type){
-                                       MethodGroupExpr mg = me as MethodGroupExpr;
                                        if ((mg != null) && left_is_explicit && left.Type.IsInterface)
                                                mg.IsExplicitImpl = left_is_explicit;
 
                                        if (!me.IsStatic){
                                                if ((ec.IsFieldInitializer || ec.IsStatic) &&
-                                                   IdenticalNameAndTypeName (ec, left_original, loc))
+                                                   IdenticalNameAndTypeName (ec, left_original, member_lookup, loc))
                                                        return member_lookup;
-
+                                               
                                                SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
                                                return null;
                                        }
 
                                } else {
-                                       if (!me.IsInstance){
-                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
+                                       if (!me.IsInstance) {
+                                               if (IdenticalNameAndTypeName (ec, left_original, left, loc))
                                                        return member_lookup;
 
                                                if (left_is_explicit) {
                                                        error176 (loc, me.Name);
                                                        return null;
                                                }
-                                       }
+                                       }                       
 
                                        //
                                        // Since we can not check for instance objects in SimpleName,
@@ -6646,6 +6968,9 @@ namespace Mono.CSharp {
                                                }
                                        }
 
+                                       if ((mg != null) && IdenticalNameAndTypeName (ec, left_original, left, loc))
+                                               mg.IdenticalTypeName = true;
+
                                        me.InstanceExpression = left;
                                }
 
@@ -6654,7 +6979,7 @@ namespace Mono.CSharp {
 
                        Console.WriteLine ("Left is: " + left);
                        Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet");
-                       Environment.Exit (0);
+                       Environment.Exit (1);
                        return null;
                }
                
@@ -6692,13 +7017,10 @@ namespace Mono.CSharp {
                        // it will fail to find any members at all
                        //
 
-                       int errors = Report.Errors;
-                       
                        Type expr_type = expr.Type;
                        if (expr is TypeExpr){
                                if (!ec.DeclSpace.CheckAccessLevel (expr_type)){
-                                       Error (122, "`" + expr_type + "' " +
-                                              "is inaccessible because of its protection level");
+                                       Report.Error_T (122, loc, expr_type);
                                        return null;
                                }
 
@@ -6709,9 +7031,23 @@ namespace Mono.CSharp {
                                                object value = en.LookupEnumValue (ec, Identifier, loc);
                                                
                                                if (value != null){
+                                                       ObsoleteAttribute oa = en.GetObsoleteAttribute (ec, Identifier);
+                                                       if (oa != null) {
+                                                               AttributeTester.Report_ObsoleteMessage (oa, en.GetSignatureForError (), Location);
+                                                       }
+
                                                        Constant c = Constantify (value, en.UnderlyingType);
                                                        return new EnumConstant (c, expr_type);
                                                }
+                                       } else {
+                                               CheckObsoleteAttribute (expr_type);
+
+                                               FieldInfo fi = expr_type.GetField (Identifier);
+                                               if (fi != null) {
+                                                       ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (fi);
+                                                       if (oa != null)
+                                                               AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (fi), Location);
+                                               }
                                        }
                                }
                        }
@@ -6778,7 +7114,7 @@ namespace Mono.CSharp {
                                        string full_name = String.Concat (((SimpleName) full_expr.Expr).Name, ".", fname);
                                        Type fully_qualified = ec.DeclSpace.FindType (loc, full_name);
                                        if (fully_qualified != null)
-                                               return new TypeExpr (fully_qualified, loc);
+                                               return new TypeExpression (fully_qualified, loc);
                                }
 
                                full_expr = full_expr.Expr as MemberAccess;
@@ -7054,9 +7390,9 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
+#if false
                        ExprClass eclass = ea.Expr.eclass;
 
-#if false
                        // As long as the type is valid
                        if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
                              eclass == ExprClass.Value)) {
@@ -7133,7 +7469,9 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Ldelem_R8);
                        else if (type == TypeManager.intptr_type)
                                ig.Emit (OpCodes.Ldelem_I);
-                       else if (type.IsValueType){
+                       else if (TypeManager.IsEnumType (type)){
+                               EmitLoadOpcode (ig, TypeManager.EnumToUnderlying (type));
+                       } else if (type.IsValueType){
                                ig.Emit (OpCodes.Ldelema, type);
                                ig.Emit (OpCodes.Ldobj, type);
                        } else 
@@ -7191,7 +7529,7 @@ namespace Mono.CSharp {
 
                MethodInfo FetchGetMethod ()
                {
-                       ModuleBuilder mb = CodeGen.ModuleBuilder;
+                       ModuleBuilder mb = CodeGen.Module.Builder;
                        int arg_count = ea.Arguments.Count;
                        Type [] args = new Type [arg_count];
                        MethodInfo get;
@@ -7212,7 +7550,7 @@ namespace Mono.CSharp {
 
                MethodInfo FetchAddressMethod ()
                {
-                       ModuleBuilder mb = CodeGen.ModuleBuilder;
+                       ModuleBuilder mb = CodeGen.Module.Builder;
                        int arg_count = ea.Arguments.Count;
                        Type [] args = new Type [arg_count];
                        MethodInfo address;
@@ -7335,7 +7673,7 @@ namespace Mono.CSharp {
                        if (rank == 1)
                                EmitStoreOpcode (ig, t);
                        else {
-                               ModuleBuilder mb = CodeGen.ModuleBuilder;
+                               ModuleBuilder mb = CodeGen.Module.Builder;
                                int arg_count = ea.Arguments.Count;
                                Type [] args = new Type [arg_count + 1];
                                MethodInfo set;
@@ -7418,7 +7756,7 @@ namespace Mono.CSharp {
                        MemberInfo [] mi = TypeManager.MemberLookup (
                                caller_type, caller_type, lookup_type, MemberTypes.Property,
                                BindingFlags.Public | BindingFlags.Instance |
-                               BindingFlags.DeclaredOnly, p_name);
+                               BindingFlags.DeclaredOnly, p_name, null);
 
                        if (mi == null || mi.Length == 0)
                                return null;
@@ -7450,9 +7788,10 @@ namespace Mono.CSharp {
                        if (!lookup_type.IsInterface)
                                return ix;
 
-                       Type [] ifaces = TypeManager.GetInterfaces (lookup_type);
+                       TypeExpr [] ifaces = TypeManager.GetInterfaces (lookup_type);
                        if (ifaces != null) {
-                               foreach (Type itype in ifaces) {
+                               foreach (TypeExpr iface in ifaces) {
+                                       Type itype = iface.Type;
                                        MemberInfo [] mi = GetIndexersForTypeOrInterface (caller_type, itype);
                                        if (mi != null){
                                                if (ix == null)
@@ -7582,8 +7921,6 @@ namespace Mono.CSharp {
                        if (!CommonResolve (ec))
                                return null;
 
-                       Type right_type = right_side.Type;
-
                        bool found_any = false, found_any_setters = false;
 
                        Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type, loc);
@@ -7717,6 +8054,11 @@ namespace Mono.CSharp {
                                Error (1511, "Keyword base is not allowed in static method");
                                return null;
                        }
+
+                       if (ec.IsFieldInitializer){
+                               Error (1512, "Keyword base is not available in the current context");
+                               return null;
+                       }
                        
                        member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type, member,
                                                      AllMemberTypes, AllBindingFlags, loc);
@@ -7728,7 +8070,7 @@ namespace Mono.CSharp {
                        Expression left;
                        
                        if (ec.IsStatic)
-                               left = new TypeExpr (base_type, loc);
+                               left = new TypeExpression (base_type, loc);
                        else
                                left = ec.GetThis (loc);
                        
@@ -7864,7 +8206,7 @@ namespace Mono.CSharp {
        //   the type specification, we just use this to construct the type
        //   one bit at a time.
        // </summary>
-       public class ComposedCast : Expression {
+       public class ComposedCast : TypeExpr {
                Expression left;
                string dim;
                
@@ -7875,12 +8217,18 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public override Expression ResolveAsTypeStep (EmitContext ec)
+               public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
                {
                        Type ltype = ec.DeclSpace.ResolveType (left, false, loc);
                        if (ltype == null)
                                return null;
 
+                       if ((ltype == TypeManager.void_type) && (dim != "*")) {
+                               Report.Error (1547, Location,
+                                             "Keyword 'void' cannot be used in this context");
+                               return null;
+                       }
+
                        //
                        // ltype.Fullname is already fully qualified, so we can skip
                        // a lot of probes, and go directly to TypeManager.LookupType
@@ -7916,19 +8264,10 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       return ResolveAsTypeStep (ec);
-               }
-
-               public override void Emit (EmitContext ec)
-               {
-                       throw new Exception ("This should never be called");
-               }
-
-               public override string ToString ()
-               {
-                       return left + dim;
+               public override string Name {
+                       get {
+                               return left + dim;
+                       }
                }
        }
 
@@ -8028,9 +8367,10 @@ namespace Mono.CSharp {
                                        return null;
                        }
 
-                       if (ec.InCatch || ec.InFinally){
+                       if (ec.CurrentBranching.InCatch () ||
+                           ec.CurrentBranching.InFinally (true)) {
                                Error (255,
-                                             "stackalloc can not be used in a catch or finally block");
+                                      "stackalloc can not be used in a catch or finally block");
                                return null;
                        }