2005-05-31 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / mcs / ecore.cs
index 39c9bbcf8762e7839654cf681a36c0f361896b79..3f2940843e3ae562c7b81ba7804f87661772750c 100644 (file)
@@ -118,49 +118,6 @@ namespace Mono.CSharp {
                bool VerifyFixed (bool is_expression);
        }
 
-       /// <summary>
-       ///   This interface denotes an expression which evaluates to a member
-       ///   of a struct or a class.
-       /// </summary>
-       public interface IMemberExpr
-       {
-               /// <summary>
-               ///   The name of this member.
-               /// </summary>
-               string Name {
-                       get;
-               }
-
-               /// <summary>
-               ///   Whether this is an instance member.
-               /// </summary>
-               bool IsInstance {
-                       get;
-               }
-
-               /// <summary>
-               ///   Whether this is a static member.
-               /// </summary>
-               bool IsStatic {
-                       get;
-               }
-
-               /// <summary>
-               ///   The type which declares this member.
-               /// </summary>
-               Type DeclaringType {
-                       get;
-               }
-
-               /// <summary>
-               ///   The instance expression associated with this member, if it's a
-               ///   non-static member.
-               /// </summary>
-               Expression InstanceExpression {
-                       get; set;
-               }
-       }
-
        /// <remarks>
        ///   Base class for expressions
        /// </remarks>
