Copying latest mcs to the branch.
[mono.git] / mcs / gmcs / expression.cs
index 375788c126fc72c5944f6218e089e6bd6e329e3c..eaccda581af45e785e97cd22a9fee2ed83d97f8a 100644 (file)
@@ -456,6 +456,12 @@ namespace Mono.CSharp {
                                        lr.local_info.Used = true;
                                }
 
+                               ParameterReference pr = Expr as ParameterReference;
+                               if ((pr != null) && pr.Parameter.IsCaptured) {
+                                       AnonymousMethod.Error_AddressOfCapturedVar (pr.Name, loc);
+                                       return null;
+                               }
+
                                // According to the specs, a variable is considered definitely assigned if you take
                                // its address.
                                if ((variable != null) && (variable.VariableInfo != null)){
@@ -592,7 +598,7 @@ namespace Mono.CSharp {
                        if (Expr == null)
                                return null;
 
-                       if (TypeManager.IsNullableType (Expr.Type))
+                       if (TypeManager.IsNullableValueType (Expr.Type))
                                return new Nullable.LiftedUnaryOperator (Oper, Expr, loc).Resolve (ec);
 
                        eclass = ExprClass.Value;
@@ -696,7 +702,7 @@ namespace Mono.CSharp {
                        Emit (ec);
                        if (leave_copy) {
                                ec.ig.Emit (OpCodes.Dup);
-                               temporary = new LocalTemporary (ec, expr.Type);
+                               temporary = new LocalTemporary (expr.Type);
                                temporary.Store (ec);
                        }
                }
@@ -713,14 +719,16 @@ namespace Mono.CSharp {
                        source.Emit (ec);
                        if (leave_copy) {
                                ec.ig.Emit (OpCodes.Dup);
-                               temporary = new LocalTemporary (ec, expr.Type);
+                               temporary = new LocalTemporary (expr.Type);
                                temporary.Store (ec);
                        }
                        
                        StoreFromPtr (ec.ig, type);
                        
-                       if (temporary != null)
+                       if (temporary != null) {
                                temporary.Emit (ec);
+                               temporary.Release (ec);
+                       }
                }
                
                public void AddressOf (EmitContext ec, AddressOp Mode)
@@ -749,9 +757,7 @@ namespace Mono.CSharp {
                #region IVariable Members
 
                public VariableInfo VariableInfo {
-                       get {
-                               return null;
-                       }
+                       get { return null; }
                }
 
                public bool VerifyFixed ()
@@ -790,18 +796,18 @@ namespace Mono.CSharp {
                        PostIncrement  = IsPost,
                        PostDecrement  = IsPost | IsDecrement
                }
-               
+
                Mode mode;
                bool is_expr = false;
                bool recurse = false;
-               
+
                Expression expr;
 
                //
                // This is expensive for the simplest case.
                //
                StaticCallExpr method;
-                       
+
                public UnaryMutator (Mode m, Expression e, Location l)
                {
                        mode = m;
@@ -814,7 +820,7 @@ namespace Mono.CSharp {
                        return (mode == Mode.PreIncrement || mode == Mode.PostIncrement) ?
                                "++" : "--";
                }
-               
+
                /// <summary>
                ///   Returns whether an object of type `t' can be incremented
                ///   or decremented with add/sub (ie, basically whether we can
@@ -883,7 +889,7 @@ namespace Mono.CSharp {
                                if (expr == null)
                                        return null;
                        } else {
-                               expr.Error_UnexpectedKind (ec, "variable, indexer or property access", loc);
+                               expr.Error_UnexpectedKind (ec.DeclContainer, "variable, indexer or property access", loc);
                                return null;
                        }
 
@@ -899,7 +905,7 @@ namespace Mono.CSharp {
 
                        eclass = ExprClass.Value;
 
-                       if (TypeManager.IsNullableType (expr.Type))
+                       if (TypeManager.IsNullableValueType (expr.Type))
                                return new Nullable.LiftedUnaryMutator (mode, expr, loc).Resolve (ec);
 
                        return ResolveOperator (ec);
@@ -990,7 +996,7 @@ namespace Mono.CSharp {
                        }
                        
                }
-               
+
                void EmitCode (EmitContext ec, bool is_expr)
                {
                        recurse = true;
@@ -1006,7 +1012,7 @@ namespace Mono.CSharp {
                        // having to allocate another expression
                        //
                        if (recurse) {
-                               ((IAssignMethod) expr).Emit (ec, is_expr && (mode == Mode.PostIncrement  || mode == Mode.PostDecrement));
+                               ((IAssignMethod) expr).Emit (ec, is_expr && (mode == Mode.PostIncrement || mode == Mode.PostDecrement));
                                if (method == null)
                                        LoadOneAndEmitOp (ec, expr.Type);
                                else
@@ -1014,10 +1020,10 @@ namespace Mono.CSharp {
                                recurse = false;
                                return;
                        }
-                       
+
                        EmitCode (ec, true);
                }
-               
+
                public override void EmitStatement (EmitContext ec)
                {
                        EmitCode (ec, false);
@@ -1055,8 +1061,6 @@ namespace Mono.CSharp {
                        probe_type_expr = ProbeType.ResolveAsTypeTerminal (ec, false);
                        if (probe_type_expr == null)
                                return null;
-                       if (probe_type_expr.ResolveType (ec) == null)
-                               return null;
 
                        expr = expr.Resolve (ec);
                        if (expr == null)
@@ -1184,6 +1188,9 @@ namespace Mono.CSharp {
                                        action = Action.AlwaysFalse;
                                else
                                        action = Action.Probe;
+                       } else if (etype.ContainsGenericParameters || probe_type.ContainsGenericParameters) {
+                               expr = new BoxedCast (expr, etype);
+                               action = Action.Probe;
                        } else {
                                action = Action.AlwaysFalse;
                                warning_never_matches = true;
@@ -1288,9 +1295,20 @@ namespace Mono.CSharp {
                                return this;
                        }
 
+                       if (etype.ContainsGenericParameters || type.ContainsGenericParameters) {
+                               expr = new BoxedCast (expr, etype);
+                               do_isinst = true;
+                               return this;
+                       }
+
                        Error_CannotConvertType (etype, type, loc);
                        return null;
-               }                               
+               }
+       
+               public override bool GetAttributableValue (Type valueType, out object value)
+               {
+                       return expr.GetAttributableValue (valueType, out value);
+               }
        }
        
        /// <summary>
@@ -1313,30 +1331,18 @@ namespace Mono.CSharp {
                        this.target_type = cast_type;
                        this.expr = expr;
                        this.loc = loc;
+
+                       if (target_type == TypeManager.system_void_expr)
+                               Error_VoidInvalidInTheContext (loc);
                }
 
                public Expression TargetType {
-                       get {
-                               return target_type;
-                       }
+                       get { return target_type; }
                }
 
                public Expression Expr {
-                       get {
-                               return expr;
-                       }
-                       set {
-                               expr = value;
-                       }
-               }
-               
-               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
-               {
-                       expr = expr.DoResolveLValue (ec, right_side);
-                       if (expr == null)
-                               return null;
-
-                       return ResolveRest (ec);
+                       get { return expr; }
+                       set { expr = value; }
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -1345,16 +1351,11 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return null;
 
-                       return ResolveRest (ec);
-               }
-
-               Expression ResolveRest (EmitContext ec)
-               {
                        TypeExpr target = target_type.ResolveAsTypeTerminal (ec, false);
                        if (target == null)
                                return null;
                        
-                       type = target.ResolveType (ec);
+                       type = target.Type;
 
                        if (type.IsAbstract && type.IsSealed) {
                                Report.Error (716, loc, "Cannot convert to static type `{0}'", TypeManager.CSharpName (type));
@@ -1365,9 +1366,14 @@ namespace Mono.CSharp {
 
                        Constant c = expr as Constant;
                        if (c != null) {
-                               c = c.TryReduce (ec, type, loc);
-                               if (c != null)
-                                       return c;
+                               try {
+                                       c = c.TryReduce (ec, type, loc);
+                                       if (c != null)
+                                               return c;
+                               }
+                               catch (OverflowException) {
+                                       return null;
+                               }
                        }
 
                        if (type.IsPointer && !ec.InUnsafe) {
@@ -1380,9 +1386,6 @@ namespace Mono.CSharp {
                
                public override void Emit (EmitContext ec)
                {
-                       //
-                       // This one will never happen
-                       //
                        throw new Exception ("Should not happen");
                }
        }
@@ -1542,193 +1545,60 @@ namespace Mono.CSharp {
                                + "'");
                }
 
-               bool IsOfType (EmitContext ec, Type l, Type r, Type t, bool check_user_conversions)
+               bool IsConvertible (EmitContext ec, Expression le, Expression re, Type t)
                {
-                       if ((l == t) || (r == t))
-                               return true;
-
-                       if (!check_user_conversions)
-                               return false;
+                       return Convert.ImplicitConversionExists (ec, le, t) && Convert.ImplicitConversionExists (ec, re, t);
+               }
 
-                       if (Convert.ImplicitUserConversionExists (ec, l, t))
-                               return true;
-                       else if (Convert.ImplicitUserConversionExists (ec, r, t))
-                               return true;
-                       else
+               bool VerifyApplicable_Predefined (EmitContext ec, Type t)
+               {
+                       if (!IsConvertible (ec, left, right, t))
                                return false;
+                       left = ForceConversion (ec, left, t);
+                       right = ForceConversion (ec, right, t);
+                       type = t;
+                       return true;
                }
 
-               //
-               // Note that handling the case l == Decimal || r == Decimal
-               // is taken care of by the Step 1 Operator Overload resolution.
-               //
-               // If `check_user_conv' is true, we also check whether a user-defined conversion
-               // exists.  Note that we only need to do this if both arguments are of a user-defined
-               // type, otherwise ConvertImplict() already finds the user-defined conversion for us,
-               // so we don't explicitly check for performance reasons.
-               //
-               bool DoNumericPromotions (EmitContext ec, Type l, Type r, Expression lexpr, Expression rexpr, bool check_user_conv)
-               {
-                       if (IsOfType (ec, l, r, TypeManager.double_type, check_user_conv)){
-                               //
-                               // If either operand is of type double, the other operand is
-                               // conveted to type double.
-                               //
-                               if (r != TypeManager.double_type)
-                                       right = Convert.ImplicitConversion (ec, right, TypeManager.double_type, loc);
-                               if (l != TypeManager.double_type)
-                                       left = Convert.ImplicitConversion (ec, left, TypeManager.double_type, loc);
-                               
-                               type = TypeManager.double_type;
-                       } else if (IsOfType (ec, l, r, TypeManager.float_type, check_user_conv)){
-                               //
-                               // if either operand is of type float, the other operand is
-                               // converted to type float.
-                               //
-                               if (r != TypeManager.double_type)
-                                       right = Convert.ImplicitConversion (ec, right, TypeManager.float_type, loc);
-                               if (l != TypeManager.double_type)
-                                       left = Convert.ImplicitConversion (ec, left, TypeManager.float_type, loc);
-                               type = TypeManager.float_type;
-                       } else if (IsOfType (ec, l, r, TypeManager.uint64_type, check_user_conv)){
-                               Expression e;
-                               Type other;
-                               //
-                               // If either operand is of type ulong, the other operand is
-                               // converted to type ulong.  or an error ocurrs if the other
-                               // operand is of type sbyte, short, int or long
-                               //
-                               if (l == TypeManager.uint64_type){
-                                       if (r != TypeManager.uint64_type){
-                                               if (right is IntConstant){
-                                                       IntConstant ic = (IntConstant) right;
-                                                       
-                                                       e = Convert.TryImplicitIntConversion (l, ic);
-                                                       if (e != null)
-                                                               right = e;
-                                               } else if (right is LongConstant){
-                                                       long ll = ((LongConstant) right).Value;
-
-                                                       if (ll >= 0)
-                                                               right = new ULongConstant ((ulong) ll, right.Location);
-                                               } else {
-                                                       e = Convert.ImplicitNumericConversion (ec, right, l);
-                                                       if (e != null)
-                                                               right = e;
-                                               }
-                                       }
-                                       other = right.Type;
-                               } else {
-                                       if (left is IntConstant){
-                                               e = Convert.TryImplicitIntConversion (r, (IntConstant) left);
-                                               if (e != null)
-                                                       left = e;
-                                       } else if (left is LongConstant){
-                                               long ll = ((LongConstant) left).Value;
-                                               
-                                               if (ll > 0)
-                                                       left = new ULongConstant ((ulong) ll, right.Location);
-                                       } else {
-                                               e = Convert.ImplicitNumericConversion (ec, left, r);
-                                               if (e != null)
-                                                       left = e;
-                                       }
-                                       other = left.Type;
-                               }
-
-                               if ((other == TypeManager.sbyte_type) ||
-                                   (other == TypeManager.short_type) ||
-                                   (other == TypeManager.int32_type) ||
-                                   (other == TypeManager.int64_type))
-                                       Error_OperatorAmbiguous (loc, oper, l, r);
-                               else {
-                                       left = ForceConversion (ec, left, TypeManager.uint64_type);
-                                       right = ForceConversion (ec, right, TypeManager.uint64_type);
-                               }
-                               type = TypeManager.uint64_type;
-                       } else if (IsOfType (ec, l, r, TypeManager.int64_type, check_user_conv)){
-                               //
-                               // If either operand is of type long, the other operand is converted
-                               // to type long.
-                               //
-                               if (l != TypeManager.int64_type)
-                                       left = Convert.ImplicitConversion (ec, left, TypeManager.int64_type, loc);
-                               if (r != TypeManager.int64_type)
-                                       right = Convert.ImplicitConversion (ec, right, TypeManager.int64_type, loc);
-                               
-                               type = TypeManager.int64_type;
-                       } else if (IsOfType (ec, l, r, TypeManager.uint32_type, check_user_conv)){
-                               //
-                               // 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 (unless we have an int constant).
-                               //
-                               Type other = null;
-                               
-                               if (l == TypeManager.uint32_type){
-                                       if (right is IntConstant){
-                                               IntConstant ic = (IntConstant) right;
-                                               int val = ic.Value;
-                                               
-                                               if (val >= 0){
-                                                       right = new UIntConstant ((uint) val, ic.Location);
-                                                       type = l;
-                                                       
-                                                       return true;
-                                               }
-                                       }
-                                       other = r;
-                               } else if (r == TypeManager.uint32_type){
-                                       if (left is IntConstant){
-                                               IntConstant ic = (IntConstant) left;
-                                               int val = ic.Value;
-                                               
-                                               if (val >= 0){
-                                                       left = new UIntConstant ((uint) val, ic.Location);
-                                                       type = r;
-                                                       return true;
-                                               }
-                                       }
-                                       
-                                       other = l;
-                               }
-
-                               if ((other == TypeManager.sbyte_type) ||
-                                   (other == TypeManager.short_type) ||
-                                   (other == TypeManager.int32_type)){
-                                       left = ForceConversion (ec, left, TypeManager.int64_type);
-                                       right = ForceConversion (ec, right, TypeManager.int64_type);
-                                       type = TypeManager.int64_type;
-                               } else {
-                                       //
-                                       // if either operand is of type uint, the other
-                                       // operand is converd to type uint
-                                       //
-                                       left = ForceConversion (ec, left, TypeManager.uint32_type);
-                                       right = ForceConversion (ec, right, TypeManager.uint32_type);
-                                       type = TypeManager.uint32_type;
-                               } 
-                       } else if (l == TypeManager.decimal_type || r == TypeManager.decimal_type){
-                               if (l != TypeManager.decimal_type)
-                                       left = Convert.ImplicitConversion (ec, left, TypeManager.decimal_type, loc);
+               bool IsApplicable_String (EmitContext ec, Expression le, Expression re, Operator oper)
+               {
+                       bool l = Convert.ImplicitConversionExists (ec, le, TypeManager.string_type);
+                       bool r = Convert.ImplicitConversionExists (ec, re, TypeManager.string_type);
 
-                               if (r != TypeManager.decimal_type)
-                                       right = Convert.ImplicitConversion (ec, right, TypeManager.decimal_type, loc);
-                               type = TypeManager.decimal_type;
-                       } else {
-                               left = ForceConversion (ec, left, TypeManager.int32_type);
-                               right = ForceConversion (ec, right, TypeManager.int32_type);
+                       if (oper == Operator.Equality || oper == Operator.Inequality)
+                               return l && r;
+                       if (oper == Operator.Addition)
+                               return l || r;
+                       return false;
+               }
 
-                               bool strConv =
-                                       Convert.ImplicitConversionExists (ec, lexpr, TypeManager.string_type) &&
-                                       Convert.ImplicitConversionExists (ec, rexpr, TypeManager.string_type);
-                               if (strConv && left != null && right != null)
-                                       Error_OperatorAmbiguous (loc, oper, l, r);
+               bool OverloadResolve_PredefinedString (EmitContext ec, Operator oper)
+               {
+                       if (!IsApplicable_String (ec, left, right, oper))
+                               return false;
+                       Type t = TypeManager.string_type;
+                       if (Convert.ImplicitConversionExists (ec, left, t))
+                               left = ForceConversion (ec, left, t);
+                       if (Convert.ImplicitConversionExists (ec, right, t))
+                               right = ForceConversion (ec, right, t);
+                       type = t;
+                       return true;
+               }
 
-                               type = TypeManager.int32_type;
-                       }
+               bool OverloadResolve_PredefinedIntegral (EmitContext ec)
+               {
+                       return VerifyApplicable_Predefined (ec, TypeManager.int32_type) ||
+                               VerifyApplicable_Predefined (ec, TypeManager.uint32_type) ||
+                               VerifyApplicable_Predefined (ec, TypeManager.int64_type) ||
+                               VerifyApplicable_Predefined (ec, TypeManager.uint64_type) ||
+                               false;
+               }
 
-                       return (left != null) && (right != null);
+               bool OverloadResolve_PredefinedFloating (EmitContext ec)
+               {
+                       return VerifyApplicable_Predefined (ec, TypeManager.float_type) ||
+                               VerifyApplicable_Predefined (ec, TypeManager.double_type) ||
+                               false;
                }
 
                static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)
@@ -1744,7 +1614,8 @@ namespace Mono.CSharp {
                
                void Error_OperatorCannotBeApplied ()
                {
-                       Error_OperatorCannotBeApplied (Location, OperName (oper), left.GetSignatureForError (), right.GetSignatureForError ());
+                       Error_OperatorCannotBeApplied (Location, OperName (oper), TypeManager.CSharpName (left.Type),
+                               TypeManager.CSharpName(right.Type));
                }
 
                static bool is_unsigned (Type t)
@@ -1753,15 +1624,6 @@ namespace Mono.CSharp {
                                t == TypeManager.short_type || t == TypeManager.byte_type);
                }
 
-               static bool is_user_defined (Type t)
-               {
-                       if (t.IsSubclassOf (TypeManager.value_type) &&
-                           (!TypeManager.IsBuiltinType (t) || t == TypeManager.decimal_type))
-                               return true;
-                       else
-                               return false;
-               }
-
                Expression Make32or64 (EmitContext ec, Expression e)
                {
                        Type t= e.Type;
@@ -1786,34 +1648,17 @@ namespace Mono.CSharp {
                                        
                Expression CheckShiftArguments (EmitContext ec)
                {
-                       Expression e;
-
-                       e = ForceConversion (ec, right, TypeManager.int32_type);
-                       if (e == null){
+                       Expression new_left = Make32or64 (ec, left);
+                       Expression new_right = ForceConversion (ec, right, TypeManager.int32_type);
+                       if (new_left == null || new_right == null) {
                                Error_OperatorCannotBeApplied ();
                                return null;
                        }
-                       right = e;
-
-                       if (((e = Convert.ImplicitConversion (ec, left, TypeManager.int32_type, loc)) != null) ||
-                           ((e = Convert.ImplicitConversion (ec, left, TypeManager.uint32_type, loc)) != null) ||
-                           ((e = Convert.ImplicitConversion (ec, left, TypeManager.int64_type, loc)) != null) ||
-                           ((e = Convert.ImplicitConversion (ec, left, TypeManager.uint64_type, loc)) != null)){
-                               left = e;
-                               type = e.Type;
-
-                               if (type == TypeManager.int32_type || type == TypeManager.uint32_type){
-                                       right = new Binary (Binary.Operator.BitwiseAnd, right, new IntConstant (31, loc));
-                                       right = right.DoResolve (ec);
-                               } else {
-                                       right = new Binary (Binary.Operator.BitwiseAnd, right, new IntConstant (63, loc));
-                                       right = right.DoResolve (ec);
-                               }
-
-                               return this;
-                       }
-                       Error_OperatorCannotBeApplied ();
-                       return null;
+                       type = new_left.Type;
+                       int shiftmask = (type == TypeManager.int32_type || type == TypeManager.uint32_type) ? 31 : 63;
+                       left = new_left;
+                       right = new Binary (Binary.Operator.BitwiseAnd, new_right, new IntConstant (shiftmask, loc)).DoResolve (ec);
+                       return this;
                }
 
                //
@@ -1867,7 +1712,6 @@ namespace Mono.CSharp {
                                if ((l == TypeManager.null_type && EqualsNullIsReferenceEquals (r)) ||
                                    (r == TypeManager.null_type && EqualsNullIsReferenceEquals (l))) {
                                        Type = TypeManager.bool_type;
-                                       
                                        return this;
                                }
 
@@ -1884,12 +1728,12 @@ namespace Mono.CSharp {
                        // built-in types
                        //
                        Expression left_operators = null, right_operators = null;
-                       if (!(TypeManager.IsPrimitiveType (l) && TypeManager.IsPrimitiveType (r))){
+                       if (!(TypeManager.IsPrimitiveType (l) && TypeManager.IsPrimitiveType (r))) {
                                //
                                // Step 1: Perform Operator Overload location
                                //
                                string op = oper_names [(int) oper];
-                               
+
                                MethodGroupExpr union;
                                left_operators = MemberLookup (ec.ContainerType, l, op, MemberTypes.Method, AllBindingFlags, loc);
                                if (r != l){
@@ -1898,23 +1742,21 @@ namespace Mono.CSharp {
                                        union = Invocation.MakeUnionSet (left_operators, right_operators, loc);
                                } else
                                        union = (MethodGroupExpr) left_operators;
-                               
+
                                if (union != null) {
                                        ArrayList args = new ArrayList (2);
                                        args.Add (new Argument (left, Argument.AType.Expression));
                                        args.Add (new Argument (right, Argument.AType.Expression));
-                                       
-                                       MethodBase method = Invocation.OverloadResolve (
-                                               ec, union, args, true, Location.Null);
+
+                                       MethodBase method = Invocation.OverloadResolve (ec, union, args, true, Location.Null);
 
                                        if (method != null) {
                                                MethodInfo mi = (MethodInfo) method;
-                                               
                                                return new BinaryMethod (mi.ReturnType, method, args);
                                        }
                                }
                        }
-                       
+
                        //
                        // Step 0: String concatenation (because overloading will get this wrong)
                        //
@@ -1933,7 +1775,7 @@ namespace Mono.CSharp {
                                                Error_OperatorCannotBeApplied ();
                                                return null;
                                        }
-                                       
+
                                        // try to fold it in on the left
                                        if (left is StringConcat) {
 
@@ -1949,7 +1791,7 @@ namespace Mono.CSharp {
                                                        return left;
                                                }
                                        }
-                                       
+
                                        // Otherwise, start a new concat expression
                                        return new StringConcat (ec, loc, left, right).Resolve (ec);
                                }
@@ -1974,7 +1816,7 @@ namespace Mono.CSharp {
                                                Error_OperatorCannotBeApplied ();
                                                return null;
                                        }
-                                       
+
                                        type = TypeManager.bool_type;
                                        return this;
                                }
@@ -2030,9 +1872,9 @@ namespace Mono.CSharp {
                                        // Also, a standard conversion must exist from either one
                                        //
                                        bool left_to_right =
-                                               Convert.ImplicitStandardConversionExists (ec, left, r);
+                                               Convert.ImplicitStandardConversionExists (left, r);
                                        bool right_to_left = !left_to_right &&
-                                               Convert.ImplicitStandardConversionExists (ec, right, l);
+                                               Convert.ImplicitStandardConversionExists (right, l);
 
                                        if (!left_to_right && !right_to_left) {
                                                Error_OperatorCannotBeApplied ();
@@ -2069,19 +1911,8 @@ namespace Mono.CSharp {
                                        if (r != TypeManager.object_type)
                                                right = new EmptyCast (right, TypeManager.object_type);
 
-                                       //
-                                       // FIXME: CSC here catches errors cs254 and cs252
-                                       //
                                        return this;
                                }
-
-                               //
-                               // One of them is a valuetype, but the other one is not.
-                               //
-                               if (!l.IsValueType || !r.IsValueType) {
-                                       Error_OperatorCannotBeApplied ();
-                                       return null;
-                               }
                        }
 
                        // Only perform numeric promotions on:
@@ -2099,8 +1930,8 @@ namespace Mono.CSharp {
                                                        r = right.Type;
                                                }
                                        }
-                               
-                                       if (TypeManager.IsDelegateType (r)){
+
+                                       if (TypeManager.IsDelegateType (r) || right is NullLiteral){
                                                MethodInfo method;
                                                ArrayList args = new ArrayList (2);
                                        
@@ -2113,7 +1944,7 @@ namespace Mono.CSharp {
                                                else
                                                        method = TypeManager.delegate_remove_delegate_delegate;
 
-                                               if (!TypeManager.IsEqual (l, r)) {
+                                               if (!TypeManager.IsEqual (l, r) && !(right is NullLiteral)) {
                                                        Error_OperatorCannotBeApplied ();
                                                        return null;
                                                }
@@ -2271,18 +2102,27 @@ namespace Mono.CSharp {
                                return e.Resolve (ec);
                        } 
 
+                       Expression orig_left = left;
+                       Expression orig_right = right;
+
                        //
                        // operator & (bool x, bool y)
                        // operator | (bool x, bool y)
                        // operator ^ (bool x, bool y)
                        //
-                       if (l == TypeManager.bool_type && r == TypeManager.bool_type){
-                               if (oper == Operator.BitwiseAnd ||
-                                   oper == Operator.BitwiseOr ||
-                                   oper == Operator.ExclusiveOr){
-                                       type = l;
-                                       return this;
+                       if (oper == Operator.BitwiseAnd ||
+                           oper == Operator.BitwiseOr ||
+                           oper == Operator.ExclusiveOr) {
+                               if (OverloadResolve_PredefinedIntegral (ec)) {
+                                       if (IsConvertible (ec, orig_left, orig_right, TypeManager.bool_type)) {
+                                               Error_OperatorAmbiguous (loc, oper, l, r);
+                                               return null;
+                                       }
+                               } else if (!VerifyApplicable_Predefined (ec, TypeManager.bool_type)) {
+                                       Error_OperatorCannotBeApplied ();
+                                       return null;
                                }
+                               return this;
                        }
                        
                        //
@@ -2295,42 +2135,26 @@ namespace Mono.CSharp {
                                        return this;
                                }
                        }
-                       
-                       //
-                       // This will leave left or right set to null if there is an error
-                       //
-                       bool check_user_conv = is_user_defined (l) && is_user_defined (r);
-                       DoNumericPromotions (ec, l, r, left, right, check_user_conv);
-                       if (left == null || right == null){
-                               Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
-                               return null;
-                       }
 
-                       //
-                       // reload our cached types if required
-                       //
-                       l = left.Type;
-                       r = right.Type;
-                       
-                       if (oper == Operator.BitwiseAnd ||
-                           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))){
-                                               type = l;
-                                       } else {
-                                               Error_OperatorCannotBeApplied ();
-                                               return null;
-                                       }
-                               } else {
-                                       Error_OperatorCannotBeApplied ();
+                       if (OverloadResolve_PredefinedIntegral (ec)) {
+                               if (IsApplicable_String (ec, orig_left, orig_right, oper)) {
+                                       Error_OperatorAmbiguous (loc, oper, l, r);
+                                       return null;
+                               }
+                       } else if (OverloadResolve_PredefinedFloating (ec)) {
+                               if (IsConvertible (ec, orig_left, orig_right, TypeManager.decimal_type) ||
+                                   IsApplicable_String (ec, orig_left, orig_right, oper)) {
+                                       Error_OperatorAmbiguous (loc, oper, l, r);
                                        return null;
                                }
+                       } else if (VerifyApplicable_Predefined (ec, TypeManager.decimal_type)) {
+                               if (IsApplicable_String (ec, orig_left, orig_right, oper)) {
+                                       Error_OperatorAmbiguous (loc, oper, l, r);
+                                       return null;
+                               }
+                       } else if (!OverloadResolve_PredefinedString (ec, oper)) {
+                               Error_OperatorCannotBeApplied ();
+                               return null;
                        }
 
                        if (oper == Operator.Equality ||
@@ -2338,14 +2162,30 @@ namespace Mono.CSharp {
                            oper == Operator.LessThanOrEqual ||
                            oper == Operator.LessThan ||
                            oper == Operator.GreaterThanOrEqual ||
-                           oper == Operator.GreaterThan){
+                           oper == Operator.GreaterThan)
                                type = TypeManager.bool_type;
+
+                       l = left.Type;
+                       r = right.Type;
+
+                       if (l == TypeManager.decimal_type || l == TypeManager.string_type || r == TypeManager.string_type) {
+                               Type lookup = l;
+                               if (r == TypeManager.string_type)
+                                       lookup = r;
+                               MethodGroupExpr ops = (MethodGroupExpr) MemberLookup (
+                                       ec.ContainerType, lookup, oper_names [(int) oper],
+                                       MemberTypes.Method, AllBindingFlags, loc);
+                               ArrayList args = new ArrayList (2);
+                               args.Add (new Argument (left, Argument.AType.Expression));
+                               args.Add (new Argument (right, Argument.AType.Expression));
+                               MethodBase method = Invocation.OverloadResolve (ec, ops, args, true, Location.Null);
+                               return new BinaryMethod (type, method, args);
                        }
 
                        return this;
                }
 
-               Constant EnumLiftUp (EmitContext ec, Constant left, Constant right)
+               Constant EnumLiftUp (Constant left, Constant right)
                {
                        switch (oper) {
                                case Operator.BitwiseOr:
@@ -2422,11 +2262,11 @@ namespace Mono.CSharp {
 
                        // The conversion rules are ignored in enum context but why
                        if (!ec.InEnumContext && lc != null && rc != null && (TypeManager.IsEnumType (left.Type) || TypeManager.IsEnumType (right.Type))) {
-                               left = lc = EnumLiftUp (ec, lc, rc);
+                               left = lc = EnumLiftUp (lc, rc);
                                if (lc == null)
                                        return null;
 
-                               right = rc = EnumLiftUp (ec, rc, lc);
+                               right = rc = EnumLiftUp (rc, lc);
                                if (rc == null)
                                        return null;
                        }
@@ -2466,7 +2306,11 @@ namespace Mono.CSharp {
                                        return e;
                        }
 
-                       if (TypeManager.IsNullableType (left.Type) || TypeManager.IsNullableType (right.Type))
+                       Type ltype = left.Type, rtype = right.Type;
+                       if ((left is NullLiteral || ltype.IsValueType) &&
+                           (right is NullLiteral || rtype.IsValueType) &&
+                           !(left is NullLiteral && right is NullLiteral) &&
+                           (TypeManager.IsNullableType (ltype) || TypeManager.IsNullableType (rtype)))
                                return new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
 
                        // Comparison warnings
@@ -2483,6 +2327,11 @@ namespace Mono.CSharp {
                        return ResolveOperator (ec);
                }
 
+               public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
+               {
+                       return null;
+               }
+
                private void CheckUselessComparison (Constant c, Type type)
                {
                        if (c == null || !IsTypeIntegral (type)
@@ -2982,11 +2831,21 @@ namespace Mono.CSharp {
                        //
                        // 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, last_operand.Location);
-                                       return;
+                       StringConstant sc = operand as StringConstant;
+                       if (sc != null) {
+// TODO: it will be better to do this silently as an optimalization
+// int i = 0;
+// string s = "" + i;
+// because this code has poor performace
+//                             if (sc.Value.Length == 0)
+//                                     Report.Warning (-300, 3, Location, "Appending an empty string has no effect. Did you intend to append a space string?");
+
+                               if (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, last_operand.Location);
+                                               return;
+                                       }
                                }
                        }
                        
@@ -3165,7 +3024,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       left_temp = new LocalTemporary (ec, type);
+                       left_temp = new LocalTemporary (type);
 
                        ArrayList arguments = new ArrayList ();
                        arguments.Add (new Argument (left_temp, Argument.AType.Expression));
@@ -3211,6 +3070,9 @@ namespace Mono.CSharp {
                        ig.MarkLabel (false_target);
                        op.Emit (ec);
                        ig.MarkLabel (end_target);
+
+                       // We release 'left_temp' here since 'op' may refer to it too
+                       left_temp.Release (ec);
                }
        }
 
@@ -3349,7 +3211,7 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return null;
 
-                       if (TypeManager.IsNullableType (expr.Type))
+                       if (TypeManager.IsNullableValueType (expr.Type))
                                return new Nullable.LiftedConditional (expr, trueExpr, falseExpr, loc).Resolve (ec);
                        
                        if (expr.Type != TypeManager.bool_type){
@@ -3419,6 +3281,11 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
+               {
+                       return null;
+               }
+
                public override void Emit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
@@ -3435,128 +3302,227 @@ namespace Mono.CSharp {
 
        }
 
-       /// <summary>
-       ///   Local variables
-       /// </summary>
-       public class LocalVariableReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
-               public readonly string Name;
-               public readonly Block Block;
-               public LocalInfo local_info;
-               bool is_readonly;
+       public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation {
                bool prepared;
                LocalTemporary temp;
-               
-               public LocalVariableReference (Block block, string name, Location l)
-               {
-                       Block = block;
-                       Name = name;
-                       loc = l;
-                       eclass = ExprClass.Variable;
-               }
 
-               //
-               // Setting `is_readonly' to false will allow you to create a writable
-               // reference to a read-only variable.  This is used by foreach and using.
-               //
-               public LocalVariableReference (Block block, string name, Location l,
-                                              LocalInfo local_info, bool is_readonly)
-                       : this (block, name, l)
-               {
-                       this.local_info = local_info;
-                       this.is_readonly = is_readonly;
+               public abstract Variable Variable {
+                       get;
                }
 
-               public VariableInfo VariableInfo {
-                       get {
-                               return local_info.VariableInfo;
-                       }
+               public abstract bool IsRef {
+                       get;
                }
 
-               public bool IsReadOnly {
-                       get {
-                               return is_readonly;
-                       }
+               public override void Emit (EmitContext ec)
+               {
+                       Emit (ec, false);
                }
 
-               public bool VerifyAssigned (EmitContext ec)
+               //
+               // This method is used by parameters that are references, that are
+               // being passed as references:  we only want to pass the pointer (that
+               // is already stored in the parameter, not the address of the pointer,
+               // and not the value of the variable).
+               //
+               public void EmitLoad (EmitContext ec)
+               {
+                       Report.Debug (64, "VARIABLE EMIT LOAD", this, Variable, type, loc);
+                       if (!prepared)
+                               Variable.EmitInstance (ec);
+                       Variable.Emit (ec);
+               }
+               
+               public void Emit (EmitContext ec, bool leave_copy)
+               {
+                       Report.Debug (64, "VARIABLE EMIT", this, Variable, type, IsRef, loc);
+
+                       EmitLoad (ec);
+
+                       if (IsRef) {
+                               if (prepared)
+                                       ec.ig.Emit (OpCodes.Dup);
+       
+                               //
+                               // If we are a reference, we loaded on the stack a pointer
+                               // Now lets load the real value
+                               //
+                               LoadFromPtr (ec.ig, type);
+                       }
+
+                       if (leave_copy) {
+                               ec.ig.Emit (OpCodes.Dup);
+
+                               if (IsRef || Variable.NeedsTemporary) {
+                                       temp = new LocalTemporary (Type);
+                                       temp.Store (ec);
+                               }
+                       }
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
+                                       bool prepare_for_load)
+               {
+                       Report.Debug (64, "VARIABLE EMIT ASSIGN", this, Variable, type, IsRef,
+                                     source, loc);
+
+                       ILGenerator ig = ec.ig;
+                       prepared = prepare_for_load;
+
+                       Variable.EmitInstance (ec);
+                       if (prepare_for_load && Variable.HasInstance)
+                               ig.Emit (OpCodes.Dup);
+                       else if (IsRef && !prepared)
+                               Variable.Emit (ec);
+
+                       source.Emit (ec);
+
+                       if (leave_copy) {
+                               ig.Emit (OpCodes.Dup);
+                               if (IsRef || Variable.NeedsTemporary) {
+                                       temp = new LocalTemporary (Type);
+                                       temp.Store (ec);
+                               }
+                       }
+
+                       if (IsRef)
+                               StoreFromPtr (ig, type);
+                       else
+                               Variable.EmitAssign (ec);
+
+                       if (temp != null) {
+                               temp.Emit (ec);
+                               temp.Release (ec);
+                       }
+               }
+               
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       Variable.EmitInstance (ec);
+                       Variable.EmitAddressOf (ec);
+               }
+       }
+
+       /// <summary>
+       ///   Local variables
+       /// </summary>
+       public class LocalVariableReference : VariableReference, IVariable {
+               public readonly string Name;
+               public readonly Block Block;
+               public LocalInfo local_info;
+               bool is_readonly;
+               Variable variable;
+
+               public LocalVariableReference (Block block, string name, Location l)
+               {
+                       Block = block;
+                       Name = name;
+                       loc = l;
+                       eclass = ExprClass.Variable;
+               }
+
+               //
+               // Setting `is_readonly' to false will allow you to create a writable
+               // reference to a read-only variable.  This is used by foreach and using.
+               //
+               public LocalVariableReference (Block block, string name, Location l,
+                                              LocalInfo local_info, bool is_readonly)
+                       : this (block, name, l)
+               {
+                       this.local_info = local_info;
+                       this.is_readonly = is_readonly;
+               }
+
+               public VariableInfo VariableInfo {
+                       get { return local_info.VariableInfo; }
+               }
+
+               public override bool IsRef {
+                       get { return false; }
+               }
+
+               public bool IsReadOnly {
+                       get { return is_readonly; }
+               }
+
+               public bool VerifyAssigned (EmitContext ec)
                {
                        VariableInfo variable_info = local_info.VariableInfo;
                        return variable_info == null || variable_info.IsAssigned (ec, loc);
                }
 
-               protected Expression DoResolveBase (EmitContext ec, Expression lvalue_right_side)
+               void ResolveLocalInfo ()
                {
                        if (local_info == null) {
                                local_info = Block.GetLocalInfo (Name);
-
-                               // is out param
-                               if (lvalue_right_side == EmptyExpression.OutAccess)
-                                       local_info.Used = true;
-
                                is_readonly = local_info.ReadOnly;
                        }
+               }
 
+               protected Expression DoResolveBase (EmitContext ec)
+               {
                        type = local_info.VariableType;
 
-                       VariableInfo variable_info = local_info.VariableInfo;
-                       if (lvalue_right_side != null){
-                               if (is_readonly){
-                                       if (lvalue_right_side is LocalVariableReference || lvalue_right_side == EmptyExpression.OutAccess)
-                                               Report.Error (1657, loc, "Cannot pass `{0}' as a ref or out argument because it is a `{1}'",
-                                                       Name, local_info.GetReadOnlyContext ());
-                                       else if (lvalue_right_side == EmptyExpression.LValueMemberAccess)
-                                               Report.Error (1654, loc, "Cannot assign to members of `{0}' because it is a `{1}'",
-                                                       Name, local_info.GetReadOnlyContext ());
-                                       else
-                                               Report.Error (1656, loc, "Cannot assign to `{0}' because it is a `{1}'",
-                                                       Name, local_info.GetReadOnlyContext ());
-                                       return null;
-                               }
-                               
-                               if (variable_info != null)
-                                       variable_info.SetAssigned (ec);
-                       }
-               
                        Expression e = Block.GetConstantExpression (Name);
-                       if (e != null) {
-                               local_info.Used = true;
-                               eclass = ExprClass.Value;
+                       if (e != null)
                                return e.Resolve (ec);
-                       }
 
                        if (!VerifyAssigned (ec))
                                return null;
 
-                       if (lvalue_right_side == null)
-                               local_info.Used = true;
-
-                       if (ec.CurrentAnonymousMethod != null){
-                               //
-                               // If we are referencing a variable from the external block
-                               // flag it for capturing
-                               //
-                               if ((local_info.Block.Toplevel != ec.CurrentBlock.Toplevel) ||
-                                   ec.CurrentAnonymousMethod.IsIterator)
-                               {
-                                       if (local_info.AddressTaken){
-                                               AnonymousMethod.Error_AddressOfCapturedVar (local_info.Name, loc);
-                                               return null;
-                                       }
-                                       ec.CaptureVariable (local_info);
+                       //
+                       // If we are referencing a variable from the external block
+                       // flag it for capturing
+                       //
+                       if (ec.MustCaptureVariable (local_info)) {
+                               if (local_info.AddressTaken){
+                                       AnonymousMethod.Error_AddressOfCapturedVar (local_info.Name, loc);
+                                       return null;
                                }
+
+                               ScopeInfo scope = local_info.Block.CreateScopeInfo ();
+                               variable = scope.AddLocal (local_info);
+                               type = variable.Type;
                        }
 
                        return this;
                }
-               
+
                public override Expression DoResolve (EmitContext ec)
                {
-                       return DoResolveBase (ec, null);
+                       ResolveLocalInfo ();
+                       local_info.Used = true;
+                       return DoResolveBase (ec);
                }
 
                override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
-                       return DoResolveBase (ec, right_side);
+                       ResolveLocalInfo ();
+
+                       if (is_readonly) {
+                               int code;
+                               string msg;
+                               if (right_side == EmptyExpression.OutAccess) {
+                                       code = 1657; msg = "Cannot pass `{0}' as a ref or out argument because it is a `{1}'";
+                               } else if (right_side == EmptyExpression.LValueMemberAccess) {
+                                       code = 1654; msg = "Cannot assign to members of `{0}' because it is a `{1}'";
+                               } else if (right_side == EmptyExpression.LValueMemberOutAccess) {
+                                       code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'";
+                               } else {
+                                       code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'";
+                               }
+                               Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ());
+                               return null;
+                       }
+
+                       // is out param
+                       if (right_side == EmptyExpression.OutAccess)
+                               local_info.Used = true;
+
+                       if (VariableInfo != null)
+                               VariableInfo.SetAssigned (ec);
+
+                       return DoResolveBase (ec);
                }
 
                public bool VerifyFixed ()
@@ -3565,7 +3531,7 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public override int GetHashCode()
+               public override int GetHashCode ()
                {
                        return Name.GetHashCode ();
                }
@@ -3579,90 +3545,8 @@ namespace Mono.CSharp {
                        return Name == lvr.Name && Block == lvr.Block;
                }
 
-               public override void Emit (EmitContext ec)
-               {
-                       ILGenerator ig = ec.ig;
-
-                       if (local_info.FieldBuilder == null){
-                               //
-                               // A local variable on the local CLR stack
-                               //
-                               ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
-                       } else {
-                               //
-                               // A local variable captured by anonymous methods.
-                               //
-                               if (!prepared)
-                                       ec.EmitCapturedVariableInstance (local_info);
-                               
-                               ig.Emit (OpCodes.Ldfld, local_info.FieldBuilder);
-                       }
-               }
-               
-               public void Emit (EmitContext ec, bool leave_copy)
-               {
-                       Emit (ec);
-                       if (leave_copy){
-                               ec.ig.Emit (OpCodes.Dup);
-                               if (local_info.FieldBuilder != null){
-                                       temp = new LocalTemporary (ec, Type);
-                                       temp.Store (ec);
-                               }
-                       }
-               }
-               
-               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
-               {
-                       ILGenerator ig = ec.ig;
-                       prepared = prepare_for_load;
-
-                       if (local_info.FieldBuilder == null){
-                               //
-                               // A local variable on the local CLR stack
-                               //
-                               if (local_info.LocalBuilder == null)
-                                       throw new Exception ("This should not happen: both Field and Local are null");
-
-                               source.Emit (ec);
-                               if (leave_copy)
-                                       ec.ig.Emit (OpCodes.Dup);
-                               ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
-                       } else {
-                               //
-                               // A local variable captured by anonymous methods or itereators.
-                               //
-                               ec.EmitCapturedVariableInstance (local_info);
-
-                               if (prepare_for_load)
-                                       ig.Emit (OpCodes.Dup);
-                               source.Emit (ec);
-                               if (leave_copy){
-                                       ig.Emit (OpCodes.Dup);
-                                       temp = new LocalTemporary (ec, Type);
-                                       temp.Store (ec);
-                               }
-                               ig.Emit (OpCodes.Stfld, local_info.FieldBuilder);
-                               if (temp != null)
-                                       temp.Emit (ec);
-                       }
-               }
-               
-               public void AddressOf (EmitContext ec, AddressOp mode)
-               {
-                       ILGenerator ig = ec.ig;
-
-                       if (local_info.FieldBuilder == null){
-                               //
-                               // A local variable on the local CLR stack
-                               //
-                               ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
-                       } else {
-                               //
-                               // A local variable captured by anonymous methods or iterators
-                               //
-                               ec.EmitCapturedVariableInstance (local_info);
-                               ig.Emit (OpCodes.Ldflda, local_info.FieldBuilder);
-                       }
+               public override Variable Variable {
+                       get { return variable != null ? variable : local_info.Variable; }
                }
 
                public override string ToString ()
@@ -3675,13 +3559,13 @@ namespace Mono.CSharp {
        ///   This represents a reference to a parameter in the intermediate
        ///   representation.
        /// </summary>
-       public class ParameterReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
+       public class ParameterReference : VariableReference, IVariable {
                Parameter par;
                string name;
                int idx;
                Block block;
                VariableInfo vi;
-               public bool is_ref, is_out, prepared;
+               public bool is_ref, is_out;
 
                public bool IsOut {
                        get {
@@ -3689,13 +3573,25 @@ namespace Mono.CSharp {
                        }
                }
 
-               public bool IsRef {
+               public override bool IsRef {
                        get {
                                return is_ref;
                        }
                }
 
-               LocalTemporary temp;
+               public string Name {
+                       get {
+                               return name;
+                       }
+               }
+
+               public Parameter Parameter {
+                       get {
+                               return par;
+                       }
+               }
+
+               Variable variable;
                
                public ParameterReference (Parameter par, Block block, int idx, Location loc)
                {
@@ -3711,6 +3607,10 @@ namespace Mono.CSharp {
                        get { return vi; }
                }
 
+               public override Variable Variable {
+                       get { return variable != null ? variable : par.Variable; }
+               }
+
                public bool VerifyFixed ()
                {
                        // A parameter is fixed if it's a value parameter (i.e., no modifier like out, ref, param).
@@ -3764,23 +3664,33 @@ namespace Mono.CSharp {
                        if (is_out)
                                vi = block.ParameterMap [idx];
 
-                       if (ec.CurrentAnonymousMethod != null){
-                               if (is_ref && !block.Toplevel.IsLocalParameter (name)){
-                                       Report.Error (1628, Location, "Cannot use ref or out parameter `{0}' inside an anonymous method block",
-                                               par.Name);
-                                       return false;
-                               }
+                       AnonymousContainer am = ec.CurrentAnonymousMethod;
+                       if (am == null)
+                               return true;
 
-                               //
-                               // If we are referencing the parameter from the external block
-                               // flag it for capturing
-                               //
-                               //Console.WriteLine ("Is parameter `{0}' local? {1}", name, block.IsLocalParameter (name));
-                               if (!block.Toplevel.IsLocalParameter (name)){
-                                       ec.CaptureParameter (name, type, idx);
+                       if (is_ref && !block.Toplevel.IsLocalParameter (name)){
+                               Report.Error (1628, Location,
+                                             "Cannot use ref or out parameter `{0}' inside an " +
+                                             "anonymous method block", par.Name);
+                               return false;
+                       }
+
+                       if (!am.IsIterator && block.Toplevel.IsLocalParameter (name))
+                               return true;
+
+                       AnonymousMethodHost host = null;
+                       ToplevelBlock toplevel = block.Toplevel;
+                       while (toplevel != null) {
+                               if (toplevel.IsLocalParameter (name)) {
+                                       host = toplevel.AnonymousMethodHost;
+                                       break;
                                }
+
+                               toplevel = toplevel.Container;
                        }
 
+                       variable = host.AddParameter (par, idx);
+                       type = variable.Type;
                        return true;
                }
 
@@ -3815,7 +3725,8 @@ namespace Mono.CSharp {
                        if (!DoResolveBase (ec))
                                return null;
 
-                       if (is_out && ec.DoFlowAnalysis && (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
+                       if (is_out && ec.DoFlowAnalysis &&
+                           (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
                                return null;
 
                        return this;
@@ -3845,135 +3756,6 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Ldarg, x);
                }
                
-               //
-               // This method is used by parameters that are references, that are
-               // being passed as references:  we only want to pass the pointer (that
-               // is already stored in the parameter, not the address of the pointer,
-               // and not the value of the variable).
-               //
-               public void EmitLoad (EmitContext ec)
-               {
-                       ILGenerator ig = ec.ig;
-                       int arg_idx = idx;
-
-                       if (!ec.MethodIsStatic)
-                               arg_idx++;
-                       
-                       EmitLdArg (ig, arg_idx);
-
-                       //
-                       // FIXME: Review for anonymous methods
-                       //
-               }
-               
-               public override void Emit (EmitContext ec)
-               {
-                       Emit (ec, false);
-               }
-               
-               public void Emit (EmitContext ec, bool leave_copy)
-               {
-                       ILGenerator ig = ec.ig;
-                       int arg_idx = idx;
-
-                       if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){                               
-                               ec.EmitParameter (name, leave_copy, prepared, ref temp);
-                               return;
-                       }
-
-                       if (!ec.MethodIsStatic)
-                               arg_idx++;
-
-                       EmitLdArg (ig, arg_idx);
-
-                       if (is_ref) {
-                               if (prepared)
-                                       ec.ig.Emit (OpCodes.Dup);
-       
-                               //
-                               // If we are a reference, we loaded on the stack a pointer
-                               // Now lets load the real value
-                               //
-                               LoadFromPtr (ig, type);
-                       }
-                       
-                       if (leave_copy) {
-                               ec.ig.Emit (OpCodes.Dup);
-                               
-                               if (is_ref) {
-                                       temp = new LocalTemporary (ec, type);
-                                       temp.Store (ec);
-                               }
-                       }
-               }
-               
-               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
-               {
-                       prepared = prepare_for_load;
-                       if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
-                               ec.EmitAssignParameter (name, source, leave_copy, prepare_for_load, ref temp);
-                               return;
-                       }
-
-                       ILGenerator ig = ec.ig;
-                       int arg_idx = idx;
-                       
-                       
-                       
-                       if (!ec.MethodIsStatic)
-                               arg_idx++;
-
-                       if (is_ref && !prepared)
-                               EmitLdArg (ig, arg_idx);
-                       
-                       source.Emit (ec);
-
-                       if (leave_copy)
-                               ec.ig.Emit (OpCodes.Dup);
-                       
-                       if (is_ref) {
-                               if (leave_copy) {
-                                       temp = new LocalTemporary (ec, type);
-                                       temp.Store (ec);
-                               }
-                               
-                               StoreFromPtr (ig, type);
-                               
-                               if (temp != null)
-                                       temp.Emit (ec);
-                       } else {
-                               if (arg_idx <= 255)
-                                       ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
-                               else
-                                       ig.Emit (OpCodes.Starg, arg_idx);
-                       }
-               }
-
-               public void AddressOf (EmitContext ec, AddressOp mode)
-               {
-                       if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
-                               ec.EmitAddressOfParameter (name);
-                               return;
-                       }
-                       
-                       int arg_idx = idx;
-
-                       if (!ec.MethodIsStatic)
-                               arg_idx++;
-
-                       if (is_ref){
-                               if (arg_idx <= 255)
-                                       ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
-                               else
-                                       ec.ig.Emit (OpCodes.Ldarg, arg_idx);
-                       } else {
-                               if (arg_idx <= 255)
-                                       ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
-                               else
-                                       ec.ig.Emit (OpCodes.Ldarga, arg_idx);
-                       }
-               }
-
                public override string ToString ()
                {
                        return "ParameterReference[" + name + "]";
@@ -4041,7 +3823,7 @@ namespace Mono.CSharp {
                                TypeManager.CSharpName (a.Expr.Type);
                }
 
-               public bool ResolveMethodGroup (EmitContext ec, Location loc)
+               public bool ResolveMethodGroup (EmitContext ec)
                {
                        SimpleName sn = Expr as SimpleName;
                        if (sn != null)
@@ -4055,106 +3837,44 @@ namespace Mono.CSharp {
 
                        return true;
                }
-               
-               void Error_LValueRequired (Location loc)
-               {
-                       Report.Error (1510, loc, "A ref or out argument must be an assignable variable");
-               }
 
                public bool Resolve (EmitContext ec, Location loc)
                {
-                       bool old_do_flow_analysis = ec.DoFlowAnalysis;
-                       ec.DoFlowAnalysis = true;
-
-                       if (ArgType == AType.Ref) {
-                               ec.InRefOutArgumentResolving = true;
-                               Expr = Expr.Resolve (ec);
-                               ec.InRefOutArgumentResolving = false;
-                               if (Expr == null) {
-                                       ec.DoFlowAnalysis = old_do_flow_analysis;
-                                       return false;
-                               }
-
-                               int errors = Report.Errors;
-                               Expr = Expr.DoResolveLValue (ec, Expr);
-                               if (Expr == null && errors == Report.Errors)
-                                       Error_LValueRequired (loc);
-                       } else if (ArgType == AType.Out) {
-                               int errors = Report.Errors;
-                               ec.InRefOutArgumentResolving = true;
-                               Expr = Expr.DoResolveLValue (ec, EmptyExpression.OutAccess);
-                               ec.InRefOutArgumentResolving = false;
-
-                               if (Expr == null && errors == Report.Errors)
-                                       Error_LValueRequired (loc);
-                       }
-                       else
-                               Expr = Expr.Resolve (ec);
+                       using (ec.With (EmitContext.Flags.DoFlowAnalysis, true)) {
+                               // Verify that the argument is readable
+                               if (ArgType != AType.Out)
+                                       Expr = Expr.Resolve (ec);
 
-                       ec.DoFlowAnalysis = old_do_flow_analysis;
+                               // Verify that the argument is writeable
+                               if (Expr != null && (ArgType == AType.Out || ArgType == AType.Ref))
+                                       Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess, loc);
 
-                       if (Expr == null)
-                               return false;
-
-                       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.SymbolRelatedToPreviousError (fe.InstanceExpression.Type);
-                                                       Report.Warning (197, 1, loc,
-                                                               "Passing `{0}' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class",
-                                                               fe.GetSignatureForError ());
-                                                       return false;
-                                               }
-                                       }
-                               }
+                               return Expr != null;
                        }
-                               
-                       return true;
                }
 
                public void Emit (EmitContext ec)
                {
-                       //
-                       // Ref and Out parameters need to have their addresses taken.
+                       if (ArgType != AType.Ref && ArgType != AType.Out) {
+                               Expr.Emit (ec);
+                               return;
+                       }
+
+                       AddressOp mode = AddressOp.Store;
+                       if (ArgType == AType.Ref)
+                               mode |= AddressOp.Load;
+                               
+                       IMemoryLocation ml = (IMemoryLocation) Expr;
+                       ParameterReference pr = ml as ParameterReference;
+
                        //
                        // ParameterReferences might already be references, so we want
                        // to pass just the value
                        //
-                       if (ArgType == AType.Ref || ArgType == AType.Out){
-                               AddressOp mode = AddressOp.Store;
-
-                               if (ArgType == AType.Ref)
-                                       mode |= AddressOp.Load;
-                               
-                               if (Expr is ParameterReference){
-                                       ParameterReference pr = (ParameterReference) Expr;
-
-                                       if (pr.IsRef)
-                                               pr.EmitLoad (ec);
-                                       else {
-                                               
-                                               pr.AddressOf (ec, mode);
-                                       }
-                               } else {
-                                       if (Expr is IMemoryLocation)
-                                               ((IMemoryLocation) Expr).AddressOf (ec, mode);
-                                       else {
-                                               Error_LValueRequired (Expr.Location);
-                                               return;
-                                       }
-                               }
-                       } else
-                               Expr.Emit (ec);
+                       if (pr != null && pr.IsRef)
+                               pr.EmitLoad (ec);
+                       else
+                               ml.AddressOf (ec, mode);
                }
        }
 
@@ -4194,7 +3914,7 @@ namespace Mono.CSharp {
                ///              q    if a->q is better,
                ///              null if neither is better
                /// </summary>
-               static Type BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc)
+               static Type BetterConversion (EmitContext ec, Argument a, Type p, Type q)
                {
                        Type argument_type = TypeManager.TypeToCoreType (a.Type);
                        Expression argument_expr = a.Expr;
@@ -4294,7 +4014,15 @@ namespace Mono.CSharp {
                        if (!p.IsGenericParameter && q.IsGenericParameter)
                                return p;
 
-                       if (p.IsGenericType) {
+                       if (TypeManager.HasElementType (p)) {
+                               Type pe = TypeManager.GetElementType (p);
+                               Type qe = TypeManager.GetElementType (q);
+                               Type specific = MoreSpecific (pe, qe);
+                               if (specific == pe)
+                                       return p;
+                               if (specific == qe)
+                                       return q;
+                       } else if (p.IsGenericType) {
                                Type[] pargs = TypeManager.GetTypeArguments (p);
                                Type[] qargs = TypeManager.GetTypeArguments (q);
 
@@ -4313,14 +4041,6 @@ namespace Mono.CSharp {
                                        return p;
                                if (!p_specific_at_least_once && q_specific_at_least_once)
                                        return q;
-                       } else if (TypeManager.HasElementType (p)) {
-                               Type pe = TypeManager.GetElementType (p);
-                               Type qe = TypeManager.GetElementType (q);
-                               Type specific = MoreSpecific (pe, qe);
-                               if (specific == pe)
-                                       return p;
-                               if (specific == qe)
-                                       return q;
                        }
 
                        return null;
@@ -4337,7 +4057,7 @@ namespace Mono.CSharp {
                /// </remarks>
                static bool BetterFunction (EmitContext ec, ArrayList args, int argument_count,
                                            MethodBase candidate, bool candidate_params,
-                                           MethodBase best, bool best_params, Location loc)
+                                           MethodBase best, bool best_params)
                {
                        ParameterData candidate_pd = TypeManager.GetParameterData (candidate);
                        ParameterData best_pd = TypeManager.GetParameterData (best);
@@ -4362,7 +4082,7 @@ namespace Mono.CSharp {
                                        continue;
 
                                same = false;
-                               Type better = BetterConversion (ec, a, ct, bt, loc);
+                               Type better = BetterConversion (ec, a, ct, bt);
 
                                // for each argument, the conversion to 'ct' should be no worse than 
                                // the conversion to 'bt'.
@@ -4557,6 +4277,9 @@ namespace Mono.CSharp {
                            !TypeManager.InferParamsTypeArguments (ec, arguments, ref candidate))
                                return false;
 
+                       if (TypeManager.IsGenericMethodDefinition (candidate))
+                               throw new InternalErrorException ("a generic method definition took part in overload resolution");
+
                        return IsParamsMethodApplicable (
                                ec, arguments, arg_count, candidate, do_varargs);
                }
@@ -4653,9 +4376,12 @@ namespace Mono.CSharp {
                                                 ref MethodBase candidate)
                {
                        if (!me.HasTypeArguments &&
-                           !TypeManager.InferTypeArguments (ec, arguments, ref candidate))
+                           !TypeManager.InferTypeArguments (arguments, ref candidate))
                                return false;
 
+                       if (TypeManager.IsGenericMethodDefinition (candidate))
+                               throw new InternalErrorException ("a generic method definition took part in overload resolution");
+
                        return IsApplicable (ec, arguments, arg_count, candidate);
                }
 
@@ -4771,11 +4497,17 @@ namespace Mono.CSharp {
                                int j = 0;
                                for (int i = 0; i < methods.Length; ++i) {
                                        MethodBase m = methods [i];
+                                       Type [] gen_args = m.IsGenericMethod && !m.IsGenericMethodDefinition ? m.GetGenericArguments () : null;
                                        if (TypeManager.IsOverride (m)) {
                                                if (candidate_overrides == null)
                                                        candidate_overrides = new ArrayList ();
                                                candidate_overrides.Add (m);
                                                m = TypeManager.TryGetBaseDefinition (m);
+                                               if (m != null && gen_args != null) {
+                                                       if (!m.IsGenericMethodDefinition)
+                                                               throw new InternalErrorException ("GetBaseDefinition didn't return a GenericMethodDefinition");
+                                                       m = ((MethodInfo) m).MakeGenericMethod (gen_args);
+                                               }
                                        }
                                        if (m != null)
                                                methods [j++] = m;
@@ -4846,7 +4578,10 @@ namespace Mono.CSharp {
                                        if (pd.Count != arg_count)
                                                continue;
 
-                                       if (!TypeManager.InferTypeArguments (ec, Arguments, ref c))
+                                       if (!TypeManager.InferTypeArguments (Arguments, ref c))
+                                               continue;
+
+                                       if (TypeManager.IsGenericMethodDefinition (c))
                                                continue;
 
                                        VerifyArgumentsCompat (ec, Arguments, arg_count,
@@ -4872,7 +4607,7 @@ namespace Mono.CSharp {
                                                if (pd.Count != arg_count)
                                                        continue;
 
-                                               if (TypeManager.InferTypeArguments (ec, Arguments, ref c))
+                                               if (TypeManager.InferTypeArguments (Arguments, ref c))
                                                        continue;
 
                                                Report.Error (
@@ -4956,7 +4691,7 @@ namespace Mono.CSharp {
 
                                if (BetterFunction (ec, Arguments, arg_count, 
                                                    candidate, cand_params,
-                                                   method, method_params, loc)) {
+                                                   method, method_params)) {
                                        method = candidate;
                                        method_params = cand_params;
                                }
@@ -4975,8 +4710,7 @@ namespace Mono.CSharp {
                                 bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
                                if (!BetterFunction (ec, Arguments, arg_count,
                                                     method, method_params,
-                                                    candidate, cand_params,
-                                                    loc)) {
+                                                    candidate, cand_params)) {
                                        Report.SymbolRelatedToPreviousError (candidate);
                                        ambiguous = candidate;
                                }
@@ -5074,85 +4808,54 @@ namespace Mono.CSharp {
                                                          Location loc)
                {
                        ParameterData pd = TypeManager.GetParameterData (method);
-                       int pd_count = pd.Count;
-                       
-                       for (int j = 0; j < arg_count; j++) {
+                       int j;
+                       for (j = 0; j < arg_count; j++) {
                                Argument a = (Argument) Arguments [j];
                                Expression a_expr = a.Expr;
                                Type parameter_type = pd.ParameterType (j);
                                Parameter.Modifier pm = pd.ParameterModifier (j);
-                               
-                               if (pm == Parameter.Modifier.PARAMS){
-                                       if ((pm & ~Parameter.Modifier.PARAMS) != a.Modifier) {
-                                               if (!may_fail)
-                                                       Error_InvalidArguments (loc, j, method, delegate_type, a, pd);
-                                               return false;
-                                       }
+                               Parameter.Modifier am = a.Modifier;
 
-                                       if (chose_params_expanded)
-                                               parameter_type = TypeManager.GetElementType (parameter_type);
-                               } else if (pm == Parameter.Modifier.ARGLIST) {
-                                       if (!(a.Expr is Arglist)) {
-                                               if (!may_fail)
-                                                       Error_InvalidArguments (loc, j, method, delegate_type, a, pd);
-                                               return false;
-                                       }
+                               if (pm == Parameter.Modifier.ARGLIST) {
+                                       if (!(a.Expr is Arglist))
+                                               break;
                                        continue;
-                               } else {
-                                       //
-                                       // Check modifiers
-                                       //
-                                       if (pd.ParameterModifier (j) != a.Modifier){
-                                               if (!may_fail)
-                                                       Error_InvalidArguments (loc, j, method, delegate_type, a, pd);
-                                               return false;
-                                       }
                                }
 
-                               //
-                               // Check Type
-                               //
-                               if (!TypeManager.IsEqual (a.Type, parameter_type)){
-                                       Expression conv;
+                               if (pm == Parameter.Modifier.PARAMS) {
+                                       pm = Parameter.Modifier.NONE;
+                                       if (chose_params_expanded)
+                                               parameter_type = TypeManager.GetElementType (parameter_type);
+                               }
+
+                               if (pm != am)
+                                       break;
 
-                                       conv = Convert.ImplicitConversion (ec, a_expr, parameter_type, loc);
+                               if (!TypeManager.IsEqual (a.Type, parameter_type)) {
+                                       if (pm == Parameter.Modifier.OUT || pm == Parameter.Modifier.REF)
+                                               break;
+
+                                       Expression conv = Convert.ImplicitConversion (ec, a_expr, parameter_type, loc);
+                                       if (conv == null)
+                                               break;
 
-                                       if (conv == null) {
-                                               if (!may_fail)
-                                                       Error_InvalidArguments (loc, j, method, delegate_type, a, pd);
-                                               return false;
-                                       }
-                                       
-                                       //
                                        // Update the argument with the implicit conversion
-                                       //
                                        if (a_expr != conv)
                                                a.Expr = conv;
                                }
 
-                               if (parameter_type.IsPointer){
-                                       if (!ec.InUnsafe){
-                                               UnsafeError (loc);
-                                               return false;
-                                       }
-                               }
-                               
-                               Parameter.Modifier a_mod = a.Modifier &
-                                       unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF));
-                               Parameter.Modifier p_mod = pd.ParameterModifier (j) &
-                                       unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF));
-                               
-                               if (a_mod != p_mod &&
-                                   pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
-                                       if (!may_fail) {
-                                               Invocation.Error_InvalidArguments (loc, j, method, null, a, pd);
-                                       }
-                                       
+                               if (parameter_type.IsPointer && !ec.InUnsafe) {
+                                       UnsafeError (loc);
                                        return false;
                                }
                        }
 
-                       return true;
+                       if (j == arg_count)
+                               return true;
+
+                       if (!may_fail)
+                               Error_InvalidArguments (loc, j, method, delegate_type, (Argument) Arguments [j], pd);
+                       return false;
                }
 
                private bool resolved = false;
@@ -5255,7 +4958,7 @@ namespace Mono.CSharp {
                        }
                        
                        if (mg.InstanceExpression != null)
-                               mg.InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType);
+                               mg.InstanceExpression.CheckMarshalByRefAccess ();
 
                        eclass = ExprClass.Value;
                        this.method = method;
@@ -5365,7 +5068,7 @@ namespace Mono.CSharp {
                                a.Emit (ec);
                                if (dup_args) {
                                        ec.ig.Emit (OpCodes.Dup);
-                                       (temps [i] = new LocalTemporary (ec, a.Type)).Store (ec);
+                                       (temps [i] = new LocalTemporary (a.Type)).Store (ec);
                                }
                        }
                        
@@ -5373,8 +5076,10 @@ namespace Mono.CSharp {
                                if (this_arg != null)
                                        this_arg.Emit (ec);
                                
-                               for (int i = 0; i < top; i ++)
+                               for (int i = 0; i < top; i ++) {
                                        temps [i].Emit (ec);
+                                       temps [i].Release (ec);
+                               }
                        }
 
                        if (pd != null && pd.Count > top &&
@@ -5386,8 +5091,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               static Type[] GetVarargsTypes (EmitContext ec, MethodBase mb,
-                                              ArrayList arguments)
+               static Type[] GetVarargsTypes (MethodBase mb, ArrayList arguments)
                {
                        ParameterData pd = TypeManager.GetParameterData (mb);
 
@@ -5479,7 +5183,7 @@ namespace Mono.CSharp {
                                        method = TypeManager.void_array_copyto_array_int;
                        }
 
-                       if (ec.TestObsoleteMethodUsage) {
+                       if (!ec.IsInObsoleteScope) {
                                //
                                // This checks ObsoleteAttribute on the method and on the declaring type
                                //
@@ -5534,7 +5238,7 @@ namespace Mono.CSharp {
                                                                ((IMemoryLocation)instance_expr).
                                                                        AddressOf (ec, AddressOp.LoadStore);
                                                        } else {
-                                                               LocalTemporary temp = new LocalTemporary (ec, iexpr_type);
+                                                               LocalTemporary temp = new LocalTemporary (iexpr_type);
                                                                instance_expr.Emit (ec);
                                                                temp.Store (ec);
                                                                temp.AddressOf (ec, AddressOp.Load);
@@ -5556,7 +5260,7 @@ namespace Mono.CSharp {
                                        if (dup_args) {
                                                ig.Emit (OpCodes.Dup);
                                                if (Arguments != null && Arguments.Count != 0) {
-                                                       this_arg = new LocalTemporary (ec, t);
+                                                       this_arg = new LocalTemporary (t);
                                                        this_arg.Store (ec);
                                                }
                                        }
@@ -5576,7 +5280,7 @@ namespace Mono.CSharp {
                                call_op = OpCodes.Callvirt;
 
                        if ((method.CallingConvention & CallingConventions.VarArgs) != 0) {
-                               Type[] varargs_types = GetVarargsTypes (ec, method, Arguments);
+                               Type[] varargs_types = GetVarargsTypes (method, Arguments);
                                ig.EmitCall (call_op, (MethodInfo) method, varargs_types);
                                return;
                        }
@@ -5878,7 +5582,7 @@ namespace Mono.CSharp {
                        if (texpr == null)
                                return null;
 
-                       type = texpr.ResolveType (ec);
+                       type = texpr.Type;
 
                        if (Arguments == null) {
                                Expression c = Constantify (type);
@@ -5955,7 +5659,7 @@ namespace Mono.CSharp {
                        MethodGroupExpr mg = ml as MethodGroupExpr;
 
                        if (mg == null) {
-                               ml.Error_UnexpectedKind (ec, "method group", loc);
+                               ml.Error_UnexpectedKind (ec.DeclContainer, "method group", loc);
                                return null;
                        }
 
@@ -6024,7 +5728,7 @@ namespace Mono.CSharp {
                                // We need to create a new LocalTemporary each time since
                                // you can't share LocalBuilders among ILGeneators.
                                if (!value_target_set)
-                                       value_target = new LocalTemporary (ec, type);
+                                       value_target = new LocalTemporary (type);
 
                                ml = (IMemoryLocation) value_target;
                                ml.AddressOf (ec, AddressOp.Store);
@@ -6082,7 +5786,7 @@ namespace Mono.CSharp {
                        }
 
                        if (!value_target_set)
-                               value_target = new LocalTemporary (ec, type);
+                               value_target = new LocalTemporary (type);
                                        
                        IMemoryLocation ml = (IMemoryLocation) value_target;
                        ml.AddressOf (ec, AddressOp.Store);
@@ -6134,15 +5838,10 @@ namespace Mono.CSharp {
 
                ArrayList array_data;
 
-               Hashtable bounds;
-
-               //
-               // The number of array initializers that we can handle
-               // via the InitializeArray method - through EmitStaticInitializers
-               //
-               int num_automatic_initializers;
+               IDictionary bounds;
 
-               const int max_automatic_initializers = 6;
+               // The number of constants in array initializers
+               int const_initializers_count;
                
                public ArrayCreation (Expression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l)
                {
@@ -6192,7 +5891,7 @@ namespace Mono.CSharp {
                        Error (178, "Invalid rank specifier: expected `,' or `]'");
                }
                
-               public bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims)
+               bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims)
                {
                        if (specified_dims) { 
                                Argument a = (Argument) arguments [idx];
@@ -6234,7 +5933,7 @@ namespace Mono.CSharp {
                                                Error_IncorrectArrayInitializer ();
                                                return false;
                                        }
-                                       if (specified_dims && (idx + 1 >= arguments.Count)){
+                                       if (idx + 1 >= dimensions){
                                                Error (623, "Array initializers can only be used in a variable or field initializer. Try using a new expression instead");
                                                return false;
                                        }
@@ -6250,38 +5949,37 @@ namespace Mono.CSharp {
                                        
                                        Expression tmp = (Expression) o;
                                        tmp = tmp.Resolve (ec);
-                                       probe [i] = tmp;
                                        if (tmp == null)
                                                return false;
 
-                                       // Console.WriteLine ("I got: " + tmp);
-                                       // Handle initialization from vars, fields etc.
-
                                        Expression conv = Convert.ImplicitConversionRequired (
                                                ec, tmp, underlying_type, loc);
                                        
                                        if (conv == null) 
                                                return false;
 
-                                       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) {
-                                               // These are the types of Constant that can appear in arrays that can be
-                                               // statically allocated.
-                                               array_data.Add (conv);
-                                               num_automatic_initializers++;
-                                       } else
-                                               array_data.Add (conv);
+                                       // Initializers with the default values can be ignored
+                                       Constant c = tmp as Constant;
+                                       if (c != null) {
+                                               if (c.IsDefaultInitializer (array_element_type)) {
+                                                       conv = null;
+                                               }
+                                               else {
+                                                       ++const_initializers_count;
+                                               }
+                                       } else {
+                                               // Used to invalidate static initializer
+                                               const_initializers_count = int.MinValue;
+                                       }
+                                       
+                                       array_data.Add (conv);
                                }
                        }
 
                        return true;
                }
                
-               public void UpdateIndices (EmitContext ec)
+               public void UpdateIndices ()
                {
                        int i = 0;
                        for (ArrayList probe = initializers; probe != null;) {
@@ -6298,19 +5996,16 @@ namespace Mono.CSharp {
                                        arguments.Add (new Argument (e, Argument.AType.Expression));
 
                                        bounds [i++] = probe.Count;
-                                       probe = null;
+                                       return;
                                }
                        }
 
                }
                
-               public bool ValidateInitializers (EmitContext ec, Type array_type)
+               bool ResolveInitializers (EmitContext ec)
                {
                        if (initializers == null) {
-                               if (expect_initializers)
-                                       return false;
-                               else
-                                       return true;
+                               return !expect_initializers;
                        }
                        
                        if (underlying_type == null)
@@ -6321,30 +6016,24 @@ namespace Mono.CSharp {
                        // will need to store them in the byte blob later
                        //
                        array_data = new ArrayList ();
-                       bounds = new Hashtable ();
+                       bounds = new System.Collections.Specialized.HybridDictionary ();
                        
-                       bool ret;
+                       if (arguments != null)
+                               return CheckIndices (ec, initializers, 0, true);
 
-                       if (arguments != null) {
-                               ret = CheckIndices (ec, initializers, 0, true);
-                               return ret;
-                       } else {
-                               arguments = new ArrayList ();
+                       arguments = new ArrayList ();
 
-                               ret = CheckIndices (ec, initializers, 0, false);
-                               
-                               if (!ret)
-                                       return false;
+                       if (!CheckIndices (ec, initializers, 0, false))
+                               return false;
                                
-                               UpdateIndices (ec);
+                       UpdateIndices ();
                                
-                               if (arguments.Count != dimensions) {
-                                       Error_IncorrectArrayInitializer ();
-                                       return false;
-                               }
-
-                               return ret;
+                       if (arguments.Count != dimensions) {
+                               Error_IncorrectArrayInitializer ();
+                               return false;
                        }
+
+                       return true;
                }
 
                //
@@ -6374,7 +6063,7 @@ namespace Mono.CSharp {
                        if (array_type_expr == null)
                                return false;
 
-                       type = array_type_expr.ResolveType (ec);                
+                       type = array_type_expr.Type;
                        underlying_type = TypeManager.GetElementType (type);
                        dimensions = type.GetArrayRank ();
 
@@ -6383,18 +6072,26 @@ namespace Mono.CSharp {
                
                public override Expression DoResolve (EmitContext ec)
                {
-                       int arg_count;
+                       if (type != null)
+                               return this;
 
                        if (!LookupType (ec))
                                return null;
                        
+                       array_element_type = TypeManager.GetElementType (type);
+                       if (array_element_type.IsAbstract && array_element_type.IsSealed) {
+                               Report.Error (719, loc, "`{0}': array elements cannot be of static type", TypeManager.CSharpName (array_element_type));
+                               return null;
+                       }
+
                        //
                        // First step is to validate the initializers and fill
                        // in any missing bits
                        //
-                       if (!ValidateInitializers (ec, type))
+                       if (!ResolveInitializers (ec))
                                return null;
 
+                       int arg_count;
                        if (arguments == null)
                                arg_count = 0;
                        else {
@@ -6411,13 +6108,6 @@ namespace Mono.CSharp {
                                }
                        }
                        
-                       array_element_type = TypeManager.GetElementType (type);
-
-                       if (array_element_type.IsAbstract && array_element_type.IsSealed) {
-                               Report.Error (719, loc, "`{0}': array elements cannot be of static type", TypeManager.CSharpName (array_element_type));
-                               return null;
-                       }
-
                        if (arg_count == 1) {
                                is_one_dimensional = true;
                                eclass = ExprClass.Value;
@@ -6433,7 +6123,7 @@ namespace Mono.CSharp {
                                                   AllBindingFlags, loc);
                                
                                if (!(ml is MethodGroupExpr)) {
-                                       ml.Error_UnexpectedKind (ec, "method group", loc);
+                                       ml.Error_UnexpectedKind (ec.DeclContainer, "method group", loc);
                                        return null;
                                }
                                
@@ -6484,7 +6174,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public static byte [] MakeByteBlob (ArrayList array_data, Type underlying_type, Location loc)
+               byte [] MakeByteBlob ()
                {
                        int factor;
                        byte [] data;
@@ -6500,7 +6190,7 @@ namespace Mono.CSharp {
 
                        data = new byte [(count * factor + 4) & ~3];
                        int idx = 0;
-                       
+
                        for (int i = 0; i < count; ++i) {
                                object v = array_data [i];
 
@@ -6639,7 +6329,7 @@ namespace Mono.CSharp {
                        FieldBuilder fb;
                        ILGenerator ig = ec.ig;
                        
-                       byte [] data = MakeByteBlob (array_data, underlying_type, loc);
+                       byte [] data = MakeByteBlob ();
 
                        fb = RootContext.MakeStaticData (data);
 
@@ -6660,90 +6350,69 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        int dims = bounds.Count;
                        int [] current_pos = new int [dims];
-                       int top = array_data.Count;
 
                        MethodInfo set = null;
 
                        if (dims != 1){
-                               Type [] args;
-                               ModuleBuilder mb = null;
-                               mb = CodeGen.Module.Builder;
-                               args = new Type [dims + 1];
+                               Type [] args = new Type [dims + 1];
 
-                               int j;
-                               for (j = 0; j < dims; j++)
+                               for (int j = 0; j < dims; j++)
                                        args [j] = TypeManager.int32_type;
-
-                               args [j] = array_element_type;
+                               args [dims] = array_element_type;
                                
-                               set = mb.GetArrayMethod (
+                               set = CodeGen.Module.Builder.GetArrayMethod (
                                        type, "Set",
                                        CallingConventions.HasThis | CallingConventions.Standard,
                                        TypeManager.void_type, args);
                        }
-                       
-                       for (int i = 0; i < top; i++){
 
-                               Expression e = null;
+                       for (int i = 0; i < array_data.Count; i++){
 
-                               if (array_data [i] is Expression)
-                                       e = (Expression) array_data [i];
+                               Expression e = (Expression)array_data [i];
 
                                if (e != null) {
-                                       //
-                                       // Basically we do this for string literals and
-                                       // other non-literal expressions
-                                       //
-                                       if (e is EnumConstant){
-                                               e = ((EnumConstant) e).Child;
-                                       }
-                                       
-                                       if (e is StringConstant || e is DecimalConstant || !(e is Constant) ||
-                                           num_automatic_initializers <= max_automatic_initializers) {
-                                               Type etype = e.Type;
+                                       Type etype = e.Type;
 
-                                               ig.Emit (OpCodes.Dup);
+                                       ig.Emit (OpCodes.Dup);
 
-                                               for (int idx = 0; idx < dims; idx++) 
-                                                       IntConstant.EmitInt (ig, current_pos [idx]);
+                                       for (int idx = 0; idx < dims; idx++) 
+                                               IntConstant.EmitInt (ig, current_pos [idx]);
 
-                                               //
-                                               // If we are dealing with a struct, get the
-                                               // address of it, so we can store it.
-                                               //
-                                               if ((dims == 1) && 
-                                                   TypeManager.IsValueType (etype) &&
-                                                   (!TypeManager.IsBuiltinOrEnum (etype) ||
-                                                    etype == TypeManager.decimal_type)) {
-                                                       if (e is New){
-                                                               New n = (New) e;
-
-                                                               //
-                                                               // Let new know that we are providing
-                                                               // the address where to store the results
-                                                               //
-                                                               n.DisableTemporaryValueType ();
-                                                       }
+                                       //
+                                       // If we are dealing with a struct, get the
+                                       // address of it, so we can store it.
+                                       //
+                                       if ((dims == 1) && 
+                                               TypeManager.IsValueType (etype) &&
+                                               (!TypeManager.IsBuiltinOrEnum (etype) ||
+                                               etype == TypeManager.decimal_type)) {
+                                               if (e is New){
+                                                       New n = (New) e;
 
-                                                       ig.Emit (OpCodes.Ldelema, etype);
+                                                       //
+                                                       // Let new know that we are providing
+                                                       // the address where to store the results
+                                                       //
+                                                       n.DisableTemporaryValueType ();
                                                }
 
-                                               e.Emit (ec);
-
-                                               if (dims == 1) {
-                                                       bool is_stobj, has_type_arg;
-                                                       OpCode op = ArrayAccess.GetStoreOpcode (
-                                                               etype, out is_stobj,
-                                                               out has_type_arg);
-                                                       if (is_stobj)
-                                                               ig.Emit (OpCodes.Stobj, etype);
-                                                       else if (has_type_arg)
-                                                               ig.Emit (op, etype);
-                                                       else
-                                                               ig.Emit (op);
-                                               } else 
-                                                        ig.Emit (OpCodes.Call, set);
+                                               ig.Emit (OpCodes.Ldelema, etype);
                                        }
+
+                                       e.Emit (ec);
+
+                                       if (dims == 1) {
+                                               bool is_stobj, has_type_arg;
+                                               OpCode op = ArrayAccess.GetStoreOpcode (etype, out is_stobj, out has_type_arg);
+                                               if (is_stobj)
+                                                       ig.Emit (OpCodes.Stobj, etype);
+                                               else if (has_type_arg)
+                                                       ig.Emit (op, etype);
+                                               else
+                                                       ig.Emit (op);
+                                       } else 
+                                               ig.Emit (OpCodes.Call, set);
+
                                }
                                
                                //
@@ -6787,60 +6456,87 @@ namespace Mono.CSharp {
                                        ig.Emit (OpCodes.Newobj, (MethodInfo) new_method);
                        }
                        
-                       if (initializers != null){
-                               //
-                               // FIXME: Set this variable correctly.
-                               // 
-                               bool dynamic_initializers = true;
+                       if (initializers == null)
+                               return;
 
-                               // 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);
+                       // This is a treshold for static initializers
+                       // I tried to make more accurate but it seems to me that Array.Initialize is
+                       // always slower (managed -> unmanaged switch?)
+                       const int max_automatic_initializers = 200;
+
+                       if (const_initializers_count > max_automatic_initializers && TypeManager.IsPrimitiveType (array_element_type)) {
+                               EmitStaticInitializers (ec);
+                               return;
                        }
+                               
+                       EmitDynamicInitializers (ec);
                }
 
-               public object EncodeAsAttribute ()
+               public override bool GetAttributableValue (Type valueType, out object value)
                {
                        if (!is_one_dimensional){
-                               Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays");
-                               return null;
+//                             Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays");
+                               return base.GetAttributableValue (null, out value);
                        }
 
-                       if (array_data == null){
-                               Report.Error (-212, Location, "array should be initialized when passing it to an attribute");
-                               return null;
+                       if (array_data == null) {
+                               Constant c = (Constant)((Argument)arguments [0]).Expr;
+                               if (c.IsDefaultValue) {
+                                       value = Array.CreateInstance (array_element_type, 0);
+                                       return true;
+                               }
+//                             Report.Error (-212, Location, "array should be initialized when passing it to an attribute");
+                               return base.GetAttributableValue (null, out value);
                        }
                        
-                       object [] ret = new object [array_data.Count];
-                       int i = 0;
-                       foreach (Expression e in array_data){
-                               object v;
-                               
-                               if (e is NullLiteral)
-                                       v = null;
-                               else {
-                                       if (!Attribute.GetAttributeArgumentExpression (e, Location, array_element_type, out v))
-                                               return null;
+                       Array ret = Array.CreateInstance (array_element_type, array_data.Count);
+                       object element_value;
+                       for (int i = 0; i < ret.Length; ++i)
+                       {
+                               Expression e = (Expression)array_data [i];
+                               if (e == null) // Is null when initializer is optimized away
+                                       e = (Expression)initializers [i];
+
+                               if (!e.GetAttributableValue (array_element_type, out element_value)) {
+                                       value = null;
+                                       return false;
                                }
-                               ret [i++] = v;
+                               ret.SetValue (element_value, i);
                        }
-                       return ret;
+                       value = ret;
+                       return true;
+               }
+       }
+       
+       public sealed class CompilerGeneratedThis : This
+       {
+               public static This Instance = new CompilerGeneratedThis ();
+
+               private CompilerGeneratedThis ()
+                       : base (Location.Null)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       eclass = ExprClass.Variable;
+                       type = ec.ContainerType;
+                       variable = new SimpleThis (type);
+                       return this;
                }
        }
        
        /// <summary>
        ///   Represents the `this' construct
        /// </summary>
-       public class This : Expression, IAssignMethod, IMemoryLocation, IVariable {
 
+       public class This : VariableReference, IVariable
+       {
                Block block;
                VariableInfo variable_info;
-               
+               protected Variable variable;
+               bool is_struct;
+
                public This (Block block, Location loc)
                {
                        this.loc = loc;
@@ -6861,6 +6557,14 @@ namespace Mono.CSharp {
                        return !TypeManager.IsValueType (Type);
                }
 
+               public override bool IsRef {
+                       get { return is_struct; }
+               }
+
+               public override Variable Variable {
+                       get { return variable; }
+               }
+
                public bool ResolveBase (EmitContext ec)
                {
                        eclass = ExprClass.Variable;
@@ -6870,16 +6574,38 @@ namespace Mono.CSharp {
                        else
                                type = ec.ContainerType;
 
+                       is_struct = ec.TypeContainer is Struct;
+
                        if (ec.IsStatic) {
-                               Error (26, "Keyword `this' is not valid in a static property, static method, or static field initializer");
+                               Error (26, "Keyword `this' is not valid in a static property, " +
+                                      "static method, or static field initializer");
                                return false;
                        }
 
-                       if (block != null && block.Toplevel.ThisVariable != null)
-                               variable_info = block.Toplevel.ThisVariable.VariableInfo;
+                       if (block != null) {
+                               if (block.Toplevel.ThisVariable != null)
+                                       variable_info = block.Toplevel.ThisVariable.VariableInfo;
+
+                               AnonymousContainer am = ec.CurrentAnonymousMethod;
+                               if (is_struct && (am != null) && !am.IsIterator) {
+                                       Report.Error (1673, loc, "Anonymous methods inside structs " +
+                                                     "cannot access instance members of `this'. " +
+                                                     "Consider copying `this' to a local variable " +
+                                                     "outside the anonymous method and using the " +
+                                                     "local instead.");
+                                       return false;
+                               }
+
+                               AnonymousMethodHost host = block.Toplevel.AnonymousMethodHost;
+                               if ((host != null) && (!is_struct || host.IsIterator)) {
+                                       variable = host.CaptureThis ();
+                                       type = variable.Type;
+                                       is_struct = false;
+                               }
+                       }
 
-                       if (ec.CurrentAnonymousMethod != null)
-                               ec.CaptureThis ();
+                       if (variable == null)
+                               variable = new SimpleThis (type);
                        
                        return true;
                }
@@ -6889,8 +6615,10 @@ namespace Mono.CSharp {
                        if (!ResolveBase (ec))
                                return null;
 
-                       if ((variable_info != null) && !(type.IsValueType && ec.OmitStructFlowAnalysis) && !variable_info.IsAssigned (ec)) {
-                               Error (188, "The `this' object cannot be used before all of its fields are assigned to");
+                       if ((variable_info != null) && !(type.IsValueType && ec.OmitStructFlowAnalysis) &&
+                           !variable_info.IsAssigned (ec)) {
+                               Error (188, "The `this' object cannot be used before all of its " +
+                                      "fields are assigned to");
                                variable_info.SetAssigned (ec);
                                return this;
                        }
@@ -6918,47 +6646,6 @@ namespace Mono.CSharp {
 
                        return this;
                }
-
-               public void Emit (EmitContext ec, bool leave_copy)
-               {
-                       Emit (ec);
-                       if (leave_copy)
-                               ec.ig.Emit (OpCodes.Dup);
-               }
-               
-               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
-               {
-                       ILGenerator ig = ec.ig;
-                       
-                       if (ec.TypeContainer is Struct){
-                               ec.EmitThis (false);
-                               source.Emit (ec);
-                               
-                               LocalTemporary t = null;
-                               if (leave_copy) {
-                                       t = new LocalTemporary (ec, type);
-                                       ec.ig.Emit (OpCodes.Dup);
-                                       t.Store (ec);
-                               }
-
-                               ig.Emit (OpCodes.Stobj, type);
-                               
-                               if (leave_copy)
-                                       t.Emit (ec);
-                       } else {
-                               throw new Exception ("how did you get here");
-                       }
-               }
-               
-               public override void Emit (EmitContext ec)
-               {
-                       ILGenerator ig = ec.ig;
-
-                       ec.EmitThis (false);
-                       if (ec.TypeContainer is Struct)
-                               ig.Emit (OpCodes.Ldobj, type);
-               }
-
                public override int GetHashCode()
                {
                        return block.GetHashCode ();
@@ -6973,18 +6660,46 @@ namespace Mono.CSharp {
                        return block == t.block;
                }
 
-               public void AddressOf (EmitContext ec, AddressOp mode)
+               protected class SimpleThis : Variable
                {
-                       ec.EmitThis (true);
+                       Type type;
 
-                       // FIMXE
-                       // FIGURE OUT WHY LDARG_S does not work
-                       //
-                       // consider: struct X { int val; int P { set { val = value; }}}
-                       //
-                       // Yes, this looks very bad. Look at `NOTAS' for
-                       // an explanation.
-                       // ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);
+                       public SimpleThis (Type type)
+                       {
+                               this.type = type;
+                       }
+
+                       public override Type Type {
+                               get { return type; }
+                       }
+
+                       public override bool HasInstance {
+                               get { return false; }
+                       }
+
+                       public override bool NeedsTemporary {
+                               get { return false; }
+                       }
+
+                       public override void EmitInstance (EmitContext ec)
+                       {
+                               // Do nothing.
+                       }
+
+                       public override void Emit (EmitContext ec)
+                       {
+                               ec.ig.Emit (OpCodes.Ldarg_0);
+                       }
+
+                       public override void EmitAssign (EmitContext ec)
+                       {
+                               throw new InvalidOperationException ();
+                       }
+
+                       public override void EmitAddressOf (EmitContext ec)
+                       {
+                               ec.ig.Emit (OpCodes.Ldarg_0);
+                       }
                }
        }
 
@@ -6998,21 +6713,15 @@ namespace Mono.CSharp {
                        this.loc = loc;
                }
 
-               public bool ResolveBase (EmitContext ec)
+               public override Expression DoResolve (EmitContext ec)
                {
                        eclass = ExprClass.Variable;
                        type = TypeManager.runtime_argument_handle_type;
-                       return true;
-               }
-
-               public override Expression DoResolve (EmitContext ec)
-               {
-                       if (!ResolveBase (ec))
-                               return null;
 
-                       if (ec.IsFieldInitializer || !ec.CurrentBlock.Toplevel.HasVarargs) {
+                       if (ec.IsFieldInitializer || !ec.CurrentBlock.Toplevel.HasVarargs) 
+                       {
                                Error (190, "The __arglist construct is valid only within " +
-                                      "a variable argument method.");
+                                      "a variable argument method");
                                return null;
                        }
 
@@ -7094,7 +6803,7 @@ namespace Mono.CSharp {
        ///   Implements the typeof operator
        /// </summary>
        public class TypeOf : Expression {
-               public Expression QueriedType;
+               readonly Expression QueriedType;
                protected Type typearg;
                
                public TypeOf (Expression queried_type, Location l)
@@ -7109,7 +6818,7 @@ namespace Mono.CSharp {
                        if (texpr == null)
                                return null;
 
-                       typearg = texpr.ResolveType (ec);
+                       typearg = texpr.Type;
 
                        if (typearg == TypeManager.void_type) {
                                Error (673, "System.Void cannot be used from C#. Use typeof (void) to get the void type object");
@@ -7134,8 +6843,30 @@ namespace Mono.CSharp {
                        ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
                }
 
-               public Type TypeArg { 
-                       get { return typearg; }
+               public override bool GetAttributableValue (Type valueType, out object value)
+               {
+                       if (typearg.ContainsGenericParameters) {
+                               Report.SymbolRelatedToPreviousError(typearg);
+                               Report.Error(416, loc, "`{0}': an attribute argument cannot use type parameters",
+                                       TypeManager.CSharpName(typearg));
+                               value = null;
+                               return false;
+                       }
+
+                       if (valueType == TypeManager.object_type) {
+                               value = (object)typearg;
+                               return true;
+                       }
+                       value = typearg;
+                       return true;
+               }
+
+               public Type TypeArgument
+               {
+                       get
+                       {
+                               return typearg;
+                       }
                }
        }
 
@@ -7182,7 +6913,14 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       type_queried = texpr.ResolveType (ec);
+                       type_queried = texpr.Type;
+                       if (type_queried.IsEnum)
+                               type_queried = TypeManager.EnumToUnderlying (type_queried);
+
+                       if (type_queried == TypeManager.void_type) {
+                               Expression.Error_VoidInvalidInTheContext (loc);
+                               return null;
+                       }
 
                        int size_of = GetTypeSize (type_queried);
                        if (size_of > 0) {
@@ -7229,7 +6967,7 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
+               public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
                {
                        if (alias == "global")
                                return new MemberAccess (RootNamespace.Global, identifier, loc).ResolveAsTypeStep (ec, silent);
@@ -7246,7 +6984,7 @@ namespace Mono.CSharp {
                                        Report.Error (431, loc, "`{0}' cannot be used with '::' since it denotes a type", alias);
                                return null;
                        }
-                       return new MemberAccess (fne, identifier, loc).ResolveAsTypeStep (ec, silent);
+                       return new MemberAccess (fne, identifier).ResolveAsTypeStep (ec, silent);
                }
 
                public override Expression DoResolve (EmitContext ec)
@@ -7264,7 +7002,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       Expression retval = new MemberAccess (fne, identifier, loc).DoResolve (ec);
+                       Expression retval = new MemberAccess (fne, identifier).DoResolve (ec);
                        if (retval == null)
                                return null;
 
@@ -7306,17 +7044,20 @@ namespace Mono.CSharp {
                Expression expr;
                TypeArguments args;
                
-               // TODO: Location can be removed
-               public MemberAccess (Expression expr, string id, Location l)
+               public MemberAccess (Expression expr, string id)
+                       : this (expr, id, expr.Location)
+               {
+               }
+
+               public MemberAccess (Expression expr, string identifier, Location loc)
                {
                        this.expr = expr;
-                       Identifier = id;
-                       loc = expr.Location;
+                       Identifier = identifier;
+                       this.loc = loc;
                }
 
-               public MemberAccess (Expression expr, string id, TypeArguments args,
-                                    Location l)
-                       : this (expr, id, l)
+               public MemberAccess (Expression expr, string id, TypeArguments args)
+                       : this (expr, id)
                {
                        this.args = args;
                }
@@ -7354,8 +7095,7 @@ namespace Mono.CSharp {
                                if ((retval != null) && (args != null))
                                        retval = new ConstructedType (retval, args, loc).ResolveAsTypeStep (ec, false);
                                if (retval == null)
-                                       Report.Error (234, loc, "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
-                                               Identifier, ns.FullName);
+                                       ns.Error_NamespaceDoesNotExist (loc, Identifier);
                                return retval;
                        }
 
@@ -7453,14 +7193,14 @@ namespace Mono.CSharp {
                        return DoResolve (ec, right_side);
                }
 
-               public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
+               public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
                {
                        return ResolveNamespaceOrType (ec, silent);
                }
 
-               public FullNamedExpression ResolveNamespaceOrType (EmitContext ec, bool silent)
+               public FullNamedExpression ResolveNamespaceOrType (IResolveContext rc, bool silent)
                {
-                       FullNamedExpression new_expr = expr.ResolveAsTypeStep (ec, silent);
+                       FullNamedExpression new_expr = expr.ResolveAsTypeStep (rc, silent);
 
                        if (new_expr == null)
                                return null;
@@ -7469,20 +7209,19 @@ namespace Mono.CSharp {
 
                        if (new_expr is Namespace) {
                                Namespace ns = (Namespace) new_expr;
-                               FullNamedExpression retval = ns.Lookup (ec.DeclContainer, lookup_id, loc);
+                               FullNamedExpression retval = ns.Lookup (rc.DeclContainer, lookup_id, loc);
                                if ((retval != null) && (args != null))
-                                       retval = new ConstructedType (retval, args, loc).ResolveAsTypeStep (ec, false);
+                                       retval = new ConstructedType (retval, args, loc).ResolveAsTypeStep (rc, false);
                                if (!silent && retval == null)
-                                       Report.Error (234, loc, "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
-                                               Identifier, ns.FullName);
+                                       ns.Error_NamespaceDoesNotExist (loc, Identifier);
                                return retval;
                        }
 
-                       TypeExpr tnew_expr = new_expr.ResolveAsTypeTerminal (ec, false);
+                       TypeExpr tnew_expr = new_expr.ResolveAsTypeTerminal (rc, false);
                        if (tnew_expr == null)
                                return null;
 
-                       Type expr_type = tnew_expr.ResolveType (ec);
+                       Type expr_type = tnew_expr.Type;
 
                        if (expr_type.IsPointer){
                                Error (23, "The `.' operator can not be applied to pointer operands (" +
@@ -7491,11 +7230,11 @@ namespace Mono.CSharp {
                        }
 
                        Expression member_lookup = MemberLookup (
-                               ec.ContainerType, expr_type, expr_type, lookup_id,
+                               rc.DeclContainer.TypeBuilder, expr_type, expr_type, lookup_id,
                                MemberTypes.NestedType, BindingFlags.Public | BindingFlags.NonPublic, loc);
                        if (member_lookup == null) {
                                int errors = Report.Errors;
-                               MemberLookupFailed (ec.ContainerType, expr_type, expr_type, lookup_id, null, false, loc);
+                               MemberLookupFailed (rc.DeclContainer.TypeBuilder, expr_type, expr_type, lookup_id, null, false, loc);
 
                                if (!silent && errors == Report.Errors) {
                                        Report.Error (426, loc, "The nested type `{0}' does not exist in the type `{1}'",
@@ -7505,11 +7244,11 @@ namespace Mono.CSharp {
                        }
 
                        if (!(member_lookup is TypeExpr)) {
-                               new_expr.Error_UnexpectedKind (ec, "type", loc);
+                               new_expr.Error_UnexpectedKind (rc.DeclContainer, "type", loc);
                                return null;
                        }
 
-                       TypeExpr texpr = member_lookup.ResolveAsTypeTerminal (ec, false);
+                       TypeExpr texpr = member_lookup.ResolveAsTypeTerminal (rc, false);
                        if (texpr == null)
                                return null;
 
@@ -7529,7 +7268,7 @@ namespace Mono.CSharp {
 
                        if (the_args != null) {
                                ConstructedType ctype = new ConstructedType (texpr.Type, the_args, loc);
-                               return ctype.ResolveAsTypeStep (ec, false);
+                               return ctype.ResolveAsTypeStep (rc, false);
                        }
 
                        return texpr;
@@ -7566,14 +7305,8 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       bool last_check = ec.CheckState;
-                       bool last_const_check = ec.ConstantCheckState;
-
-                       ec.CheckState = true;
-                       ec.ConstantCheckState = true;
-                       Expr = Expr.Resolve (ec);
-                       ec.CheckState = last_check;
-                       ec.ConstantCheckState = last_const_check;
+                       using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
+                               Expr = Expr.Resolve (ec);
                        
                        if (Expr == null)
                                return null;
@@ -7588,16 +7321,15 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       bool last_check = ec.CheckState;
-                       bool last_const_check = ec.ConstantCheckState;
-                       
-                       ec.CheckState = true;
-                       ec.ConstantCheckState = true;
-                       Expr.Emit (ec);
-                       ec.CheckState = last_check;
-                       ec.ConstantCheckState = last_const_check;
+                       using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
+                               Expr.Emit (ec);
+               }
+
+               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               {
+                       using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
+                               Expr.EmitBranchable (ec, target, onTrue);
                }
-               
        }
 
        /// <summary>
@@ -7615,14 +7347,8 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       bool last_check = ec.CheckState;
-                       bool last_const_check = ec.ConstantCheckState;
-
-                       ec.CheckState = false;
-                       ec.ConstantCheckState = false;
-                       Expr = Expr.Resolve (ec);
-                       ec.CheckState = last_check;
-                       ec.ConstantCheckState = last_const_check;
+                       using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
+                               Expr = Expr.Resolve (ec);
 
                        if (Expr == null)
                                return null;
@@ -7637,16 +7363,15 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       bool last_check = ec.CheckState;
-                       bool last_const_check = ec.ConstantCheckState;
-                       
-                       ec.CheckState = false;
-                       ec.ConstantCheckState = false;
-                       Expr.Emit (ec);
-                       ec.CheckState = last_check;
-                       ec.ConstantCheckState = last_const_check;
+                       using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
+                               Expr.Emit (ec);
                }
                
+               public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               {
+                       using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
+                               Expr.EmitBranchable (ec, target, onTrue);
+               }
        }
 
        /// <summary>
@@ -8042,7 +7767,7 @@ namespace Mono.CSharp {
                        
                        if (leave_copy) {
                                ec.ig.Emit (OpCodes.Dup);
-                               temp = new LocalTemporary (ec, this.type);
+                               temp = new LocalTemporary (this.type);
                                temp.Store (ec);
                        }
                }
@@ -8065,13 +7790,15 @@ namespace Mono.CSharp {
                                source.Emit (ec);
                                if (leave_copy) {
                                        ec.ig.Emit (OpCodes.Dup);
-                                       temp = new LocalTemporary (ec, this.type);
+                                       temp = new LocalTemporary (this.type);
                                        temp.Store (ec);
                                }
                                StoreFromPtr (ec.ig, t);
                                
-                               if (temp != null)
+                               if (temp != null) {
                                        temp.Emit (ec);
+                                       temp.Release (ec);
+                               }
                                
                                return;
                        }
@@ -8093,7 +7820,7 @@ namespace Mono.CSharp {
                                source.Emit (ec);
                                if (leave_copy) {
                                        ec.ig.Emit (OpCodes.Dup);
-                                       temp = new LocalTemporary (ec, this.type);
+                                       temp = new LocalTemporary (this.type);
                                        temp.Store (ec);
                                }
                                
@@ -8112,7 +7839,7 @@ namespace Mono.CSharp {
                                source.Emit (ec);
                                if (leave_copy) {
                                        ec.ig.Emit (OpCodes.Dup);
-                                       temp = new LocalTemporary (ec, this.type);
+                                       temp = new LocalTemporary (this.type);
                                        temp.Store (ec);
                                }
                                
@@ -8132,8 +7859,10 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Call, set);
                        }
                        
-                       if (temp != null)
+                       if (temp != null) {
                                temp.Emit (ec);
+                               temp.Release (ec);
+                       }
                }
 
                public void AddressOf (EmitContext ec, AddressOp mode)
@@ -8226,7 +7955,7 @@ namespace Mono.CSharp {
                                BindingFlags.DeclaredOnly, p_name, null);
                }
                
-               static public Indexers GetIndexersForType (Type caller_type, Type lookup_type, Location loc
+               static public Indexers GetIndexersForType (Type caller_type, Type lookup_type) 
                {
                        Indexers ix = empty;
 
@@ -8304,7 +8033,6 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       ArrayList AllGetters = new ArrayList();
                        if (!CommonResolve (ec))
                                return null;
 
@@ -8314,37 +8042,35 @@ namespace Mono.CSharp {
                        //
                        // This is a group of properties, piles of them.  
 
-                       bool found_any = false, found_any_getters = false;
-                       Type lookup_type = indexer_type;
+                       ArrayList AllGetters = null;
 
-                       Indexers ilist = Indexers.GetIndexersForType (current_type, lookup_type, loc);
+                       Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type);
                        if (ilist.Properties != null) {
-                               found_any = true;
+                               AllGetters = new ArrayList(ilist.Properties.Count);
                                foreach (Indexers.Indexer ix in ilist.Properties) {
                                        if (ix.Getter != null)
                                                AllGetters.Add (ix.Getter);
                                }
                        }
 
-                       if (AllGetters.Count > 0) {
-                               found_any_getters = true;
-                               get = (MethodInfo) Invocation.OverloadResolve (
-                                       ec, new MethodGroupExpr (AllGetters, loc),
-                                       arguments, false, loc);
-                       }
-
-                       if (!found_any) {
+                       if (AllGetters == null) {
                                Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `{0}'",
-                                             TypeManager.CSharpName (indexer_type));
+                                       TypeManager.CSharpName (indexer_type));
                                return null;
                        }
 
-                       if (!found_any_getters) {
+                       if (AllGetters.Count == 0) {
+                               // FIXME: we cannot simply select first one as the error message is missleading when
+                               // multiple indexers exist
+                               Indexers.Indexer first_indexer = (Indexers.Indexer)ilist.Properties[ilist.Properties.Count - 1];
                                Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
-                                             "XXXXXXXX");
+                                       TypeManager.GetFullNameSignature (first_indexer.PropertyInfo));
                                return null;
                        }
 
+                       get = (MethodInfo)Invocation.OverloadResolve (ec, new MethodGroupExpr (AllGetters, loc),
+                                       arguments, false, loc);
+
                        if (get == null) {
                                Invocation.Error_WrongNumArguments (loc, "this", arguments.Count);
                                return null;
@@ -8364,7 +8090,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       instance_expr.CheckMarshallByRefAccess (ec.ContainerType);
+                       instance_expr.CheckMarshalByRefAccess ();
                        
                        eclass = ExprClass.IndexerAccess;
                        return this;
@@ -8379,7 +8105,7 @@ namespace Mono.CSharp {
                        }
 
                        // if the indexer returns a value type, and we try to set a field in it
-                       if (right_side == EmptyExpression.LValueMemberAccess) {
+                       if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) {
                                Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable",
                                              GetSignatureForError ());
                                return null;
@@ -8391,7 +8117,7 @@ namespace Mono.CSharp {
 
                        bool found_any = false, found_any_setters = false;
 
-                       Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type, loc);
+                       Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type);
                        if (ilist.Properties != null) {
                                found_any = true;
                                foreach (Indexers.Indexer ix in ilist.Properties) {
@@ -8444,7 +8170,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       instance_expr.CheckMarshallByRefAccess (ec.ContainerType);
+                       instance_expr.CheckMarshalByRefAccess ();
 
                        eclass = ExprClass.IndexerAccess;
                        return this;
@@ -8458,7 +8184,7 @@ namespace Mono.CSharp {
                        Invocation.EmitCall (ec, is_base_indexer, false, instance_expr, get, arguments, loc, prepared, false);
                        if (leave_copy) {
                                ec.ig.Emit (OpCodes.Dup);
-                               temp = new LocalTemporary (ec, Type);
+                               temp = new LocalTemporary (Type);
                                temp.Store (ec);
                        }
                }
@@ -8477,11 +8203,11 @@ namespace Mono.CSharp {
                                source.Emit (ec);
                                if (leave_copy) {
                                        ec.ig.Emit (OpCodes.Dup);
-                                       temp = new LocalTemporary (ec, Type);
+                                       temp = new LocalTemporary (Type);
                                        temp.Store (ec);
                                }
                        } else if (leave_copy) {
-                               temp = new LocalTemporary (ec, Type);
+                               temp = new LocalTemporary (Type);
                                source.Emit (ec);
                                temp.Store (ec);
                                a.Expr = temp;
@@ -8489,8 +8215,10 @@ namespace Mono.CSharp {
                        
                        Invocation.EmitCall (ec, is_base_indexer, false, instance_expr, set, set_arguments, loc, false, prepared);
                        
-                       if (temp != null)
+                       if (temp != null) {
                                temp.Emit (ec);
+                               temp.Release (ec);
+                       }
                }
                
                
@@ -8656,6 +8384,7 @@ namespace Mono.CSharp {
 
                public static readonly EmptyExpression OutAccess = new EmptyExpression ();
                public static readonly EmptyExpression LValueMemberAccess = new EmptyExpression ();
+               public static readonly EmptyExpression LValueMemberOutAccess = new EmptyExpression ();
 
                static EmptyExpression temp = new EmptyExpression ();
                public static EmptyExpression Grab ()
@@ -8784,20 +8513,15 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+               protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
                {
                        TypeExpr lexpr = left.ResolveAsTypeTerminal (ec, false);
                        if (lexpr == null)
                                return null;
 
-                       bool old = ec.TestObsoleteMethodUsage;
-                       ec.TestObsoleteMethodUsage = false;
-                       Type ltype = lexpr.ResolveType (ec);
-                       ec.TestObsoleteMethodUsage = old;
-
+                       Type ltype = lexpr.Type;
                        if ((ltype == TypeManager.void_type) && (dim != "*")) {
-                               Report.Error (1547, Location,
-                                             "Keyword 'void' cannot be used in this context");
+                               Error_VoidInvalidInTheContext (loc);
                                return null;
                        }
 
@@ -8821,7 +8545,7 @@ namespace Mono.CSharp {
                                throw new InternalErrorException ("Couldn't create computed type " + ltype + dim);
                        }
 
-                       if (!ec.InUnsafe && type.IsPointer){
+                       if (type.IsPointer && !ec.IsInUnsafeScope){
                                UnsafeError (loc);
                                return null;
                        }
@@ -8976,7 +8700,7 @@ namespace Mono.CSharp {
                        if (texpr == null)
                                return null;
 
-                       otype = texpr.ResolveType (ec);
+                       otype = texpr.Type;
 
                        if (!TypeManager.VerifyUnManaged (otype, loc))
                                return null;