Copying latest mcs to the branch.
[mono.git] / mcs / gmcs / expression.cs
index 0e3c197e2865b5876ec4ce4c2e6aa647f2fa27b0..eaccda581af45e785e97cd22a9fee2ed83d97f8a 100644 (file)
@@ -178,20 +178,10 @@ namespace Mono.CSharp {
                        oper_names [(int) Operator.AddressOf] = "op_AddressOf";
                }
 
-               public static void Error_OperatorCannotBeApplied (Location loc, string oper, Type t)
-               {
-                       Error_OperatorCannotBeApplied (loc, oper, TypeManager.CSharpName (t));
-               }
-
-               public static void Error_OperatorCannotBeApplied (Location loc, string oper, string type)
-               {
-                       Report.Error (23, loc, "The `{0}' operator cannot be applied to operand of type `{1}'",
-                               oper, type);
-               }
-
                void Error23 (Type t)
                {
-                       Error_OperatorCannotBeApplied (loc, OperName (Oper), t);
+                       Report.Error (23, loc, "Operator `{0}' cannot be applied to operand of type `{1}'",
+                               OperName (Oper), TypeManager.CSharpName (t));
                }
 
                /// <remarks>
@@ -467,8 +457,7 @@ namespace Mono.CSharp {
                                }
 
                                ParameterReference pr = Expr as ParameterReference;
-                               if ((pr != null) && (ec.capture_context != null) &&
-                                   ec.capture_context.IsParameterCaptured (pr.Name)) {
+                               if ((pr != null) && pr.Parameter.IsCaptured) {
                                        AnonymousMethod.Error_AddressOfCapturedVar (pr.Name, loc);
                                        return null;
                                }
@@ -3313,16 +3302,116 @@ namespace Mono.CSharp {
 
        }
 
+       public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation {
+               bool prepared;
+               LocalTemporary temp;
+
+               public abstract Variable Variable {
+                       get;
+               }
+
+               public abstract bool IsRef {
+                       get;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Emit (ec, false);
+               }
+
+               //
+               // 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 : Expression, IAssignMethod, IMemoryLocation, IVariable {
+       public class LocalVariableReference : VariableReference, IVariable {
                public readonly string Name;
                public readonly Block Block;
                public LocalInfo local_info;
                bool is_readonly;
-               bool prepared;
-               LocalTemporary temp;
+               Variable variable;
 
                public LocalVariableReference (Block block, string name, Location l)
                {
@@ -3348,6 +3437,10 @@ namespace Mono.CSharp {
                        get { return local_info.VariableInfo; }
                }
 
+               public override bool IsRef {
+                       get { return false; }
+               }
+
                public bool IsReadOnly {
                        get { return is_readonly; }
                }
@@ -3377,20 +3470,19 @@ namespace Mono.CSharp {
                        if (!VerifyAssigned (ec))
                                return null;
 
-                       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;
@@ -3417,8 +3509,7 @@ namespace Mono.CSharp {
                                } 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 {
-                                       Error_CannotAssign (Name, local_info.GetReadOnlyContext ());
-                                       return null;
+                                       code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'";
                                }
                                Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ());
                                return null;
@@ -3454,92 +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 (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 (Type);
-                                       temp.Store (ec);
-                               }
-                               ig.Emit (OpCodes.Stfld, local_info.FieldBuilder);
-                               if (temp != null) {
-                                       temp.Emit (ec);
-                                       temp.Release (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 ()
@@ -3552,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 {
@@ -3566,7 +3573,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public bool IsRef {
+               public override bool IsRef {
                        get {
                                return is_ref;
                        }
@@ -3578,7 +3585,13 @@ namespace Mono.CSharp {
                        }
                }
 
-               LocalTemporary temp;
+               public Parameter Parameter {
+                       get {
+                               return par;
+                       }
+               }
+
+               Variable variable;
                
                public ParameterReference (Parameter par, Block block, int idx, Location loc)
                {
@@ -3594,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).
@@ -3647,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;
                }
 
@@ -3698,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;
@@ -3728,137 +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 (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 (type);
-                                       temp.Store (ec);
-                               }
-                               
-                               StoreFromPtr (ig, type);
-                               
-                               if (temp != null) {
-                                       temp.Emit (ec);
-                                       temp.Release (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 + "]";
@@ -6624,6 +6521,7 @@ namespace Mono.CSharp {
                {
                        eclass = ExprClass.Variable;
                        type = ec.ContainerType;
+                       variable = new SimpleThis (type);
                        return this;
                }
        }
@@ -6632,11 +6530,13 @@ namespace Mono.CSharp {
        ///   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;
@@ -6657,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;
@@ -6666,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;
 
-                       if (ec.CurrentAnonymousMethod != null)
-                               ec.CaptureThis ();
+                               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 (variable == null)
+                               variable = new SimpleThis (type);
                        
                        return true;
                }
@@ -6685,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;
                        }
@@ -6714,49 +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 (type);
-                                       ec.ig.Emit (OpCodes.Dup);
-                                       t.Store (ec);
-                               }
-
-                               ig.Emit (OpCodes.Stobj, type);
-                               
-                               if (leave_copy) {
-                                       t.Emit (ec);
-                                       t.Release (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 ();
@@ -6771,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);
+                       }
                }
        }
 
@@ -7128,26 +7045,21 @@ namespace Mono.CSharp {
                TypeArguments args;
                
                public MemberAccess (Expression expr, string id)
-                       : this (expr, id, null)
+                       : this (expr, id, expr.Location)
                {
                }
 
-               public MemberAccess (Expression expr, string identifier, Location loc, TypeArguments args)
+               public MemberAccess (Expression expr, string identifier, Location loc)
                {
                        this.expr = expr;
                        Identifier = identifier;
                        this.loc = loc;
-                       this.args = args;
                }
 
-               public MemberAccess (Expression expr, string id, Location loc)
-                       : this (expr, id, loc, null)
-               {
-               }
-               
                public MemberAccess (Expression expr, string id, TypeArguments args)
-                       : this (expr, id, expr.Location, args)
+                       : this (expr, id)
                {
+                       this.args = args;
                }
 
                public Expression Expr {
@@ -7188,13 +7100,15 @@ namespace Mono.CSharp {
                        }
 
                        Type expr_type = new_expr.Type;
-                       if (expr_type.IsPointer || expr_type == TypeManager.void_type || new_expr is NullLiteral){
-                               Unary.Error_OperatorCannotBeApplied (loc, ".", expr_type);
+                       if (expr_type.IsPointer){
+                               Error (23, "The `.' operator can not be applied to pointer operands (" +
+                                      TypeManager.CSharpName (expr_type) + ")");
                                return null;
-                       }
-                       if (expr_type == TypeManager.anonymous_method_type){
-                               Unary.Error_OperatorCannotBeApplied (loc, ".", "anonymous method");
+                       } else if (expr_type == TypeManager.void_type) {
+                               Error (23, "The `.' operator can not be applied to operands of type 'void'");
                                return null;
+                       } else if (expr_type == TypeManager.anonymous_method_type){
+                               Error (23, "The `.' operator can not be applied to anonymous methods");
                        }