@@ -228,34 +185,23 @@ namespace Mono.CSharp {
                        //
                        // If only accessible to the current class or children
                        //
-                       if (ma == MethodAttributes.Private) {
-                               Type declaring_type = mi.DeclaringType;
+                       if (ma == MethodAttributes.Private)
+                               return invocation_type == mi.DeclaringType ||
+                                       TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
 
-                               if (invocation_type != declaring_type)
-                                       return TypeManager.IsNestedChildOf (invocation_type, declaring_type);
-
-                               return true;
-                       }
-                       //
-                       // FamAndAssem requires that we not only derivate, but we are on the
-                       // same assembly.  
-                       //
-                       if (ma == MethodAttributes.FamANDAssem){
-                               return (mi.DeclaringType.Assembly != invocation_type.Assembly);
-                       }
-
-                       // Assembly and FamORAssem succeed if we're in the same assembly.
-                       if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
-                               if (mi.DeclaringType.Assembly == invocation_type.Assembly)
+                       if (mi.DeclaringType.Assembly == invocation_type.Assembly) {
+                               if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
                                        return true;
+                       } else {
+                               if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
+                                       return false;
                        }
 
-                       // We already know that we aren't in the same assembly.
-                       if (ma == MethodAttributes.Assembly)
-                               return false;
-
                        // Family and FamANDAssem require that we derive.
-                       if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem) || (ma == MethodAttributes.FamORAssem)){
+                       // FamORAssem requires that we derive if in different assemblies.
+                       if (ma == MethodAttributes.Family ||
+                           ma == MethodAttributes.FamANDAssem ||
+                           ma == MethodAttributes.FamORAssem) {
                                if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
                                        return false;
 
@@ -449,14 +395,14 @@ namespace Mono.CSharp {
                ///   Currently ResolveLValue wraps DoResolveLValue to perform sanity
                ///   checking and assertion checking on what we expect from Resolve
                /// </remarks>
-               public Expression ResolveLValue (EmitContext ec, Expression right_side)
+               public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc)
                {
                        int errors = Report.Errors;
                        Expression e = DoResolveLValue (ec, right_side);
 
                        if (e == null) {
                                if (errors == Report.Errors)
-                                       Report.Error (131, Location, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer");
+                                       Report.Error (131, loc, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer");
                                return null;
                        }
 
@@ -717,43 +663,47 @@ namespace Mono.CSharp {
                                                       Location loc)
                {
                        if (almostMatchedMembers.Count != 0) {
-                               if (qualifier_type == null) {
-                                       foreach (MemberInfo m in almostMatchedMembers)
+                               for (int i = 0; i < almostMatchedMembers.Count; ++i) {
+                                       MemberInfo m = (MemberInfo) almostMatchedMembers [i];
+                                       for (int j = 0; j < i; ++j) {
+                                               if (m == almostMatchedMembers [j]) {
+                                                       m = null;
+                                                       break;
+                                               }
+                                       }
+                                       if (m == null)
+                                               continue;
+                                       
+                                       Type declaring_type = m.DeclaringType;
+                                       
+                                       Report.SymbolRelatedToPreviousError (m);
+                                       if (qualifier_type == null) {
                                                Report.Error (38, loc, 
                                                              "Cannot access non-static member `{0}' via nested type `{1}'", 
                                                              TypeManager.GetFullNameSignature (m),
                                                              TypeManager.CSharpName (ec.ContainerType));
-                                       return;
-                               }
-
-                               if (qualifier_type != ec.ContainerType) {
-                                       // Although a derived class can access protected members of
-                                       // its base class it cannot do so through an instance of the
-                                       // base class (CS1540).  If the qualifier_type is a base of the
-                                       // ec.ContainerType and the lookup succeeds with the latter one,
-                                       // then we are in this situation.
-                                       for (int i = 0; i < almostMatchedMembers.Count; ++i) {
-                                               MemberInfo m = (MemberInfo) almostMatchedMembers [i];
-                                               for (int j = 0; j < i; ++j) {
-                                                       if (m == almostMatchedMembers [j]) {
-                                                               m = null;
-                                                               break;
-                                                       }
-                                               }
-                                               if (m == null)
-                                                       continue;
-
-                                               Report.SymbolRelatedToPreviousError (m);
+                                               
+                                       } else if (qualifier_type != ec.ContainerType &&
+                                                  TypeManager.IsNestedFamilyAccessible (ec.ContainerType, declaring_type)) {
+                                               // Although a derived class can access protected members of
+                                               // its base class it cannot do so through an instance of the
+                                               // base class (CS1540).  If the qualifier_type is a base of the
+                                               // ec.ContainerType and the lookup succeeds with the latter one,
+                                               // then we are in this situation.
                                                Report.Error (1540, loc, 
                                                              "Cannot access protected member `{0}' via a qualifier of type `{1}';"
                                                              + " the qualifier must be of type `{2}' (or derived from it)", 
                                                              TypeManager.GetFullNameSignature (m),
                                                              TypeManager.CSharpName (qualifier_type),
                                                              TypeManager.CSharpName (ec.ContainerType));
+                                       } else {
+                                               Report.Error (122, loc, 
+                                                             "'{0}' is inaccessible due to its protection level", 
+                                                             TypeManager.GetFullNameSignature (m));
                                        }
-                                       return;
                                }
                                almostMatchedMembers.Clear ();
+                               return;
                        }
 
                        object lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
@@ -788,13 +738,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               static public MemberInfo GetFieldFromEvent (EventExpr event_expr)
-               {
-                       EventInfo ei = event_expr.EventInfo;
-
-                       return TypeManager.GetPrivateFieldOfEvent (ei);
-               }
-               
                /// <summary>
                ///   Returns an expression that can be used to invoke operator true
                ///   on the expression if it exists.
@@ -1443,6 +1386,104 @@ namespace Mono.CSharp {
                        child.Emit (ec);
                }
        }
+       /// <summary>
+       ///     This is a numeric cast to a Decimal
+       /// </summary>
+       public class CastToDecimal : EmptyCast {
+
+               MethodInfo conversion_operator;
+
+               public CastToDecimal (EmitContext ec, Expression child)
+                       : this (ec, child, false)
+               {
+               }
+
+               public CastToDecimal (EmitContext ec, Expression child, bool find_explicit)
+                       : base (child, TypeManager.decimal_type)
+               {
+                       conversion_operator = GetConversionOperator (ec, find_explicit);
+
+                       if (conversion_operator == null)
+                               Convert.Error_CannotImplicitConversion (loc, child.Type, type);
+               }
+
+               // Returns the implicit operator that converts from
+               // 'child.Type' to System.Decimal.
+               MethodInfo GetConversionOperator (EmitContext ec, bool find_explicit)
+               {
+                       string operator_name = "op_Implicit";
+
+                       if (find_explicit)
+                               operator_name = "op_Explicit";
+                       
+                       MethodGroupExpr opers = Expression.MethodLookup (
+                               ec, type, operator_name, loc) as MethodGroupExpr;
+
+                       if (opers == null)
+                               Convert.Error_CannotImplicitConversion (loc, child.Type, type);
+                       
+                       foreach (MethodInfo oper in opers.Methods) {
+                               ParameterData pd = TypeManager.GetParameterData (oper);
+
+                               if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
+                                       return oper;
+                       }
+
+                       return null;
+               }
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       child.Emit (ec);
+
+                       ig.Emit (OpCodes.Call, conversion_operator);
+               }
+       }
+       /// <summary>
+       ///     This is an explicit numeric cast from a Decimal
+       /// </summary>
+       public class CastFromDecimal : EmptyCast
+       {
+               MethodInfo conversion_operator;
+               public CastFromDecimal (EmitContext ec, Expression child, Type return_type)
+                       : base (child, return_type)
+               {
+                       if (child.Type != TypeManager.decimal_type)
+                               throw new InternalErrorException (
+                                       "The expected type is Decimal, instead it is " + child.Type.FullName);
+
+                       conversion_operator = GetConversionOperator (ec);
+                       if (conversion_operator == null)
+                               Convert.Error_CannotImplicitConversion (loc, child.Type, type);
+               }
+
+               // Returns the explicit operator that converts from an
+               // express of type System.Decimal to 'type'.
+               MethodInfo GetConversionOperator (EmitContext ec)
+               {                               
+                       MethodGroupExpr opers = Expression.MethodLookup (
+                               ec, child.Type, "op_Explicit", loc) as MethodGroupExpr;
+
+                       if (opers == null)
+                               Convert.Error_CannotImplicitConversion (loc, child.Type, type);
+                       
+                       foreach (MethodInfo oper in opers.Methods) {
+                               ParameterData pd = TypeManager.GetParameterData (oper);
+
+                               if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
+                                       return oper;
+                       }
+
+                       return null;
+               }
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       child.Emit (ec);
+
+                       ig.Emit (OpCodes.Call, conversion_operator);
+               }
+       }
 
         //
        // We need to special case this since an empty cast of
@@ -1993,6 +2034,7 @@ namespace Mono.CSharp {
        /// </summary>
        public class SimpleName : Expression {
                public string Name;
+               bool in_transit;
 
                public SimpleName (string name, Location l)
                {
@@ -2020,25 +2062,6 @@ namespace Mono.CSharp {
                                resolved_to.Type.Name == Name &&
                                (ec.DeclSpace.LookupType (Name, loc, /* ignore_cs0104 = */ true) != null);
                }
-               
-               //
-               // Checks whether we are trying to access an instance
-               // property, method or field from a static body.
-               //
-               Expression MemberStaticCheck (EmitContext ec, Expression e, bool intermediate)
-               {
-                       if (e is IMemberExpr){
-                               IMemberExpr member = (IMemberExpr) e;
-                               
-                               if (!member.IsStatic &&
-                                   (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
-                                       Error_ObjectRefRequired (ec, loc, Name);
-                                       return null;
-                               }
-                       }
-
-                       return e;
-               }
 
                public override Expression DoResolve (EmitContext ec)
                {
@@ -2068,20 +2091,18 @@ namespace Mono.CSharp {
 
                Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
                {
+                       if (in_transit)
+                               return null;
+                       in_transit = true;
+
                        Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
                        if (e == null)
                                return null;
 
-                       Block current_block = ec.CurrentBlock;
-                       if (current_block != null){
-                               if (current_block.IsVariableNameUsedInChildBlock (Name)) {
-                                       Report.Error (135, Location,
-                                                     "'{0}' has a different meaning in a child block", Name);
-                                       return null;
-                               }
-                       }
+                       if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
+                               return e;
 
-                       return e;
+                       return null;
                }
 
                /// <remarks>
@@ -2117,15 +2138,15 @@ namespace Mono.CSharp {
                                        var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
                                        
                                        if (right_side != null)
-                                               return var.ResolveLValue (ec, right_side);
+                                               return var.ResolveLValue (ec, right_side, loc);
                                        else
                                                return var.Resolve (ec);
                                }
 
-                               ParameterReference pref = current_block.GetParameterReference (Name, loc);
+                               ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc);
                                if (pref != null) {
                                        if (right_side != null)
-                                               return pref.ResolveLValue (ec, right_side);
+                                               return pref.ResolveLValue (ec, right_side, loc);
                                        else
                                                return pref.Resolve (ec);
                                }
@@ -2177,21 +2198,44 @@ namespace Mono.CSharp {
                        if (e is TypeExpr)
                                return e;
 
-                       if (e is IMemberExpr) {
-                               e = MemberAccess.ResolveMemberAccess (ec, e, null, loc, this);
+                       if (e is MemberExpr) {
+                               MemberExpr me = (MemberExpr) e;
+
+                               Expression left;
+                               if (me.IsInstance) {
+                                       if (ec.IsStatic || ec.IsFieldInitializer) {
+                                               //
+                                               // Note that an MemberExpr can be both IsInstance and IsStatic.
+                                               // An unresolved MethodGroupExpr can contain both kinds of methods
+                                               // and each predicate is true if the MethodGroupExpr contains
+                                               // at least one of that kind of method.
+                                               //
+
+                                               if (!me.IsStatic &&
+                                                   (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
+                                                       Error_ObjectRefRequired (ec, loc, Name);
+                                                       return null;
+                                               }
+
+                                               //
+                                               // Pass the buck to MemberAccess and Invocation.
+                                               //
+                                               left = EmptyExpression.Null;
+                                       } else {
+                                               left = ec.GetThis (loc);
+                                       }
+                               } else {
+                                       left = new TypeExpression (ec.ContainerType, loc);
+                               }
+
+                               e = me.ResolveMemberAccess (ec, left, loc, null);
                                if (e == null)
                                        return null;
 
-                               IMemberExpr me = e as IMemberExpr;
+                               me = e as MemberExpr;
                                if (me == null)
                                        return e;
 
-                               // This fails if ResolveMemberAccess() was unable to decide whether
-                               // it's a field or a type of the same name.
-                               
-                               if (!me.IsStatic && (me.InstanceExpression == null))
-                                       return e;
-                               
                                if (!me.IsStatic &&
                                    TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
                                    me.InstanceExpression.Type != me.DeclaringType &&
@@ -2204,14 +2248,11 @@ namespace Mono.CSharp {
                                }
 
                                return (right_side != null)
-                                       ? e.DoResolveLValue (ec, right_side)
-                                       : e.DoResolve (ec);
+                                       ? me.DoResolveLValue (ec, right_side)
+                                       : me.DoResolve (ec);
                        }
 
-                       if (ec.IsStatic || ec.IsFieldInitializer){
-                               return MemberStaticCheck (ec, e, intermediate);
-                       } else
-                               return e;
+                       return e;
                }
                
                public override void Emit (EmitContext ec)
@@ -2471,15 +2512,93 @@ namespace Mono.CSharp {
                }
        }
 
+       /// <summary>
+       ///   This class denotes an expression which evaluates to a member
+       ///   of a struct or a class.
+       /// </summary>
+       public abstract class MemberExpr : Expression
+       {
+               /// <summary>
+               ///   The name of this member.
+               /// </summary>
+               public abstract string Name {
+                       get;
+               }
+
+               /// <summary>
+               ///   Whether this is an instance member.
+               /// </summary>
+               public abstract bool IsInstance {
+                       get;
+               }
+
+               /// <summary>
+               ///   Whether this is a static member.
+               /// </summary>
+               public abstract bool IsStatic {
+                       get;
+               }
+
+               /// <summary>
+               ///   The type which declares this member.
+               /// </summary>
+               public abstract Type DeclaringType {
+                       get;
+               }
+
+               /// <summary>
+               ///   The instance expression associated with this member, if it's a
+               ///   non-static member.
+               /// </summary>
+               public Expression InstanceExpression;
+
+               public static void error176 (Location loc, string name)
+               {
+                       Report.Error (176, loc, "Static member `" + name + "' cannot be accessed " +
+                                     "with an instance reference, qualify with a type name instead");
+               }
+
+
+               // TODO: possible optimalization
+               // Cache resolved constant result in FieldBuilder <-> expression map
+               public virtual Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
+                                                              SimpleName original)
+               {
+                       //
+                       // Precondition:
+                       //   original == null || original.Resolve (...) ==> left
+                       //
+
+                       if (left is TypeExpr) {
+                               if (!IsStatic) {
+                                       SimpleName.Error_ObjectRefRequired (ec, loc, Name);
+                                       return null;
+                               }
+
+                               return this;
+                       }
+                               
+                       if (!IsInstance) {
+                               if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
+                                       return this;
+
+                               error176 (loc, Name);
+                               return null;
+                       }
+
+                       InstanceExpression = left;
+
+                       return this;
+               }
+       }
+
        /// <summary>
        ///   MethodGroup Expression.
        ///  
        ///   This is a fully resolved expression that evaluates to a type
        /// </summary>
-       public class MethodGroupExpr : Expression, IMemberExpr {
+       public class MethodGroupExpr : MemberExpr {
                public MethodBase [] Methods;
-               Expression instance_expression = null;
-               bool is_explicit_impl = false;
                bool identical_type_name = false;
                bool is_base;
                
@@ -2513,7 +2632,7 @@ namespace Mono.CSharp {
                        type = TypeManager.object_type;
                }
 
-               public Type DeclaringType {
+               public override Type DeclaringType {
                        get {
                                 //
                                 // The methods are arranged in this order:
@@ -2522,29 +2641,6 @@ namespace Mono.CSharp {
                                return Methods [0].DeclaringType;
                        }
                }
-               
-               //
-               // `A method group may have associated an instance expression' 
-               // 
-               public Expression InstanceExpression {
-                       get {
-                               return instance_expression;
-                       }
-
-                       set {
-                               instance_expression = value;
-                       }
-               }
-
-               public bool IsExplicitImpl {
-                       get {
-                               return is_explicit_impl;
-                       }
-
-                       set {
-                               is_explicit_impl = value;
-                       }
-               }
 
                public bool IdenticalTypeName {
                        get {
@@ -2565,13 +2661,13 @@ namespace Mono.CSharp {
                        }
                }
 
-               public string Name {
+               public override string Name {
                        get {
                                 return Methods [0].Name;
                        }
                }
 
-               public bool IsInstance {
+               public override bool IsInstance {
                        get {
                                foreach (MethodBase mb in Methods)
                                        if (!mb.IsStatic)
@@ -2581,7 +2677,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public bool IsStatic {
+               public override bool IsStatic {
                        get {
                                foreach (MethodBase mb in Methods)
                                        if (mb.IsStatic)
@@ -2590,15 +2686,25 @@ namespace Mono.CSharp {
                                return false;
                        }
                }
+
+               public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
+                                                               SimpleName original)
+               {
+                       if (!(left is TypeExpr) &&
+                           original != null && original.IdenticalNameAndTypeName (ec, left, loc))
+                               IdenticalTypeName = true;
+
+                       return base.ResolveMemberAccess (ec, left, loc, original);
+               }
                
                override public Expression DoResolve (EmitContext ec)
                {
                        if (!IsInstance)
-                               instance_expression = null;
+                               InstanceExpression = null;
 
-                       if (instance_expression != null) {
-                               instance_expression = instance_expression.DoResolve (ec);
-                               if (instance_expression == null)
+                       if (InstanceExpression != null) {
+                               InstanceExpression = InstanceExpression.DoResolve (ec);
+                               if (InstanceExpression == null)
                                        return null;
                        }
 
@@ -2656,13 +2762,19 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Fully resolved expression that evaluates to a Field
        /// </summary>
-       public class FieldExpr : Expression, IAssignMethod, IMemoryLocation, IMemberExpr, IVariable {
+       public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariable {
                public readonly FieldInfo FieldInfo;
-               Expression instance_expr;
                VariableInfo variable_info;
 
                LocalTemporary temp;
                bool prepared;
+               bool in_initializer;
+
+               public FieldExpr (FieldInfo fi, Location l, bool in_initializer):
+                       this (fi, l)
+               {
+                       this.in_initializer = in_initializer;
+               }
                
                public FieldExpr (FieldInfo fi, Location l)
                {
@@ -2672,50 +2784,152 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public string Name {
+               public override string Name {
                        get {
                                return FieldInfo.Name;
                        }
                }
 
-               public bool IsInstance {
+               public override bool IsInstance {
                        get {
                                return !FieldInfo.IsStatic;
                        }
                }
 
-               public bool IsStatic {
+               public override bool IsStatic {
                        get {
                                return FieldInfo.IsStatic;
                        }
                }
 
-               public Type DeclaringType {
+               public override Type DeclaringType {
                        get {
                                return FieldInfo.DeclaringType;
                        }
                }
 
-               public Expression InstanceExpression {
+               public VariableInfo VariableInfo {
                        get {
-                               return instance_expr;
+                               return variable_info;
                        }
+               }
 
-                       set {
-                               instance_expr = value;
+               public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
+                                                               SimpleName original)
+               {
+                       bool left_is_type = left is TypeExpr;
+
+                       Type decl_type = FieldInfo.DeclaringType;
+                       
+                       bool is_emitted = FieldInfo is FieldBuilder;
+                       Type t = FieldInfo.FieldType;
+                       
+                       if (is_emitted) {
+                               Const c = TypeManager.LookupConstant ((FieldBuilder) FieldInfo);
+                               
+                               if (c != null) {
+                                       object o;
+                                       if (!c.LookupConstantValue (out o))
+                                               return null;
+
+                                       c.SetMemberIsUsed ();
+                                       object real_value = ((Constant) c.Expr).GetValue ();
+
+                                       Expression exp = Constantify (real_value, t);
+                                       
+                                       if (!left_is_type && 
+                                           (original == null || !original.IdenticalNameAndTypeName (ec, left, loc))) {
+                                               Report.SymbolRelatedToPreviousError (c);
+                                               error176 (loc, c.GetSignatureForError ());
+                                               return null;
+                                       }
+                                       
+                                       return exp;
+                               }
                        }
-               }
 
-               public VariableInfo VariableInfo {
-                       get {
-                               return variable_info;
+                       //
+                       // Decimal constants cannot be encoded in the constant blob, and thus are marked
+                       // as IsInitOnly ('readonly' in C# parlance).  We get its value from the 
+                       // DecimalConstantAttribute metadata.
+                       //
+                       if (FieldInfo.IsInitOnly && !is_emitted && t == TypeManager.decimal_type) {
+                               object[] attrs = FieldInfo.GetCustomAttributes (TypeManager.decimal_constant_attribute_type, false);
+                               if (attrs.Length == 1)
+                                       return new DecimalConstant (((System.Runtime.CompilerServices.DecimalConstantAttribute) attrs [0]).Value);
                        }
+                       
+                       if (FieldInfo.IsLiteral) {
+                               object o;
+                               
+                               if (is_emitted)
+                                       o = TypeManager.GetValue ((FieldBuilder) FieldInfo);
+                               else
+                                       o = FieldInfo.GetValue (FieldInfo);
+                               
+                               if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
+                                       if (!left_is_type &&
+                                           (original == null || !original.IdenticalNameAndTypeName (ec, left, loc))) {
+                                               error176 (loc, FieldInfo.Name);
+                                               return null;
+                                       }                                       
+                                       
+                                       Expression enum_member = MemberLookup (
+                                              ec, decl_type, "value__", MemberTypes.Field,
+                                              AllBindingFlags | BindingFlags.NonPublic, loc); 
+                                       
+                                       Enum en = TypeManager.LookupEnum (decl_type);
+                                       
+                                       Constant c;
+                                       if (en != null)
+                                               c = Constantify (o, en.UnderlyingType);
+                                       else 
+                                               c = Constantify (o, enum_member.Type);
+                                       
+                                       return new EnumConstant (c, decl_type);
+                               }
+                               
+                               Expression exp = Constantify (o, t);
+                               
+                               if (!left_is_type) {
+                                       error176 (loc, FieldInfo.Name);
+                                       return null;
+                               }
+                               
+                               return exp;
+                       }
+                       
+                       if (t.IsPointer && !ec.InUnsafe) {
+                               UnsafeError (loc);
+                               return null;
+                       }
+
+                       return base.ResolveMemberAccess (ec, left, loc, original);
                }
 
                override public Expression DoResolve (EmitContext ec)
                {
+                       if (ec.InRefOutArgumentResolving && FieldInfo.IsInitOnly && !ec.IsConstructor && FieldInfo.FieldType.IsValueType) {
+                               if (FieldInfo.FieldType is TypeBuilder) {
+                                       if (FieldInfo.IsStatic)
+                                               Report.Error (1651, loc, "Members of readonly static field '{0}.{1}' cannot be passed ref or out (except in a constructor)",
+                                                       TypeManager.CSharpName (DeclaringType), Name);
+                                       else
+                                               Report.Error (1649, loc, "Members of readonly field '{0}.{1}' cannot be passed ref or out (except in a constructor)",
+                                                       TypeManager.CSharpName (DeclaringType), Name);
+                               } else {
+                                       if (FieldInfo.IsStatic)
+                                               Report.Error (199, loc, "A static readonly field '{0}' cannot be passed ref or out (except in a static constructor)",
+                                                       Name);
+                                       else
+                                               Report.Error (192, loc, "A readonly field '{0}' cannot be passed ref or out (except in a constructor)",
+                                                       Name);
+                               }
+                               return null;
+                       }
+
                        if (!FieldInfo.IsStatic){
-                               if (instance_expr == null){
+                               if (InstanceExpression == null){
                                        //
                                        // This can happen when referencing an instance field using
                                        // a fully qualified type expression: TypeName.InstanceField = xxx
@@ -2727,24 +2941,26 @@ namespace Mono.CSharp {
                                // Resolve the field's instance expression while flow analysis is turned
                                // off: when accessing a field "a.b", we must check whether the field
                                // "a.b" is initialized, not whether the whole struct "a" is initialized.
-                               instance_expr = instance_expr.Resolve (ec, ResolveFlags.VariableOrValue |
+                               InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue |
                                                                       ResolveFlags.DisableFlowAnalysis);
-                               if (instance_expr == null)
+                               if (InstanceExpression == null)
                                        return null;
                        }
 
-                       ObsoleteAttribute oa;
-                       FieldBase f = TypeManager.GetField (FieldInfo);
-                       if (f != null) {
-                               oa = f.GetObsoleteAttribute (f.Parent);
-                               if (oa != null)
-                                       AttributeTester.Report_ObsoleteMessage (oa, f.GetSignatureForError (), loc);
+                       if (!in_initializer) {
+                               ObsoleteAttribute oa;
+                               FieldBase f = TypeManager.GetField (FieldInfo);
+                               if (f != null) {
+                                       oa = f.GetObsoleteAttribute (f.Parent);
+                                       if (oa != null)
+                                               AttributeTester.Report_ObsoleteMessage (oa, f.GetSignatureForError (), loc);
                                 
-                        // To be sure that type is external because we do not register generated fields
-                        } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {                                
-                               oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
-                               if (oa != null)
-                                       AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
+                                       // To be sure that type is external because we do not register generated fields
+                               } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {                                
+                                       oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
+                                       if (oa != null)
+                                               AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
+                               }
                        }
 
                        if (ec.CurrentAnonymousMethod != null){
@@ -2758,7 +2974,7 @@ namespace Mono.CSharp {
                        }
                        
                        // If the instance expression is a local variable or parameter.
-                       IVariable var = instance_expr as IVariable;
+                       IVariable var = InstanceExpression as IVariable;
                        if ((var == null) || (var.VariableInfo == null))
                                return this;
 
@@ -2786,7 +3002,7 @@ namespace Mono.CSharp {
                
                override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
                {
-                       IVariable var = instance_expr as IVariable;
+                       IVariable var = InstanceExpression as IVariable;
                        if ((var != null) && (var.VariableInfo != null))
                                var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
 
@@ -2795,19 +3011,19 @@ namespace Mono.CSharp {
                        if (e == null)
                                return null;
 
-                       if (!FieldInfo.IsStatic && (instance_expr.Type.IsValueType && !(instance_expr is IMemoryLocation))) {
+                       if (!FieldInfo.IsStatic && (InstanceExpression.Type.IsValueType && !(InstanceExpression is IMemoryLocation))) {
                                // FIXME: Provide better error reporting.
                                Error (1612, "Cannot modify expression because it is not a variable.");
                                return null;
                        }
 
-                       if (!FieldInfo.IsInitOnly)
-                               return this;
-
                        FieldBase fb = TypeManager.GetField (FieldInfo);
                        if (fb != null)
                                fb.SetAssigned ();
 
+                       if (!FieldInfo.IsInitOnly)
+                               return this;
+
                        //
                        // InitOnly fields can only be assigned in constructors
                        //
@@ -2835,7 +3051,7 @@ namespace Mono.CSharp {
 
                public bool VerifyFixed (bool is_expression)
                {
-                       IVariable variable = instance_expr as IVariable;
+                       IVariable variable = InstanceExpression as IVariable;
                        if ((variable == null) || !variable.VerifyFixed (true))
                                return false;
 
@@ -2873,7 +3089,7 @@ namespace Mono.CSharp {
                                        if ((f.ModFlags & Modifiers.VOLATILE) != 0)
                                                is_volatile = true;
                                        
-                                       f.status |= Field.Status.USED;
+                                       f.SetMemberIsUsed ();
                                }
                        } 
                        
@@ -2958,27 +3174,17 @@ namespace Mono.CSharp {
 
                void EmitInstance (EmitContext ec)
                {
-                       //
-                       // In case it escapes StaticMemberCheck due to IdenticalTypeAndName.
-                       // This happens in cases like 'string String', 'int Int32', etc.
-                       // where the "IdenticalTypeAndName" mechanism is fooled.
-                       //
-                       if (instance_expr == null) {
-                               SimpleName.Error_ObjectRefRequired (ec, loc, FieldInfo.Name);
-                               return;
-                       }
-
-                       if (instance_expr.Type.IsValueType) {
-                               if (instance_expr is IMemoryLocation) {
-                                       ((IMemoryLocation) instance_expr).AddressOf (ec, AddressOp.LoadStore);
+                       if (InstanceExpression.Type.IsValueType) {
+                               if (InstanceExpression is IMemoryLocation) {
+                                       ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
                                } else {
-                                       LocalTemporary t = new LocalTemporary (ec, instance_expr.Type);
-                                       instance_expr.Emit (ec);
+                                       LocalTemporary t = new LocalTemporary (ec, InstanceExpression.Type);
+                                       InstanceExpression.Emit (ec);
                                        t.Store (ec);
                                        t.AddressOf (ec, AddressOp.Store);
                                }
                        } else
-                               instance_expr.Emit (ec);
+                               InstanceExpression.Emit (ec);
                }
 
                public override void Emit (EmitContext ec)
@@ -3001,7 +3207,7 @@ namespace Mono.CSharp {
                                        if ((mode & AddressOp.Store) != 0)
                                                f.status |= Field.Status.ASSIGNED;
                                        if ((mode & AddressOp.Load) != 0)
-                                               f.status |= Field.Status.USED;
+                                               f.SetMemberIsUsed ();
                                }
                        } 
 
@@ -3062,7 +3268,7 @@ namespace Mono.CSharp {
        ///   This is not an LValue because we need to re-write the expression, we
        ///   can not take data from the stack and store it.  
        /// </summary>
-       public class PropertyExpr : ExpressionStatement, IAssignMethod, IMemberExpr {
+       public class PropertyExpr : MemberExpr, IAssignMethod {
                public readonly PropertyInfo PropertyInfo;
 
                //
@@ -3071,8 +3277,9 @@ namespace Mono.CSharp {
                public bool IsBase;
                MethodInfo getter, setter;
                bool is_static;
+
+               bool resolved;
                
-               Expression instance_expr;
                LocalTemporary temp;
                bool prepared;
 
@@ -3090,43 +3297,30 @@ namespace Mono.CSharp {
                        ResolveAccessors (ec);
                }
 
-               public string Name {
+               public override string Name {
                        get {
                                return PropertyInfo.Name;
                        }
                }
 
-               public bool IsInstance {
+               public override bool IsInstance {
                        get {
                                return !is_static;
                        }
                }
 
-               public bool IsStatic {
+               public override bool IsStatic {
                        get {
                                return is_static;
                        }
                }
                
-               public Type DeclaringType {
+               public override Type DeclaringType {
                        get {
                                return PropertyInfo.DeclaringType;
                        }
                }
 
-               //
-               // The instance expression associated with this expression
-               //
-               public Expression InstanceExpression {
-                       set {
-                               instance_expr = value;
-                       }
-
-                       get {
-                               return instance_expr;
-                       }
-               }
-
                public bool VerifyAssignable ()
                {
                        if (setter == null) {
@@ -3182,11 +3376,19 @@ namespace Mono.CSharp {
                        FindAccessors (ec.ContainerType);
 
                        if (getter != null) {
+                               IMethodData md = TypeManager.GetMethod (getter);
+                               if (md != null)
+                                       md.SetMemberIsUsed ();
+
                                AccessorTable [getter] = PropertyInfo;
                                is_static = getter.IsStatic;
                        }
 
                        if (setter != null) {
+                               IMethodData md = TypeManager.GetMethod (setter);
+                               if (md != null)
+                                       md.SetMemberIsUsed ();
+
                                AccessorTable [setter] = PropertyInfo;
                                is_static = setter.IsStatic;
                        }
@@ -3194,26 +3396,29 @@ namespace Mono.CSharp {
 
                bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
                {
-                       if ((instance_expr == null) && ec.IsStatic && !is_static) {
+                       if ((InstanceExpression == null) && ec.IsStatic && !is_static) {
                                SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
                                return false;
                        }
 
-                       if (instance_expr != null) {
-                               instance_expr = instance_expr.DoResolve (ec);
-                               if (instance_expr == null)
+                       if (!IsInstance || InstanceExpression == EmptyExpression.Null)
+                               InstanceExpression = null;
+
+                       if (InstanceExpression != null) {
+                               InstanceExpression = InstanceExpression.DoResolve (ec);
+                               if (InstanceExpression == null)
                                        return false;
 
-                               instance_expr.CheckMarshallByRefAccess (ec.ContainerType);
+                               InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType);
                        }
 
-                       if (must_do_cs1540_check && (instance_expr != null)) {
-                               if ((instance_expr.Type != ec.ContainerType) &&
-                                   ec.ContainerType.IsSubclassOf (instance_expr.Type)) {
+                       if (must_do_cs1540_check && (InstanceExpression != null)) {
+                               if ((InstanceExpression.Type != ec.ContainerType) &&
+                                   ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
                                        Report.Error (1540, loc, "Cannot access protected member `" +
                                                      PropertyInfo.DeclaringType + "." + PropertyInfo.Name + 
                                                      "' via a qualifier of type `" +
-                                                     TypeManager.CSharpName (instance_expr.Type) +
+                                                     TypeManager.CSharpName (InstanceExpression.Type) +
                                                      "'; the qualifier must be of type `" +
                                                      TypeManager.CSharpName (ec.ContainerType) +
                                                      "' (or derived from it)");
@@ -3226,6 +3431,11 @@ namespace Mono.CSharp {
                
                override public Expression DoResolve (EmitContext ec)
                {
+                       if (resolved) {
+                               Report.Debug ("Double resolve of " + Name);
+                               return this;
+                       }
+
                        if (getter != null){
                                if (TypeManager.GetArgumentTypes (getter).Length != 0){
                                        Report.Error (
@@ -3245,16 +3455,19 @@ namespace Mono.CSharp {
                                //
                                if (setter == null)
                                        return null;
-                               
-                               Report.Error (154, loc, 
-                                             "The property `" + PropertyInfo.Name +
-                                             "' can not be used in " +
-                                             "this context because it lacks a get accessor");
-                               return null;
+
+                               if (InstanceExpression != EmptyExpression.Null) {
+                                       Report.Error (154, loc, 
+                                               "The property `" + PropertyInfo.Name +
+                                               "' can not be used in " +
+                                               "this context because it lacks a get accessor");
+                                       return null;
+                               }
                        } 
 
-                       bool must_do_cs1540_check;
-                       if (!IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
+                       bool must_do_cs1540_check = false;
+                       if (getter != null &&
+                           !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
                                PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
                                if (pm != null && pm.HasCustomAccessModifier) {
                                        Report.SymbolRelatedToPreviousError (pm);
@@ -3284,6 +3497,8 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       resolved = true;
+
                        return this;
                }
 
@@ -3342,7 +3557,7 @@ namespace Mono.CSharp {
                        //
                        // Check that we are not making changes to a temporary memory location
                        //
-                       if (instance_expr != null && instance_expr.Type.IsValueType && !(instance_expr is IMemoryLocation)) {
+                       if (InstanceExpression != null && InstanceExpression.Type.IsValueType && !(InstanceExpression is IMemoryLocation)) {
                                // FIXME: Provide better error reporting.
                                Error (1612, "Cannot modify expression because it is not a variable.");
                                return null;
@@ -3363,27 +3578,17 @@ namespace Mono.CSharp {
                        if (is_static)
                                return;
 
-                       //
-                       // In case it escapes StaticMemberCheck due to IdenticalTypeAndName.
-                       // This happens in cases like 'string String', 'int Int32', etc.
-                       // where the "IdenticalTypeAndName" mechanism is fooled.
-                       //
-                       if (instance_expr == null) {
-                               SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
-                               return;
-                       }
-
-                       if (instance_expr.Type.IsValueType) {
-                               if (instance_expr is IMemoryLocation) {
-                                       ((IMemoryLocation) instance_expr).AddressOf (ec, AddressOp.LoadStore);
+                       if (InstanceExpression.Type.IsValueType) {
+                               if (InstanceExpression is IMemoryLocation) {
+                                       ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
                                } else {
-                                       LocalTemporary t = new LocalTemporary (ec, instance_expr.Type);
-                                       instance_expr.Emit (ec);
+                                       LocalTemporary t = new LocalTemporary (ec, InstanceExpression.Type);
+                                       InstanceExpression.Emit (ec);
                                        t.Store (ec);
                                        t.AddressOf (ec, AddressOp.Store);
                                }
                        } else
-                               instance_expr.Emit (ec);
+                               InstanceExpression.Emit (ec);
                        
                        if (prepared)
                                ec.ig.Emit (OpCodes.Dup);
@@ -3400,7 +3605,7 @@ namespace Mono.CSharp {
                        //
                        if ((getter == TypeManager.system_int_array_get_length) ||
                            (getter == TypeManager.int_array_get_length)){
-                               Type iet = instance_expr.Type;
+                               Type iet = InstanceExpression.Type;
 
                                //
                                // System.Array.Length can be called, but the Type does not
@@ -3451,20 +3656,13 @@ namespace Mono.CSharp {
                        if (temp != null)
                                temp.Emit (ec);
                }
-
-               override public void EmitStatement (EmitContext ec)
-               {
-                       Emit (ec);
-                       ec.ig.Emit (OpCodes.Pop);
-               }
        }
 
        /// <summary>
        ///   Fully resolved expression that evaluates to an Event
        /// </summary>
-       public class EventExpr : Expression, IMemberExpr {
+       public class EventExpr : MemberExpr {
                public readonly EventInfo EventInfo;
-               Expression instance_expr;
 
                bool is_static;
                MethodInfo add_accessor, remove_accessor;
@@ -3489,50 +3687,72 @@ namespace Mono.CSharp {
                                type = EventInfo.EventHandlerType;
                }
 
-               public string Name {
+               public override string Name {
                        get {
                                return EventInfo.Name;
                        }
                }
 
-               public bool IsInstance {
+               public override bool IsInstance {
                        get {
                                return !is_static;
                        }
                }
 
-               public bool IsStatic {
+               public override bool IsStatic {
                        get {
                                return is_static;
                        }
                }
 
-               public Type DeclaringType {
+               public override Type DeclaringType {
                        get {
                                return EventInfo.DeclaringType;
                        }
                }
 
-               public Expression InstanceExpression {
-                       get {
-                               return instance_expr;
-                       }
+               public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
+                                                               SimpleName original)
+               {
+                       //
+                       // If the event is local to this class, we transform ourselves into a FieldExpr
+                       //
 
-                       set {
-                               instance_expr = value;
+                       if (EventInfo.DeclaringType == ec.ContainerType ||
+                           TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
+                               MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo);
+
+                               if (mi != null) {
+                                       MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec, mi, loc);
+
+                                       if (ml == null) {
+                                               Report.Error (-200, loc, "Internal error!!");
+                                               return null;
+                                       }
+
+                                       InstanceExpression = null;
+                               
+                                       return ml.ResolveMemberAccess (ec, left, loc, original);
+                               }
                        }
+
+                       return base.ResolveMemberAccess (ec, left, loc, original);
                }
 
+
                bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
                {
-                       if ((instance_expr == null) && ec.IsStatic && !is_static) {
+                       if ((InstanceExpression == null) && ec.IsStatic && !is_static) {
                                SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name);
                                return false;
                        }
 
-                       if (instance_expr != null) {
-                               instance_expr = instance_expr.DoResolve (ec);
-                               if (instance_expr == null)
+                       if (!IsInstance || InstanceExpression == EmptyExpression.Null)
+                               InstanceExpression = null;
+
+                       if (InstanceExpression != null) {
+                               InstanceExpression = InstanceExpression.DoResolve (ec);
+                               if (InstanceExpression == null)
                                        return false;
                        }
 
@@ -3540,9 +3760,9 @@ namespace Mono.CSharp {
                        // This is using the same mechanism as the CS1540 check in PropertyExpr.
                        // However, in the Event case, we reported a CS0122 instead.
                        //
-                       if (must_do_cs1540_check && (instance_expr != null)) {
-                               if ((instance_expr.Type != ec.ContainerType) &&
-                                       ec.ContainerType.IsSubclassOf (instance_expr.Type)) {
+                       if (must_do_cs1540_check && (InstanceExpression != null)) {
+                               if ((InstanceExpression.Type != ec.ContainerType) &&
+                                       ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
                                        Report.Error (122, loc, "'{0}' is inaccessible due to its protection level",
                                                DeclaringType.Name + "." + EventInfo.Name);
 
@@ -3560,15 +3780,18 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       if (instance_expr != null) {
-                               instance_expr = instance_expr.DoResolve (ec);
-                               if (instance_expr == null)
+                       if (!IsInstance)
+                               InstanceExpression = null;
+
+                       if (InstanceExpression != null) {
+                               InstanceExpression = InstanceExpression.DoResolve (ec);
+                               if (InstanceExpression == null)
                                        return null;
                        }
 
                        bool must_do_cs1540_check;
-                       if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check)
-                                   && IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
+                       if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) &&
+                             IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
                                
                                Report.Error (122, loc, "'{0}' is inaccessible due to its protection level",
                                                DeclaringType.Name + "." + EventInfo.Name);
@@ -3583,7 +3806,7 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       if (instance_expr is This)
+                       if (InstanceExpression is This)
                                Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=, try calling the actual delegate", Name);
                        else
                                Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
@@ -3602,10 +3825,10 @@ namespace Mono.CSharp {
                        
                        if (source_del.IsAddition)
                                Invocation.EmitCall (
-                                       ec, false, IsStatic, instance_expr, add_accessor, args, loc);
+                                       ec, false, IsStatic, InstanceExpression, add_accessor, args, loc);
                        else
                                Invocation.EmitCall (
-                                       ec, false, IsStatic, instance_expr, remove_accessor, args, loc);
+                                       ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc);
                }
        }
 }