2008-09-17 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / expression.cs
index c7201a2c1611dd87d25b4aa297653453235b5f2e..b3a88cccca53b401678513fbbfe2904bc8d030a2 100644 (file)
@@ -72,28 +72,6 @@ namespace Mono.CSharp {
                        mg.EmitCall (ec, arguments);
                }
 
-               [Obsolete ("It may not be compatible with expression trees")]
-               static public UserOperatorCall MakeSimpleCall (EmitContext ec, MethodGroupExpr mg,
-                                                        Expression e, Location loc)
-               {
-                       ArrayList args;
-                       
-                       args = new ArrayList (1);
-                       Argument a = new Argument (e, Argument.AType.Expression);
-
-                        // We need to resolve the arguments before sending them in !
-                        if (!a.Resolve (ec, loc))
-                                return null;
-
-                        args.Add (a);
-                       mg = mg.OverloadResolve (ec, ref args, false, loc);
-
-                       if (mg == null)
-                               return null;
-
-                       return new UserOperatorCall (mg, args, null, loc);
-               }
-
                public MethodGroupExpr Method {
                        get { return mg; }
                }
@@ -169,6 +147,9 @@ namespace Mono.CSharp {
                // </summary>
                Constant TryReduceConstant (EmitContext ec, Constant e)
                {
+                       if (e is EmptyConstantCast)
+                               return TryReduceConstant (ec, ((EmptyConstantCast) e).child);
+                       
                        if (e is SideEffectConstant) {
                                Constant r = TryReduceConstant (ec, ((SideEffectConstant) e).value);
                                return r == null ? null : new SideEffectConstant (r, e, r.Location);
@@ -462,13 +443,6 @@ namespace Mono.CSharp {
                public override Expression DoResolve (EmitContext ec)
                {
                        if (Oper == Operator.AddressOf) {
-                               Expr = Expr.DoResolveLValue (ec, new EmptyExpression ());
-
-                               if (Expr == null || Expr.eclass != ExprClass.Variable){
-                                       Error (211, "Cannot take the address of the given expression");
-                                       return null;
-                               }
-
                                return ResolveAddressOf (ec);
                        }
 
@@ -615,8 +589,12 @@ namespace Mono.CSharp {
 
                Expression ResolveAddressOf (EmitContext ec)
                {
-                       if (!ec.InUnsafe) {
+                       if (!ec.InUnsafe)
                                UnsafeError (loc);
+
+                       Expr = Expr.DoResolveLValue (ec, EmptyExpression.UnaryAddress);
+                       if (Expr == null || Expr.eclass != ExprClass.Variable) {
+                               Error (211, "Cannot take the address of the given expression");
                                return null;
                        }
 
@@ -624,39 +602,35 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       IVariable variable = Expr as IVariable;
-                       if (variable != null && variable.IsFixed) {
-                               if (ec.InFixedInitializer) {
-                                       Error (213, "You cannot use the fixed statement to take the address of an already fixed expression");
-                                       return null;
-                               }
-                       } else {
-                               if (!ec.InFixedInitializer) {
-                                       Error (212, "You can only take the address of unfixed expression inside of a fixed statement initializer");
-                                       return null;
-                               }
-                       }
+                       IVariableReference vr = Expr as IVariableReference;
+                       bool is_fixed;
+                       if (vr != null) {
+                               VariableInfo vi = vr.VariableInfo;
+                               if (vi != null) {
+                                       if (vi.LocalInfo != null)
+                                               vi.LocalInfo.Used = true;
 
-                       LocalVariableReference lr = Expr as LocalVariableReference;
-                       if (lr != null) {
-                               if (lr.IsHoisted) {
-                                       AnonymousMethodBody.Error_AddressOfCapturedVar (lr.Name, loc);
-                                       return null;
+                                       //
+                                       // A variable is considered definitely assigned if you take its address.
+                                       //
+                                       vi.SetAssigned (ec);
                                }
-                               lr.local_info.AddressTaken = true;
-                               lr.local_info.Used = true;
-                       }
 
-                       ParameterReference pr = Expr as ParameterReference;
-                       if ((pr != null) && pr.IsHoisted) {
-                               AnonymousMethodBody.Error_AddressOfCapturedVar (pr.Name, loc);
-                               return null;
+                               is_fixed = vr.IsFixedVariable;
+                               vr.SetHasAddressTaken ();
+
+                               if (vr.IsHoisted) {
+                                       AnonymousMethodExpression.Error_AddressOfCapturedVar (vr, loc);
+                               }
+                       } else {
+                               //
+                               // A pointer-indirection is always fixed
+                               //
+                               is_fixed = Expr is Indirection;
                        }
 
-                       // According to the specs, a variable is considered definitely assigned if you take
-                       // its address.
-                       if ((variable != null) && (variable.VariableInfo != null)) {
-                               variable.VariableInfo.SetAssigned (ec);
+                       if (!is_fixed && !ec.InFixedInitializer) {
+                               Error (212, "You can only take the address of unfixed expression inside of a fixed statement initializer");
                        }
 
                        type = TypeManager.GetPointerType (Expr.Type);
@@ -780,7 +754,7 @@ namespace Mono.CSharp {
        // after semantic analysis (this is so we can take the address
        // of an indirection).
        //
-       public class Indirection : Expression, IMemoryLocation, IAssignMethod, IVariable {
+       public class Indirection : Expression, IMemoryLocation, IAssignMethod {
                Expression expr;
                LocalTemporary temporary;
                bool prepared;
@@ -797,6 +771,12 @@ namespace Mono.CSharp {
                        return null;
                }
                
+               protected override void CloneTo (CloneContext clonectx, Expression t)
+               {
+                       Indirection target = (Indirection) t;
+                       target.expr = expr.Clone (clonectx);
+               }               
+               
                public override void Emit (EmitContext ec)
                {
                        if (!prepared)
@@ -863,30 +843,20 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       if (expr.Type == TypeManager.void_ptr_type) {
+                               Error (242, "The operation in question is undefined on void pointers");
+                               return null;
+                       }
+
                        type = TypeManager.GetElementType (expr.Type);
                        eclass = ExprClass.Variable;
                        return this;
                }
-               
+
                public override string ToString ()
                {
                        return "*(" + expr + ")";
                }
-
-               #region IVariable Members
-
-               public VariableInfo VariableInfo {
-                       get { return null; }
-               }
-
-               //
-               // A pointer-indirection is always fixed.
-               //              
-               public bool IsFixed {
-                       get { return true; }
-               }               
-
-               #endregion
        }
        
        /// <summary>
@@ -966,12 +936,12 @@ namespace Mono.CSharp {
 
                Expression ResolveOperator (EmitContext ec)
                {
-                       Type expr_type = expr.Type;
+                       type = expr.Type;
 
                        //
                        // Step 1: Perform Operator Overload location
                        //
-                       Expression mg;
+                       MethodGroupExpr mg;
                        string op_name;
                        
                        if (mode == Mode.PreIncrement || mode == Mode.PostIncrement)
@@ -979,17 +949,24 @@ namespace Mono.CSharp {
                        else
                                op_name = Operator.GetMetadataName (Operator.OpType.Decrement);
 
-                       mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
+                       mg = MemberLookup (ec.ContainerType, type, op_name, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
 
                        if (mg != null) {
-                               method = UserOperatorCall.MakeSimpleCall (
-                                       ec, (MethodGroupExpr) mg, expr, loc);
+                               ArrayList args = new ArrayList (1);
+                               args.Add (new Argument (expr, Argument.AType.Expression));
+                               mg = mg.OverloadResolve (ec, ref args, false, loc);
+                               if (mg == null)
+                                       return null;
 
-                               type = method.Type;
-                       } else if (!IsIncrementableNumber (expr_type)) {
+                               method = new UserOperatorCall (mg, args, null, loc);
+                               Convert.ImplicitConversionRequired (ec, method, type, loc);
+                               return this;
+                       }
+
+                       if (!IsIncrementableNumber (type)) {
                                Error (187, "No such operator '" + OperName (mode) + "' defined for type '" +
-                                      TypeManager.CSharpName (expr_type) + "'");
-                                  return null;
+                                          TypeManager.CSharpName (type) + "'");
+                               return null;
                        }
 
                        //
@@ -997,20 +974,10 @@ namespace Mono.CSharp {
                        // should be an expression that is classified as a variable,
                        // a property access or an indexer access
                        //
-                       type = expr_type;
-                       if (expr.eclass == ExprClass.Variable){
-                               LocalVariableReference var = expr as LocalVariableReference;
-                               if ((var != null) && var.IsReadOnly) {
-                                       Error (1604, "cannot assign to `" + var.Name + "' because it is readonly");
-                                       return null;
-                               }
-                       } else if (expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess){
-                               expr = expr.ResolveLValue (ec, this, Location);
-                               if (expr == null)
-                                       return null;
+                       if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) {
+                               expr = expr.ResolveLValue (ec, expr, Location);
                        } else {
                                Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer");
-                               return null;
                        }
 
                        return this;
@@ -1175,6 +1142,11 @@ namespace Mono.CSharp {
                        expr = expr.Resolve (ec);
                        if (expr == null)
                                return null;
+
+                       if ((probe_type_expr.Type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
+                               Report.Error (-244, loc, "The `{0}' operator cannot be applied to an operand of a static type",
+                                       OperatorName);
+                       }
                        
                        if (expr.Type.IsPointer || probe_type_expr.Type.IsPointer) {
                                Report.Error (244, loc, "The `{0}' operator cannot be applied to an operand of pointer type",
@@ -1274,14 +1246,14 @@ namespace Mono.CSharp {
                        Type d = expr.Type;
                        bool d_is_nullable = false;
 
-                       if (expr is Constant) {
-                               //
-                               // If E is a method group or the null literal, of if the type of E is a reference
-                               // type or a nullable type and the value of E is null, the result is false
-                               //
-                               if (expr.IsNull)
-                                       return CreateConstantResult (false);
-                       } else if (TypeManager.IsNullableType (d) && !TypeManager.ContainsGenericParameters (d)) {
+                       //
+                       // If E is a method group or the null literal, or if the type of E is a reference
+                       // type or a nullable type and the value of E is null, the result is false
+                       //
+                       if (expr.IsNull || expr.eclass == ExprClass.MethodGroup)
+                               return CreateConstantResult (false);
+
+                       if (TypeManager.IsNullableType (d) && !TypeManager.ContainsGenericParameters (d)) {
                                d = TypeManager.GetTypeArguments (d) [0];
                                d_is_nullable = true;
                        }
@@ -1353,10 +1325,12 @@ namespace Mono.CSharp {
                                        return CreateConstantResult (false);
 
                                if (constraints.IsValueType && !d.IsValueType)
-                                       return CreateConstantResult (false);
+                                       return CreateConstantResult (TypeManager.IsEqual (d, t));
                        }
 
-                       expr = new BoxedCast (expr, d);
+                       if (!TypeManager.IsReferenceType (expr.Type))
+                               expr = new BoxedCast (expr, d);
+
                        return this;
 #else
                        return null;
@@ -1403,13 +1377,6 @@ namespace Mono.CSharp {
 #endif
                }
 
-               static void Error_CannotConvertType (Type source, Type target, Location loc)
-               {
-                       Report.Error (39, loc, "Cannot convert type `{0}' to `{1}' via a built-in conversion",
-                               TypeManager.CSharpName (source),
-                               TypeManager.CSharpName (target));
-               }
-               
                public override Expression DoResolve (EmitContext ec)
                {
                        if (resolved_type == null) {
@@ -1423,38 +1390,19 @@ namespace Mono.CSharp {
                        eclass = ExprClass.Value;
                        Type etype = expr.Type;
 
-                       if (type.IsValueType && !TypeManager.IsNullableType (type)) {
-                               Report.Error (77, loc, "The `as' operator cannot be used with a non-nullable value type `{0}'",
-                                             TypeManager.CSharpName (type));
-                               return null;
-                       
-                       }
-
-#if GMCS_SOURCE
-                       //
-                       // If the type is a type parameter, ensure
-                       // that it is constrained by a class
-                       //
-                       TypeParameterExpr tpe = probe_type_expr as TypeParameterExpr;
-                       if (tpe != null){
-                               GenericConstraints constraints = tpe.TypeParameter.GenericConstraints;
-                               bool error = false;
-                               
-                               if (constraints == null)
-                                       error = true;
-                               else {
-                                       if (!constraints.HasClassConstraint)
-                                               if ((constraints.Attributes & GenericParameterAttributes.ReferenceTypeConstraint) == 0)
-                                                       error = true;
-                               }
-                               if (error){
+                       if (!TypeManager.IsReferenceType (type) && !TypeManager.IsNullableType (type)) {
+                               if (probe_type_expr is TypeParameterExpr) {
                                        Report.Error (413, loc,
-                                                     "The as operator requires that the `{0}' type parameter be constrained by a class",
-                                                     probe_type_expr.GetSignatureForError ());
-                                       return null;
+                                               "The `as' operator cannot be used with a non-reference type parameter `{0}'",
+                                               probe_type_expr.GetSignatureForError ());
+                               } else {
+                                       Report.Error (77, loc,
+                                               "The `as' operator cannot be used with a non-nullable value type `{0}'",
+                                               TypeManager.CSharpName (type));
                                }
+                               return null;
                        }
-#endif
+
                        if (expr.IsNull && TypeManager.IsNullableType (type)) {
                                return Nullable.LiftedNull.CreateFromExpression (this);
                        }
@@ -1481,7 +1429,9 @@ namespace Mono.CSharp {
                                return this;
                        }
 
-                       Error_CannotConvertType (etype, type, loc);
+                       Report.Error (39, loc, "Cannot convert type `{0}' to `{1}' via a built-in conversion",
+                               TypeManager.CSharpName (etype), TypeManager.CSharpName (type));
+
                        return null;
                }
 
@@ -1489,9 +1439,9 @@ namespace Mono.CSharp {
                        get { return "as"; }
                }
        
-               public override bool GetAttributableValue (Type value_type, out object value)
+               public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value)
                {
-                       return expr.GetAttributableValue (value_type, out value);
+                       return expr.GetAttributableValue (ec, value_type, out value);
                }
        }
        
@@ -1515,9 +1465,6 @@ 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 {
@@ -1610,23 +1557,24 @@ namespace Mono.CSharp {
 
                        type = texpr.Type;
 
-                       if (type == TypeManager.void_type) {
-                               Error_VoidInvalidInTheContext (loc);
-                               return null;
+                       if ((type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
+                               Report.Error (-244, loc, "The `default value' operator cannot be applied to an operand of a static type");
                        }
 
-                       if (TypeManager.IsGenericParameter (type)) {
-                               GenericConstraints constraints = TypeManager.GetTypeParameterConstraints(type);
-                               if (constraints != null && constraints.IsReferenceType)
-                                       return new EmptyConstantCast (new NullLiteral (Location), type);
-                       } else {
-                               Constant c = New.Constantify (type);
-                               if (c != null)
-                                       return c;
+                       if (type.IsPointer)
+                               return new NullLiteral (Location).ConvertImplicitly (type);
+
+                       if (TypeManager.IsReferenceType (type)) {
+                               return new EmptyConstantCast (new NullLiteral (Location), type);
 
-                               if (!TypeManager.IsValueType (type))
-                                       return new EmptyConstantCast (new NullLiteral (Location), type);
+                               // TODO: ET needs
+                               // return ReducedExpression.Create (new NullLiteral (Location), this);
                        }
+
+                       Constant c = New.Constantify (type);
+                       if (c != null)
+                               return c;
+
                        eclass = ExprClass.Variable;
                        return this;
                }
@@ -1726,7 +1674,7 @@ namespace Mono.CSharp {
                                        Convert.ImplicitConversionExists (ec, rexpr, right);
                        }
 
-                       public PredefinedOperator ResolveBetterOperator (EmitContext ec, Expression lexpr, Expression rexpr, PredefinedOperator best_operator)
+                       public PredefinedOperator ResolveBetterOperator (EmitContext ec, PredefinedOperator best_operator)
                        {
                                int result = 0;
                                if (left != null && best_operator.left != null) {
@@ -1736,7 +1684,7 @@ namespace Mono.CSharp {
                                //
                                // When second arguments are same as the first one, the result is same
                                //
-                               if (left != right || best_operator.left != best_operator.right) {
+                               if (right != null && (left != right || best_operator.left != best_operator.right)) {
                                        result |= MethodGroupExpr.BetterTypeConversion (ec, best_operator.right, right);
                                }
 
@@ -1818,6 +1766,11 @@ namespace Mono.CSharp {
                        {
                        }
 
+                       public PredefinedPointerOperator (Type ltype, Type rtype, Operator op_mask, Type retType)
+                               : base (ltype, rtype, op_mask, retType)
+                       {
+                       }
+
                        public PredefinedPointerOperator (Type type, Operator op_mask, Type return_type)
                                : base (type, op_mask, return_type)
                        {
@@ -1854,8 +1807,9 @@ namespace Mono.CSharp {
 
                                Type r_type = ReturnType;
                                if (r_type == null) {
-                                       r_type = b.left.Type;
-                                       if (r_type == null)
+                                       if (left == null)
+                                               r_type = b.left.Type;
+                                       else 
                                                r_type = b.right.Type;
                                }
 
@@ -2373,10 +2327,10 @@ namespace Mono.CSharp {
                        // T* operator + (long y,  T *x);
                        // T* operator + (ulong y, T *x);
                        //
-                       temp.Add (new PredefinedPointerOperator (TypeManager.int32_type, null, Operator.AdditionMask));
-                       temp.Add (new PredefinedPointerOperator (TypeManager.uint32_type, null, Operator.AdditionMask));
-                       temp.Add (new PredefinedPointerOperator (TypeManager.int64_type, null, Operator.AdditionMask));
-                       temp.Add (new PredefinedPointerOperator (TypeManager.uint64_type, null, Operator.AdditionMask));
+                       temp.Add (new PredefinedPointerOperator (TypeManager.int32_type, null, Operator.AdditionMask, null));
+                       temp.Add (new PredefinedPointerOperator (TypeManager.uint32_type, null, Operator.AdditionMask, null));
+                       temp.Add (new PredefinedPointerOperator (TypeManager.int64_type, null, Operator.AdditionMask, null));
+                       temp.Add (new PredefinedPointerOperator (TypeManager.uint64_type, null, Operator.AdditionMask, null));
 
                        //
                        // long operator - (T* x, T *y)
@@ -2586,13 +2540,14 @@ namespace Mono.CSharp {
                                                return null;
                                        }
 
-                                       if (rc != null) {
-                                               right = left;
-                                               lc = rc;
-                                       }
-
+                                       //
                                        // The result is a constant with side-effect
-                                       return new SideEffectConstant (lc, right, loc);
+                                       //
+                                       Constant side_effect = rc == null ?
+                                               new SideEffectConstant (lc, right, loc) :
+                                               new SideEffectConstant (rc, left, loc);
+
+                                       return ReducedExpression.Create (side_effect, this);
                                }
                        }
 
@@ -2725,6 +2680,23 @@ namespace Mono.CSharp {
                        Expression ltemp = left;
                        Expression rtemp = right;
                        Type underlying_type;
+                       Expression expr;
+                       
+                       if ((oper & Operator.ComparisonMask | Operator.BitwiseMask) != 0) {
+                               if (renum) {
+                                       expr = Convert.ImplicitConversion (ec, left, rtype, loc);
+                                       if (expr != null) {
+                                               left = expr;
+                                               ltype = expr.Type;
+                                       }
+                               } else if (lenum) {
+                                       expr = Convert.ImplicitConversion (ec, right, ltype, loc);
+                                       if (expr != null) {
+                                               right = expr;
+                                               rtype = expr.Type;
+                                       }
+                               }
+                       }                       
 
                        if (TypeManager.IsEqual (ltype, rtype)) {
                                underlying_type = TypeManager.GetEnumUnderlyingType (ltype);
@@ -2804,7 +2776,7 @@ namespace Mono.CSharp {
                                        res_type = ltype;
                        }
                        
-                       Expression expr = ResolveOperatorPredefined (ec, standard_operators, true, res_type);
+                       expr = ResolveOperatorPredefined (ec, standard_operators, true, res_type);
                        if (!is_compound || expr == null)
                                return expr;
 
@@ -3008,7 +2980,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               best_operator = po.ResolveBetterOperator (ec, left, right, best_operator);
+                               best_operator = po.ResolveBetterOperator (ec, best_operator);
 
                                if (best_operator == null) {
                                        Report.Error (34, loc, "Operator `{0}' is ambiguous on operands of type `{1}' and `{2}'",
@@ -3184,7 +3156,7 @@ namespace Mono.CSharp {
                                WarnUselessComparison (type);
                }
 
-               private bool IsValueOutOfRange (long value, Type type)
+               static bool IsValueOutOfRange (long value, Type type)
                {
                        if (IsTypeUnsigned (type) && value < 0)
                                return true;
@@ -3325,7 +3297,8 @@ namespace Mono.CSharp {
                        right.Emit (ec);
 
                        Type t = left.Type;
-                       bool is_unsigned = IsUnsigned (t) || IsFloat (t);
+                       bool is_float = IsFloat (t);
+                       bool is_unsigned = is_float || IsUnsigned (t);
                        
                        switch (oper){
                        case Operator.Equality:
@@ -3344,7 +3317,7 @@ namespace Mono.CSharp {
 
                        case Operator.LessThan:
                                if (on_true)
-                                       if (is_unsigned)
+                                       if (is_unsigned && !is_float)
                                                ig.Emit (OpCodes.Blt_Un, target);
                                        else
                                                ig.Emit (OpCodes.Blt, target);
@@ -3357,7 +3330,7 @@ namespace Mono.CSharp {
 
                        case Operator.GreaterThan:
                                if (on_true)
-                                       if (is_unsigned)
+                                       if (is_unsigned && !is_float)
                                                ig.Emit (OpCodes.Bgt_Un, target);
                                        else
                                                ig.Emit (OpCodes.Bgt, target);
@@ -3370,7 +3343,7 @@ namespace Mono.CSharp {
 
                        case Operator.LessThanOrEqual:
                                if (on_true)
-                                       if (is_unsigned)
+                                       if (is_unsigned && !is_float)
                                                ig.Emit (OpCodes.Ble_Un, target);
                                        else
                                                ig.Emit (OpCodes.Ble, target);
@@ -3384,7 +3357,7 @@ namespace Mono.CSharp {
 
                        case Operator.GreaterThanOrEqual:
                                if (on_true)
-                                       if (is_unsigned)
+                                       if (is_unsigned && !is_float)
                                                ig.Emit (OpCodes.Bge_Un, target);
                                        else
                                                ig.Emit (OpCodes.Bge, target);
@@ -3673,6 +3646,12 @@ namespace Mono.CSharp {
                        if (concat != null)
                                concat.Emit (ec);
                }
+               
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       foreach (Argument a in arguments)
+                               a.Expr.MutateHoistedGenericType (storey);
+               }               
        }
 
        //
@@ -3693,7 +3672,7 @@ namespace Mono.CSharp {
                {
                        MethodInfo method = (MethodInfo)mg;
                        type = TypeManager.TypeToCoreType (method.ReturnType);
-                       ParameterData pd = TypeManager.GetParameterData (method);
+                       AParametersCollection pd = TypeManager.GetParameterData (method);
                        if (!TypeManager.IsEqual (type, type) || !TypeManager.IsEqual (type, pd.Types [0]) || !TypeManager.IsEqual (type, pd.Types [1])) {
                                Report.Error (217, loc,
                                        "A user-defined operator `{0}' must have parameters and return values of the same type in order to be applicable as a short circuit operator",
@@ -3774,14 +3753,21 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        
                        // It must be either array or fixed buffer
-                       Type element = TypeManager.HasElementType (op_type) ?
-                               element = TypeManager.GetElementType (op_type) :
-                               element = AttributeTester.GetFixedBuffer (((FieldExpr)left).FieldInfo).ElementType;
+                       Type element;
+                       if (TypeManager.HasElementType (op_type)) {
+                               element = TypeManager.GetElementType (op_type);
+                       } else {
+                               FieldExpr fe = left as FieldExpr;
+                               if (fe != null)
+                                       element = AttributeTester.GetFixedBuffer (fe.FieldInfo).ElementType;
+                               else
+                                       element = op_type;
+                       }
 
                        int size = GetTypeSize (element);
                        Type rtype = right.Type;
                        
-                       if (rtype.IsPointer){
+                       if ((op & Binary.Operator.SubtractionMask) != 0 && rtype.IsPointer){
                                //
                                // handle (pointer - pointer)
                                //
@@ -3918,54 +3904,46 @@ namespace Mono.CSharp {
                                return null;
 
                        eclass = ExprClass.Value;
-                       if (true_expr.Type == false_expr.Type) {
-                               type = true_expr.Type;
-                               if (type == TypeManager.null_type) {
-                                       // TODO: probably will have to implement ConditionalConstant
-                                       // to call method without return constant as well
-                                       Report.Warning (-101, 1, loc, "Conditional expression will always return same value");
-                                       return true_expr;
-                               }
-                       } else {
-                               Expression conv;
-                               Type true_type = true_expr.Type;
-                               Type false_type = false_expr.Type;
+                       Type true_type = true_expr.Type;
+                       Type false_type = false_expr.Type;
+                       type = true_type;
 
-                               //
-                               // First, if an implicit conversion exists from true_expr
-                               // to false_expr, then the result type is of type false_expr.Type
-                               //
-                               conv = Convert.ImplicitConversion (ec, true_expr, false_type, loc);
-                               if (conv != null){
+                       //
+                       // First, if an implicit conversion exists from true_expr
+                       // to false_expr, then the result type is of type false_expr.Type
+                       //
+                       if (!TypeManager.IsEqual (true_type, false_type)) {
+                               Expression conv = Convert.ImplicitConversion (ec, true_expr, false_type, loc);
+                               if (conv != null) {
                                        //
                                        // Check if both can convert implicitl to each other's type
                                        //
-                                       if (Convert.ImplicitConversion (ec, false_expr, true_type, loc) != null){
+                                       if (Convert.ImplicitConversion (ec, false_expr, true_type, loc) != null) {
                                                Error (172,
-                                                      "Can not compute type of conditional expression " +
-                                                      "as `" + TypeManager.CSharpName (true_expr.Type) +
-                                                      "' and `" + TypeManager.CSharpName (false_expr.Type) +
-                                                      "' convert implicitly to each other");
+                                                          "Can not compute type of conditional expression " +
+                                                          "as `" + TypeManager.CSharpName (true_expr.Type) +
+                                                          "' and `" + TypeManager.CSharpName (false_expr.Type) +
+                                                          "' convert implicitly to each other");
                                                return null;
                                        }
                                        type = false_type;
                                        true_expr = conv;
-                               } else if ((conv = Convert.ImplicitConversion(ec, false_expr, true_type,loc))!= null){
-                                       type = true_type;
+                               } else if ((conv = Convert.ImplicitConversion (ec, false_expr, true_type, loc)) != null) {
                                        false_expr = conv;
                                } else {
-                                       Report.Error (173, loc, "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'",
+                                       Report.Error (173, loc,
+                                               "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'",
                                                true_expr.GetSignatureForError (), false_expr.GetSignatureForError ());
                                        return null;
                                }
-                       }
+                       }                       
 
                        // Dead code optimalization
-                       if (expr is BoolConstant){
-                               BoolConstant bc = (BoolConstant) expr;
-
-                               Report.Warning (429, 4, bc.Value ? false_expr.Location : true_expr.Location, "Unreachable expression code detected");
-                               return bc.Value ? true_expr : false_expr;
+                       Constant c = expr as Constant;
+                       if (c != null){
+                               bool is_false = c.IsDefaultValue;
+                               Report.Warning (429, 4, is_false ? true_expr.Location : false_expr.Location, "Unreachable expression code detected");
+                               return ReducedExpression.Create (is_false ? false_expr : true_expr, this).Resolve (ec);
                        }
 
                        return this;
@@ -4016,13 +3994,15 @@ namespace Mono.CSharp {
                }
        }
 
-       public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
+       public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation, IVariableReference {
                LocalTemporary temp;
 
                #region Abstract
                public abstract HoistedVariable HoistedVariable { get; }
-               public abstract bool IsFixed { get; }
+               public abstract bool IsFixedVariable { get; }
                public abstract bool IsRef { get; }
+               public abstract string Name { get; }
+               public abstract void SetHasAddressTaken ();
 
                //
                // Variable IL data, it has to be protected to encapsulate hoisted variables
@@ -4106,8 +4086,6 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       ILGenerator ig = ec.ig;
-
                        if (IsRef)
                                Variable.Emit (ec);
 
@@ -4122,7 +4100,7 @@ namespace Mono.CSharp {
                        }
 
                        if (leave_copy) {
-                               ig.Emit (OpCodes.Dup);
+                               ec.ig.Emit (OpCodes.Dup);
                                if (IsRef) {
                                        temp = new LocalTemporary (Type);
                                        temp.Store (ec);
@@ -4130,7 +4108,7 @@ namespace Mono.CSharp {
                        }
 
                        if (IsRef)
-                               StoreFromPtr (ig, type);
+                               StoreFromPtr (ec.ig, type);
                        else
                                Variable.EmitAssign (ec);
 
@@ -4162,7 +4140,7 @@ namespace Mono.CSharp {
        ///   Local variables
        /// </summary>
        public class LocalVariableReference : VariableReference {
-               public readonly string Name;
+               readonly string name;
                public Block Block;
                public LocalInfo local_info;
                bool is_readonly;
@@ -4170,7 +4148,7 @@ namespace Mono.CSharp {
                public LocalVariableReference (Block block, string name, Location l)
                {
                        Block = block;
-                       Name = name;
+                       this.name = name;
                        loc = l;
                        eclass = ExprClass.Variable;
                }
@@ -4196,9 +4174,9 @@ namespace Mono.CSharp {
                }
 
                //              
-               // A local Variable is always fixed.
+               // A local variable is always fixed
                //
-               public override bool IsFixed {
+               public override bool IsFixedVariable {
                        get { return true; }
                }
 
@@ -4210,6 +4188,10 @@ namespace Mono.CSharp {
                        get { return is_readonly; }
                }
 
+               public override string Name {
+                       get { return name; }
+               }
+
                public bool VerifyAssigned (EmitContext ec)
                {
                        VariableInfo variable_info = local_info.VariableInfo;
@@ -4225,6 +4207,11 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override void SetHasAddressTaken ()
+               {
+                       local_info.AddressTaken = true;
+               }
+
                public override Expression CreateExpressionTree (EmitContext ec)
                {
                        ArrayList arg = new ArrayList (1);
@@ -4247,12 +4234,10 @@ namespace Mono.CSharp {
                        // flag it for capturing
                        //
                        if (ec.MustCaptureVariable (local_info)) {
-                               if (local_info.AddressTaken){
-                                       AnonymousMethodBody.Error_AddressOfCapturedVar (local_info.Name, loc);
-                                       return null;
-                               }
+                               if (local_info.AddressTaken)
+                                       AnonymousMethodExpression.Error_AddressOfCapturedVar (this, loc);
 
-                               if (!ec.IsInProbingMode) {
+                               if (ec.IsVariableCapturingRequired) {
                                        AnonymousMethodStorey storey = local_info.Block.Explicit.CreateAnonymousMethodStorey (ec);
                                        storey.CaptureLocalVariable (ec, local_info);
                                }
@@ -4302,15 +4287,15 @@ namespace Mono.CSharp {
                                        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 if (right_side == EmptyExpression.UnaryAddress) {
+                                       code = 459; msg = "Cannot take the address of {1} `{0}'";
                                } else {
                                        code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'";
                                }
                                Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ());
-                               return null;
-                       }
-
-                       if (VariableInfo != null)
+                       } else if (VariableInfo != null) {
                                VariableInfo.SetAssigned (ec);
+                       }
 
                        return DoResolveBase (ec);
                }
@@ -4376,13 +4361,14 @@ namespace Mono.CSharp {
                }
 
                //
-               // A parameter is fixed if it's a value parameter (i.e., no modifier like out, ref, param).
+               // A ref or out parameter is classified as a moveable variable, even 
+               // if the argument given for the parameter is a fixed variable
                //              
-               public override bool IsFixed {
-                       get { return pi.Parameter.ModFlags == Parameter.Modifier.NONE; }
+               public override bool IsFixedVariable {
+                       get { return !IsRef; }
                }
 
-               public string Name {
+               public override string Name {
                        get { return Parameter.Name; }
                }
 
@@ -4410,7 +4396,12 @@ namespace Mono.CSharp {
                        Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name);
                        return false;
                }
-               
+
+               public override void SetHasAddressTaken ()
+               {
+                       Parameter.HasAddressTaken = true;
+               }
+
                void SetAssigned (EmitContext ec)
                {
                        if (HasOutModifier && ec.DoFlowAnalysis)
@@ -4419,8 +4410,7 @@ namespace Mono.CSharp {
 
                bool DoResolveBase (EmitContext ec)
                {
-                       Parameter par = Parameter;
-                       type = par.ParameterType;
+                       type = pi.ParameterType;
                        eclass = ExprClass.Variable;
 
                        AnonymousExpression am = ec.CurrentAnonymousMethod;
@@ -4432,7 +4422,7 @@ namespace Mono.CSharp {
                                if (IsRef) {
                                        Report.Error (1628, loc,
                                                "Parameter `{0}' cannot be used inside `{1}' when using `ref' or `out' modifier",
-                                               par.Name, am.ContainerType);
+                                               Name, am.ContainerType);
                                        return false;
                                }
                        } else {
@@ -4440,8 +4430,10 @@ namespace Mono.CSharp {
                                        return true;
                        }
 
-                       // Don't capture parameters when the probing is on
-                       if (!ec.IsInProbingMode) {
+                       if (ec.IsVariableCapturingRequired) {
+                               if (pi.Parameter.HasAddressTaken)
+                                       AnonymousMethodExpression.Error_AddressOfCapturedVar (this, loc);
+
                                AnonymousMethodStorey storey = declared.CreateAnonymousMethodStorey (ec);
                                storey.CaptureParameter (ec, this);
                        }
@@ -4525,11 +4517,6 @@ namespace Mono.CSharp {
                        } else
                                ig.Emit (OpCodes.Ldarg, x);
                }
-               
-               public override string ToString ()
-               {
-                       return "ParameterReference[" + Name + "]";
-               }
        }
        
        /// <summary>
@@ -4561,12 +4548,7 @@ namespace Mono.CSharp {
                }
 
                public Type Type {
-                       get {
-                               if (ArgType == AType.Ref || ArgType == AType.Out)
-                                       return TypeManager.GetReferenceType (Expr.Type);
-                               else
-                                       return Expr.Type;
-                       }
+                       get { return Expr.Type; }
                }
 
                public Parameter.Modifier Modifier
@@ -4590,7 +4572,7 @@ namespace Mono.CSharp {
                        if (Expr.eclass == ExprClass.MethodGroup)
                                return Expr.ExprClassName;
 
-                       return Expr.GetSignatureForError ();
+                       return TypeManager.CSharpName (Expr.Type);
                }               
 
                public bool ResolveMethodGroup (EmitContext ec)
@@ -4829,9 +4811,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       if (IsSpecialMethodInvocation (method)) {
-                               return null;
-                       }
+                       IsSpecialMethodInvocation (method, loc);
                        
                        if (mg.InstanceExpression != null)
                                mg.InstanceExpression.CheckMarshalByRefAccess (ec);
@@ -4845,7 +4825,7 @@ namespace Mono.CSharp {
                        return mg.OverloadResolve (ec, ref Arguments, false, loc);
                }
 
-               bool IsSpecialMethodInvocation (MethodBase method)
+               public static bool IsSpecialMethodInvocation (MethodBase method, Location loc)
                {
                        if (!TypeManager.IsSpecialMethod (method))
                                return false;
@@ -4906,11 +4886,8 @@ namespace Mono.CSharp {
 
                static Type[] GetVarargsTypes (MethodBase mb, ArrayList arguments)
                {
-                       ParameterData pd = TypeManager.GetParameterData (mb);
-
-                       if (arguments == null)
-                               return new Type [0];
-
+                       AParametersCollection pd = TypeManager.GetParameterData (mb);
+                       
                        Argument a = (Argument) arguments [pd.Count - 1];
                        Arglist list = (Arglist) a.Expr;
 
@@ -4920,7 +4897,7 @@ namespace Mono.CSharp {
                /// <summary>
                /// This checks the ConditionalAttribute on the method 
                /// </summary>
-               public static bool IsMethodExcluded (MethodBase method)
+               public static bool IsMethodExcluded (MethodBase method, Location loc)
                {
                        if (method.IsConstructor)
                                return false;
@@ -4936,7 +4913,7 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       return AttributeTester.IsConditionalMethodExcluded (method);
+                       return AttributeTester.IsConditionalMethodExcluded (method, loc);
                }
 
                /// <remarks>
@@ -4993,7 +4970,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (IsMethodExcluded (method))
+                       if (IsMethodExcluded (method, loc))
                                return;
                        
                        bool is_static = method.IsStatic;
@@ -5135,6 +5112,9 @@ namespace Mono.CSharp {
                }
        }
 
+       //
+       // It's either a cast or delegate invocation
+       //
        public class InvocationOrCast : ExpressionStatement
        {
                Expression expr;
@@ -5153,14 +5133,22 @@ namespace Mono.CSharp {
                }
 
                public override Expression DoResolve (EmitContext ec)
+               {
+                       Expression e = ResolveCore (ec);
+                       if (e == null)
+                               return null;
+
+                       return e.Resolve (ec);
+               }
+
+               Expression ResolveCore (EmitContext ec)
                {
                        //
                        // First try to resolve it as a cast.
                        //
-                       TypeExpr te = expr.ResolveAsTypeTerminal (ec, true);
-                       if ((te != null) && (te.eclass == ExprClass.Type)) {
-                               Cast cast = new Cast (te, argument, loc);
-                               return cast.Resolve (ec);
+                       TypeExpr te = expr.ResolveAsBaseTerminal (ec, true);
+                       if (te != null) {
+                               return new Cast (te, argument, loc);
                        }
 
                        //
@@ -5174,11 +5162,15 @@ namespace Mono.CSharp {
                        //
                        // Ok, so it's a Cast.
                        //
-                       if (expr.eclass == ExprClass.Type) {
-                               Cast cast = new Cast (new TypeExpression (expr.Type, loc), argument, loc);
-                               return cast.Resolve (ec);
+                       if (expr.eclass == ExprClass.Type || expr.eclass == ExprClass.TypeParameter) {
+                               return new Cast (expr, argument, loc);
                        }
 
+                       if (expr.eclass == ExprClass.Namespace) {
+                               expr.Error_UnexpectedKind (null, "type", loc);
+                               return null;
+                       }                       
+
                        //
                        // It's a delegate invocation.
                        //
@@ -5187,45 +5179,24 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       ArrayList args = new ArrayList ();
+                       ArrayList args = new ArrayList (1);
                        args.Add (new Argument (argument, Argument.AType.Expression));
-                       DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
-                       return invocation.Resolve (ec);
+                       return new DelegateInvocation (expr, args, loc);
                }
 
                public override ExpressionStatement ResolveStatement (EmitContext ec)
                {
-                       //
-                       // First try to resolve it as a cast.
-                       //
-                       TypeExpr te = expr.ResolveAsTypeTerminal (ec, true);
-                       if ((te != null) && (te.eclass == ExprClass.Type)) {
-                               Error_InvalidExpressionStatement ();
+                       Expression e = ResolveCore (ec);
+                       if (e == null)
                                return null;
-                       }
 
-                       //
-                       // This can either be a type or a delegate invocation.
-                       // Let's just resolve it and see what we'll get.
-                       //
-                       expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
-                       if ((expr == null) || (expr.eclass == ExprClass.Type)) {
+                       ExpressionStatement s = e as ExpressionStatement;
+                       if (s == null) {
                                Error_InvalidExpressionStatement ();
                                return null;
                        }
 
-                       //
-                       // It's a delegate invocation.
-                       //
-                       if (!TypeManager.IsDelegateType (expr.Type)) {
-                               Error (149, "Method name expected");
-                               return null;
-                       }
-
-                       ArrayList args = new ArrayList ();
-                       args.Add (new Argument (argument, Argument.AType.Expression));
-                       DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
-                       return invocation.ResolveStatement (ec);
+                       return s.ResolveStatement (ec);
                }
 
                public override void Emit (EmitContext ec)
@@ -5251,13 +5222,11 @@ namespace Mono.CSharp {
        // This class is used to "disable" the code generation for the
        // temporary variable when initializing value types.
        //
-       class EmptyAddressOf : EmptyExpression, IMemoryLocation {
+       sealed class EmptyAddressOf : EmptyExpression, IMemoryLocation {
                public void AddressOf (EmitContext ec, AddressOp Mode)
                {
                        // nothing
                }
-               
-               public bool IsFixed { get { return true; } }
        }
        
        /// <summary>
@@ -5433,11 +5402,6 @@ namespace Mono.CSharp {
 
                        type = texpr.Type;
 
-                       if (type == TypeManager.void_type) {
-                               Error_VoidInvalidInTheContext (loc);
-                               return null;
-                       }
-
                        if (type.IsPointer) {
                                Report.Error (1919, loc, "Unsafe type `{0}' cannot be used in an object creation expression",
                                        TypeManager.CSharpName (type));
@@ -5786,7 +5750,7 @@ namespace Mono.CSharp {
                        this.rank = rank;
                        loc = l;
 
-                       arguments = new ArrayList ();
+                       arguments = new ArrayList (exprs.Count);
 
                        foreach (Expression e in exprs) {
                                arguments.Add (new Argument (e, Argument.AType.Expression));
@@ -5829,7 +5793,7 @@ namespace Mono.CSharp {
 
                                Constant c = a.Expr as Constant;
                                if (c != null) {
-                                       c = c.ImplicitConversionRequired (TypeManager.int32_type, a.Expr.Location);
+                                       c = c.ImplicitConversionRequired (ec, TypeManager.int32_type, a.Expr.Location);
                                }
 
                                if (c == null) {
@@ -5927,8 +5891,13 @@ namespace Mono.CSharp {
                        args = new ArrayList (array_data == null ? 1 : array_data.Count + 1);
                        args.Add (new Argument (new TypeOf (new TypeExpression (array_element_type, loc), loc)));
                        if (array_data != null) {
-                               foreach (Expression e in array_data)
+                               for (int i = 0; i < array_data.Count; ++i) {
+                                       Expression e = (Expression) array_data [i];
+                                       if (e == null)
+                                               e = Convert.ImplicitConversion (ec, (Expression) initializers [i], array_element_type, loc);
+
                                        args.Add (new Argument (e.CreateExpressionTree (ec)));
+                               }
                        }
 
                        return CreateExpressionFactoryCall ("NewArrayInit", args);
@@ -6012,6 +5981,11 @@ namespace Mono.CSharp {
                                Report.Error (622, loc, "Can only use array initializer expressions to assign to array types. Try using a new expression instead");
                                return false;
                        }
+
+                       if (requested_base_type is VarExpr) {
+                               Report.Error (820, loc, "An implicitly typed local variable declarator cannot use an array initializer");
+                               return false;
+                       }
                        
                        StringBuilder array_qualifier = new StringBuilder (rank);
 
@@ -6050,11 +6024,6 @@ namespace Mono.CSharp {
                        if (!ResolveArrayType (ec))
                                return null;
 
-                       if ((array_element_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
-                               Report.Error (719, loc, "`{0}': array elements cannot be of static type",
-                                       TypeManager.CSharpName (array_element_type));
-                       }
-
                        //
                        // First step is to validate the initializers and fill
                        // in any missing bits
@@ -6255,8 +6224,11 @@ namespace Mono.CSharp {
                                foreach (Argument a in arguments)
                                        a.Expr.MutateHoistedGenericType (storey);
                        }
-
-                       // TODO: finish !!
+                       
+                       if (array_data != null) {
+                               foreach (Expression e in array_data)
+                                       e.MutateHoistedGenericType (storey);
+                       }
                }
 
                //
@@ -6415,11 +6387,11 @@ namespace Mono.CSharp {
                                first_emit_temp.Release (ec);
                }
 
-               public override bool GetAttributableValue (Type value_type, out object value)
+               public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value)
                {
                        if (arguments.Count != 1) {
                                // Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays");
-                               return base.GetAttributableValue (null, out value);
+                               return base.GetAttributableValue (ec, null, out value);
                        }
 
                        if (array_data == null) {
@@ -6429,7 +6401,7 @@ namespace Mono.CSharp {
                                        return true;
                                }
                                // Report.Error (-212, Location, "array should be initialized when passing it to an attribute");
-                               return base.GetAttributableValue (null, out value);
+                               return base.GetAttributableValue (ec, null, out value);
                        }
                        
                        Array ret = Array.CreateInstance (array_element_type, array_data.Count);
@@ -6442,7 +6414,7 @@ namespace Mono.CSharp {
                                if (e == null) 
                                        continue;
 
-                               if (!e.GetAttributableValue (array_element_type, out element_value)) {
+                               if (!e.GetAttributableValue (ec, array_element_type, out element_value)) {
                                        value = null;
                                        return false;
                                }
@@ -6510,7 +6482,7 @@ namespace Mono.CSharp {
                        if (array_element_type == null || array_element_type == TypeManager.null_type ||
                                array_element_type == TypeManager.void_type || array_element_type == TypeManager.anonymous_method_type ||
                                arguments.Count != dimensions) {
-                               Report.Error (826, loc, "The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
+                               Error_NoBestType ();
                                return null;
                        }
 
@@ -6526,6 +6498,12 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               void Error_NoBestType ()
+               {
+                       Report.Error (826, loc,
+                               "The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
+               }
+
                //
                // Converts static initializer only
                //
@@ -6558,8 +6536,8 @@ namespace Mono.CSharp {
                                return element;
                        }
 
-                       element.Error_ValueCannotBeConverted (ec, element.Location, array_element_type, false);
-                       return element;
+                       Error_NoBestType ();
+                       return null;
                }
        }       
        
@@ -6597,7 +6575,7 @@ namespace Mono.CSharp {
 
        public class This : VariableReference
        {
-               class ThisVariable : ILocalVariable
+               sealed class ThisVariable : ILocalVariable
                {
                        public static readonly ILocalVariable Instance = new ThisVariable ();
 
@@ -6636,7 +6614,7 @@ namespace Mono.CSharp {
                        get { return variable_info; }
                }
 
-               public override bool IsFixed {
+               public override bool IsFixedVariable {
                        get { return !TypeManager.IsValueType (type); }
                }
 
@@ -6670,8 +6648,25 @@ namespace Mono.CSharp {
                        }
                }
 
+               public static bool IsThisAvailable (EmitContext ec)
+               {
+                       if (ec.IsStatic || ec.IsInFieldInitializer)
+                               return false;
+
+                       if (ec.CurrentAnonymousMethod == null)
+                               return true;
+
+                       if (ec.TypeContainer is Struct && ec.CurrentIterator == null)
+                               return false;
+
+                       return true;
+               }
+
                public bool ResolveBase (EmitContext ec)
                {
+                       if (eclass != ExprClass.Invalid)
+                               return true;
+
                        eclass = ExprClass.Variable;
 
                        if (ec.TypeContainer.CurrentType != null)
@@ -6679,32 +6674,28 @@ 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");
-                               return false;
+                       if (!IsThisAvailable (ec)) {
+                               if (ec.IsStatic) {
+                                       Error (26, "Keyword `this' is not valid in a static property, static method, or static field initializer");
+                               } else {
+                                       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");
+                               }
                        }
 
+                       is_struct = ec.TypeContainer is Struct;
+
                        if (block != null) {
                                if (block.Toplevel.ThisVariable != null)
                                        variable_info = block.Toplevel.ThisVariable.VariableInfo;
 
                                AnonymousExpression am = ec.CurrentAnonymousMethod;
                                if (am != null) {
-                                       if (is_struct && !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.");
-                                       }
-
                                        //
                                        // this is hoisted to very top level block
                                        //
-                                       if (!ec.IsInProbingMode) {
+                                       if (ec.IsVariableCapturingRequired) {
                                                // TODO: it could be optimized
                                                AnonymousMethodStorey scope = TopToplevelBlock.Explicit.CreateAnonymousMethodStorey (ec);
                                                if (HoistedVariable == null) {
@@ -6759,10 +6750,14 @@ namespace Mono.CSharp {
 
                        if (variable_info != null)
                                variable_info.SetAssigned (ec);
-                       
+
                        if (ec.TypeContainer is Class){
-                               Error (1604, "Cannot assign to 'this' because it is read-only");
-                               return null;
+                               if (right_side == EmptyExpression.UnaryAddress)
+                                       Report.Error (459, loc, "Cannot take the address of `this' because it is read-only");
+                               else if (right_side == EmptyExpression.OutAccess)
+                                       Report.Error (1605, loc, "Cannot pass `this' as a ref or out argument because it is read-only");
+                               else
+                                       Report.Error (1604, loc, "Cannot assign to `this' because it is read-only");
                        }
 
                        return this;
@@ -6773,6 +6768,10 @@ namespace Mono.CSharp {
                        return block.GetHashCode ();
                }
 
+               public override string Name {
+                       get { return "this"; }
+               }
+
                public override bool Equals (object obj)
                {
                        This t = obj as This;
@@ -6793,6 +6792,11 @@ namespace Mono.CSharp {
                {
                        TopToplevelBlock.HoistedThisVariable = null;
                }
+
+               public override void SetHasAddressTaken ()
+               {
+                       // Nothing
+               }
        }
 
        /// <summary>
@@ -6888,6 +6892,12 @@ namespace Mono.CSharp {
                                arg.Emit (ec);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       foreach (Argument arg in Arguments)
+                               arg.Expr.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        Arglist target = (Arglist) t;
@@ -6964,7 +6974,7 @@ namespace Mono.CSharp {
                        ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
                }
 
-               public override bool GetAttributableValue (Type value_type, out object value)
+               public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value)
                {
                        if (TypeManager.ContainsGenericParameters (typearg) &&
                                !TypeManager.IsGenericTypeDefinition (typearg)) {
@@ -7191,11 +7201,6 @@ namespace Mono.CSharp {
                        if (TypeManager.IsEnumType (type_queried))
                                type_queried = TypeManager.GetEnumUnderlyingType (type_queried);
 
-                       if (type_queried == TypeManager.void_type) {
-                               Expression.Error_VoidInvalidInTheContext (loc);
-                               return null;
-                       }
-
                        int size_of = GetTypeSize (type_queried);
                        if (size_of > 0) {
                                return new IntConstant (size_of, loc);
@@ -7237,6 +7242,7 @@ namespace Mono.CSharp {
        public class QualifiedAliasMember : MemberAccess
        {
                readonly string alias;
+               public static readonly string GlobalAlias = "global";
 
                public QualifiedAliasMember (string alias, string identifier, TypeArguments targs, Location l)
                        : base (null, identifier, targs, l)
@@ -7252,7 +7258,7 @@ namespace Mono.CSharp {
 
                public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
                {
-                       if (alias == "global") {
+                       if (alias == GlobalAlias) {
                                expr = RootNamespace.Global;
                                return base.ResolveAsTypeStep (ec, silent);
                        }
@@ -7657,7 +7663,7 @@ namespace Mono.CSharp {
                        if (Expr == null)
                                return null;
 
-                       if (Expr is Constant)
+                       if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression)
                                return Expr;
                        
                        eclass = Expr.eclass;
@@ -7677,6 +7683,11 @@ namespace Mono.CSharp {
                                Expr.EmitBranchable (ec, target, on_true);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       Expr.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        CheckedExpr target = (CheckedExpr) t;
@@ -7712,7 +7723,7 @@ namespace Mono.CSharp {
                        if (Expr == null)
                                return null;
 
-                       if (Expr is Constant)
+                       if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression)
                                return Expr;
                        
                        eclass = Expr.eclass;
@@ -7732,6 +7743,11 @@ namespace Mono.CSharp {
                                Expr.EmitBranchable (ec, target, on_true);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       Expr.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        UnCheckedExpr target = (UnCheckedExpr) t;
@@ -7753,16 +7769,14 @@ namespace Mono.CSharp {
                public ElementAccess (Expression e, ArrayList e_list)
                {
                        Expr = e;
-
                        loc  = e.Location;
                        
                        if (e_list == null)
                                return;
                        
-                       Arguments = new ArrayList ();
+                       Arguments = new ArrayList (e_list.Count);
                        foreach (Expression tmp in e_list)
                                Arguments.Add (new Argument (tmp, Argument.AType.Expression));
-                       
                }
 
                bool CommonResolve (EmitContext ec)
@@ -7792,10 +7806,6 @@ namespace Mono.CSharp {
 
                Expression MakePointerAccess (EmitContext ec, Type t)
                {
-                       if (t == TypeManager.void_ptr_type){
-                               Error (242, "The array index operation is not valid on void pointers");
-                               return null;
-                       }
                        if (Arguments.Count != 1){
                                Error (196, "A pointer must be indexed by only one value");
                                return null;
@@ -8245,7 +8255,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       protected override int GetApplicableParametersCount (MethodBase method, ParameterData parameters)
+                       protected override int GetApplicableParametersCount (MethodBase method, AParametersCollection parameters)
                        {
                                //
                                // Here is the trick, decrease number of arguments by 1 when only
@@ -8666,13 +8676,12 @@ namespace Mono.CSharp {
                        Type current_type = ec.ContainerType;
                        Type base_type = current_type.BaseType;
 
-                       if (ec.IsStatic){
-                               Error (1511, "Keyword `base' is not available in a static method");
-                               return null;
-                       }
-
-                       if (ec.IsInFieldInitializer){
-                               Error (1512, "Keyword `base' is not available in the current context");
+                       if (!This.IsThisAvailable (ec)) {
+                               if (ec.IsStatic) {
+                                       Error (1511, "Keyword `base' is not available in a static method");
+                               } else {
+                                       Error (1512, "Keyword `base' is not available in the current context");
+                               }
                                return null;
                        }
                        
@@ -8764,11 +8773,12 @@ namespace Mono.CSharp {
        ///   is needed (the `New' class).
        /// </summary>
        public class EmptyExpression : Expression {
-               public static readonly EmptyExpression Null = new EmptyExpression ();
+               public static readonly Expression Null = new EmptyExpression ();
 
                public static readonly EmptyExpression OutAccess = new EmptyExpression ();
                public static readonly EmptyExpression LValueMemberAccess = new EmptyExpression ();
                public static readonly EmptyExpression LValueMemberOutAccess = new EmptyExpression ();
+               public static readonly EmptyExpression UnaryAddress = new EmptyExpression ();
 
                static EmptyExpression temp = new EmptyExpression ();
                public static EmptyExpression Grab ()
@@ -8904,6 +8914,12 @@ namespace Mono.CSharp {
                        source.Emit (ec);
                        ec.ig.Emit (OpCodes.Call, method);
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       source.MutateHoistedGenericType (storey);
+                       method = storey.MutateGenericMethod (method);
+               }
        }
 
        // <summary>
@@ -8928,17 +8944,6 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public Expression RemoveNullable ()
-               {
-                       if (dim.EndsWith ("?")) {
-                               dim = dim.Substring (0, dim.Length - 1);
-                               if (dim.Length == 0)
-                                       return left;
-                       }
-
-                       return this;
-               }
-
                protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
                {
                        TypeExpr lexpr = left.ResolveAsTypeTerminal (ec, false);
@@ -8946,11 +8951,6 @@ namespace Mono.CSharp {
                                return null;
 
                        Type ltype = lexpr.Type;
-                       if ((ltype == TypeManager.void_type) && (dim != "*")) {
-                               Error_VoidInvalidInTheContext (loc);
-                               return null;
-                       }
-
 #if GMCS_SOURCE
                        if ((dim.Length > 0) && (dim [0] == '?')) {
                                TypeExpr nullable = new Nullable.NullableType (left, loc);
@@ -8963,10 +8963,17 @@ namespace Mono.CSharp {
                        if (dim == "*" && !TypeManager.VerifyUnManaged (ltype, loc))
                                return null;
 
-                       if (dim != "" && dim [0] == '[' &&
-                           (ltype == TypeManager.arg_iterator_type || ltype == TypeManager.typed_reference_type)) {
-                               Report.Error (611, loc, "Array elements cannot be of type `{0}'", TypeManager.CSharpName (ltype));
-                               return null;
+                       if (dim.Length != 0 && dim [0] == '[') {
+                               if (TypeManager.IsSpecialType (ltype)) {
+                                       Report.Error (611, loc, "Array elements cannot be of type `{0}'", TypeManager.CSharpName (ltype));
+                                       return null;
+                               }
+
+                               if ((ltype.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
+                                       Report.SymbolRelatedToPreviousError (ltype);
+                                       Report.Error (719, loc, "Array elements cannot be of static type `{0}'", 
+                                               TypeManager.CSharpName (ltype));
+                               }
                        }
 
                        if (dim != "")
@@ -8979,7 +8986,6 @@ namespace Mono.CSharp {
 
                        if (type.IsPointer && !ec.IsInUnsafeScope){
                                UnsafeError (loc);
-                               return null;
                        }
 
                        eclass = ExprClass.Type;
@@ -9329,7 +9335,11 @@ namespace Mono.CSharp {
                        // for known types like List<T>, Dictionary<T, U>
                        
                        for (int i = 0; i < Arguments.Count; ++i) {
-                               Expression expr = ((Expression) Arguments [i]).Resolve (ec);
+                               Expression expr = Arguments [i] as Expression;
+                               if (expr == null)
+                                       return null;
+
+                               expr = expr.Resolve (ec);
                                if (expr == null)
                                        return null;
 
@@ -9765,20 +9775,25 @@ namespace Mono.CSharp {
                        if (e == null)
                                return null;
 
+                       if (e.eclass == ExprClass.MethodGroup) {
+                               Error_InvalidInitializer (e.ExprClassName);
+                               return null;
+                       }
+
                        type = e.Type;
                        if (type == TypeManager.void_type || type == TypeManager.null_type ||
                                type == TypeManager.anonymous_method_type || type.IsPointer) {
-                               Error_InvalidInitializer (e);
+                               Error_InvalidInitializer (e.GetSignatureForError ());
                                return null;
                        }
 
                        return e;
                }
 
-               protected virtual void Error_InvalidInitializer (Expression initializer)
+               protected virtual void Error_InvalidInitializer (string initializer)
                {
                        Report.Error (828, loc, "An anonymous type property `{0}' cannot be initialized with `{1}'",
-                               Name, initializer.GetSignatureForError ());
+                               Name, initializer);
                }
 
                public override void Emit (EmitContext ec)