**** Merged from MCS ****
[mono.git] / mcs / gmcs / ecore.cs
index da16aeda8f08348f62a46a50f1a8e31241ad67e4..8dd46c5aee3555a64dd43742f0b77feea978e4b5 100755 (executable)
@@ -92,6 +92,25 @@ namespace Mono.CSharp {
                void AddressOf (EmitContext ec, AddressOp mode);
        }
 
+       /// <summary>
+       ///   We are either a namespace or a type.
+       ///   If we're a type, `IsType' is true and we may use `Type' to get
+       ///   a TypeExpr representing that type.
+       /// </summary>
+       public interface IAlias {
+               bool IsType {
+                       get;
+               }
+
+               string Name {
+                       get;
+               }
+
+               TypeExpr Type {
+                       get;
+               }
+       }
+
        /// <summary>
        ///   This interface is implemented by variables
        /// </summary>
@@ -251,15 +270,9 @@ namespace Mono.CSharp {
                // value will be returned if the expression is not a type
                // reference
                //
-               public Expression ResolveAsTypeTerminal (EmitContext ec)
+               public TypeExpr ResolveAsTypeTerminal (EmitContext ec)
                {
-                       Expression e = ResolveAsTypeStep (ec);
-
-                       if (e == null)
-                               return null;
-                       if (e is SimpleName)
-                               return null;
-                       return e;
+                       return ResolveAsTypeStep (ec) as TypeExpr;
                }
               
                /// <summary>
@@ -320,10 +333,12 @@ namespace Mono.CSharp {
                                break;
 
                        case ExprClass.MethodGroup:
+                               if (!RootContext.V2){
                                if ((flags & ResolveFlags.MethodGroup) == 0) {
                                        ((MethodGroupExpr) e).ReportUsageError ();
                                        return null;
                                }
+                               }
                                break;
 
                        case ExprClass.Value:
@@ -393,7 +408,7 @@ namespace Mono.CSharp {
                                        return null;
                                }
 
-                               if (e.type == null)
+                               if ((e.type == null) && !(e is ConstructedType))
                                        throw new Exception ("Expression " + e +
                                                             " did not set its type after Resolve");
                        }
@@ -411,6 +426,12 @@ namespace Mono.CSharp {
                /// </remarks>
                public abstract void Emit (EmitContext ec);
 
+               public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               {
+                       Emit (ec);
+                       ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+               }
+
                /// <summary>
                ///   Protected constructor.  Only derivate types should
                ///   be able to be created
@@ -464,7 +485,11 @@ namespace Mono.CSharp {
                        else if (t == TypeManager.bool_type)
                                return new BoolConstant ((bool) v);
                        else if (TypeManager.IsEnumType (t)){
-                               Constant e = Constantify (v, TypeManager.TypeToCoreType (v.GetType ()));
+                               Type real_type = TypeManager.TypeToCoreType (v.GetType ());
+                               if (real_type == t)
+                                       real_type = real_type.UnderlyingSystemType;
+
+                               Constant e = Constantify (v, real_type);
 
                                return new EnumConstant (e, t);
                        } else
@@ -484,7 +509,7 @@ namespace Mono.CSharp {
                        else if (mi is PropertyInfo)
                                return new PropertyExpr (ec, (PropertyInfo) mi, loc);
                        else if (mi is Type){
-                               return new TypeExpr ((System.Type) mi, loc);
+                               return new TypeExpression ((System.Type) mi, loc);
                        }
 
                        return null;
@@ -534,8 +559,8 @@ namespace Mono.CSharp {
                                                       string name, MemberTypes mt,
                                                       BindingFlags bf, Location loc)
                {
-                       MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type,
-                                                                    queried_type, mt, bf, name);
+                       MemberInfo [] mi = TypeManager.MemberLookup (
+                               container_type, qualifier_type,queried_type, mt, bf, name);
 
                        if (mi == null)
                                return null;
@@ -592,7 +617,8 @@ namespace Mono.CSharp {
                ///   find it.
                /// </summary>
                public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
-                                                           Type queried_type, string name, Location loc)
+                                                           Type queried_type, string name,
+                                                           Location loc)
                {
                        return MemberLookupFinal (ec, qualifier_type, queried_type, name,
                                                  AllMemberTypes, AllBindingFlags, loc);
@@ -617,7 +643,8 @@ namespace Mono.CSharp {
                        if (errors < Report.Errors)
                                return null;
 
-                       MemberLookupFailed (ec, qualifier_type, queried_type, name, null, loc);
+                       MemberLookupFailed (ec, qualifier_type, queried_type, name,
+                                           null, loc);
                        return null;
                }
 
@@ -625,11 +652,11 @@ namespace Mono.CSharp {
                                                       Type queried_type, string name,
                                                       string class_name, Location loc)
                {
-                       object lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
-                                                                 AllMemberTypes, AllBindingFlags |
-                                                                 BindingFlags.NonPublic, name);
+                       MemberInfo[] mi = TypeManager.MemberLookup (queried_type, null, queried_type,
+                                                                   AllMemberTypes, AllBindingFlags |
+                                                                   BindingFlags.NonPublic, name);
 
-                       if (lookup == null) {
+                       if (mi == null) {
                                if (class_name != null)
                                        Report.Error (103, loc, "The name `" + name + "' could not be " +
                                                      "found in `" + class_name + "'");
@@ -640,6 +667,21 @@ namespace Mono.CSharp {
                                return;
                        }
 
+                       if (TypeManager.MemberLookup (queried_type, null, queried_type,
+                                                     AllMemberTypes, AllBindingFlags |
+                                                     BindingFlags.NonPublic, name) == null) {
+                               if ((mi.Length == 1) && (mi [0] is Type)) {
+                                       Type t = (Type) mi [0];
+
+                                       Report.Error (305, loc,
+                                                     "Using the generic type `{0}' " +
+                                                     "requires {1} type arguments",
+                                                     TypeManager.GetFullName (t),
+                                                     TypeManager.GetNumberOfTypeArguments (t));
+                                       return;
+                               }
+                       }
+
                        if ((qualifier_type != null) && (qualifier_type != ec.ContainerType) &&
                            ec.ContainerType.IsSubclassOf (qualifier_type)) {
                                // Although a derived class can access protected members of
@@ -648,11 +690,11 @@ namespace Mono.CSharp {
                                // ec.ContainerType and the lookup succeeds with the latter one,
                                // then we are in this situation.
 
-                               lookup = TypeManager.MemberLookup (
+                               mi = TypeManager.MemberLookup (
                                        ec.ContainerType, ec.ContainerType, ec.ContainerType,
                                        AllMemberTypes, AllBindingFlags, name);
 
-                               if (lookup != null) {
+                               if (mi != null) {
                                        Report.Error (
                                                1540, loc, "Cannot access protected member `" +
                                                TypeManager.CSharpName (qualifier_type) + "." +
@@ -669,11 +711,15 @@ namespace Mono.CSharp {
                                Report.Error (
                                        122, loc, "`" + TypeManager.CSharpName (qualifier_type) + "." +
                                        name + "' is inaccessible due to its protection level");
-                       else
+                       else if (name == ".ctor") {
+                               Report.Error (143, loc, String.Format ("The type {0} has no constructors defined",
+                                                                      TypeManager.CSharpName (queried_type)));
+                       } else {
                                Report.Error (
                                        122, loc, "`" + name + "' is inaccessible due to its " +
                                        "protection level");
                }
+               }
 
                static public MemberInfo GetFieldFromEvent (EventExpr event_expr)
                {
@@ -711,7 +757,8 @@ namespace Mono.CSharp {
 
                        ArrayList arguments = new ArrayList ();
                        arguments.Add (new Argument (e, Argument.AType.Expression));
-                       method = Invocation.OverloadResolve (ec, (MethodGroupExpr) operator_group, arguments, loc);
+                       method = Invocation.OverloadResolve (
+                               ec, (MethodGroupExpr) operator_group, arguments, false, loc);
 
                        if (method == null)
                                return null;
@@ -826,7 +873,7 @@ namespace Mono.CSharp {
                               "a `" + sb.ToString () + "' was expected");
                }
                
-               static void Error_ConstantValueCannotBeConverted (Location l, string val, Type t)
+               static public void Error_ConstantValueCannotBeConverted (Location l, string val, Type t)
                {
                        Report.Error (31, l, "Constant value `" + val + "' cannot be converted to " +
                                      TypeManager.CSharpName (t));
@@ -1320,6 +1367,12 @@ namespace Mono.CSharp {
        public class EmptyCast : Expression {
                protected Expression child;
                
+               public Expression Child {
+                       get {
+                               return child;
+                       }
+               }               
+
                public EmptyCast (Expression child, Type return_type)
                {
                        eclass = child.eclass;
@@ -1503,6 +1556,10 @@ namespace Mono.CSharp {
                {
                        return Child.ConvertToInt ();
                }
+               
+               public override bool IsZeroInteger {
+                       get { return Child.IsZeroInteger; }
+               }
        }
 
        /// <summary>
@@ -1516,11 +1573,13 @@ namespace Mono.CSharp {
                public BoxedCast (Expression expr)
                        : base (expr, TypeManager.object_type) 
                {
+                       eclass = ExprClass.Value;
                }
 
                public BoxedCast (Expression expr, Type target_type)
                        : base (expr, target_type)
                {
+                       eclass = ExprClass.Value;
                }
                
                public override Expression DoResolve (EmitContext ec)
@@ -1559,9 +1618,13 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        
                        base.Emit (ec);
-                       ig.Emit (OpCodes.Unbox, t);
+                       if (t.IsGenericParameter)
+                               ig.Emit (OpCodes.Unbox_Any, t);
+                       else {
+                               ig.Emit (OpCodes.Unbox, t);
 
-                       LoadFromPtr (ig, t);
+                               LoadFromPtr (ig, t);
+                       }
                }
        }
        
@@ -1844,9 +1907,14 @@ namespace Mono.CSharp {
                {
                        base.Emit (ec);
 
-                       ec.ig.Emit (OpCodes.Castclass, type);
-               }                       
-               
+                       if (child.Type.IsGenericParameter)
+                               ec.ig.Emit (OpCodes.Box, child.Type);
+
+                       if (type.IsGenericParameter)
+                               ec.ig.Emit (OpCodes.Unbox_Any, type);
+                       else
+                               ec.ig.Emit (OpCodes.Castclass, type);
+               }
        }
        
        /// <summary>
@@ -1950,9 +2018,9 @@ namespace Mono.CSharp {
                public override Expression ResolveAsTypeStep (EmitContext ec)
                {
                        DeclSpace ds = ec.DeclSpace;
-                       NamespaceEntry ns = ds.Namespace;
-                       Type t;
-                       string alias_value;
+                       NamespaceEntry ns = ds.NamespaceEntry;
+                       TypeExpr t;
+                       IAlias alias_value;
 
                        //
                        // Since we are cheating: we only do the Alias lookup for
@@ -1963,47 +2031,48 @@ namespace Mono.CSharp {
                        else
                                alias_value = null;
 
-                       if (ec.ResolvingTypeTree){
-                               if (alias_value != null){
-                                       if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
-                                               return new TypeExpr (t, loc);
-                               }
+                       TypeParameterExpr generic_type = ds.LookupGeneric (Name, loc);
+                       if (generic_type != null)
+                               return generic_type.ResolveAsTypeTerminal (ec);
 
+                       if (ec.ResolvingTypeTree){
                                int errors = Report.Errors;
-                               Type dt = ec.DeclSpace.FindType (loc, Name);
+                               Type dt = ds.FindType (loc, Name);
                                
                                if (Report.Errors != errors)
                                        return null;
                                
                                if (dt != null)
-                                       return new TypeExpr (dt, loc);
+                                       return new TypeExpression (dt, loc);
+
+                               if (alias_value != null){
+                                       if (alias_value.IsType)
+                                               return alias_value.Type;
+                                       if ((t = RootContext.LookupType (ds, alias_value.Name, true, loc)) != null)
+                                               return t;
+                               }
                        }
 
                        //
                        // First, the using aliases
                        //
                        if (alias_value != null){
-                               if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
-                                       return new TypeExpr (t, loc);
+                               if (alias_value.IsType)
+                                       return alias_value.Type;
+                               if ((t = RootContext.LookupType (ds, alias_value.Name, true, loc)) != null)
+                                       return t;
                                
                                // we have alias value, but it isn't Type, so try if it's namespace
-                               return new SimpleName (alias_value, loc);
+                               return new SimpleName (alias_value.Name, loc);
                        }
 
-                       if (ec.IsGeneric){
-                               TypeParameterExpr generic_type = ds.LookupGeneric (Name, loc);
-                               
-                               if (generic_type != null)
-                                       return generic_type;
-                       }
-                       
                        //
                        // Stage 2: Lookup up if we are an alias to a type
                        // or a namespace.
                        //
 
                        if ((t = RootContext.LookupType (ds, Name, true, loc)) != null)
-                               return new TypeExpr (t, loc);
+                               return t;
                                
                        // No match, maybe our parent can compose us
                        // into something meaningful.
@@ -2031,34 +2100,16 @@ namespace Mono.CSharp {
                {
                        Expression e = null;
 
-                       //
-                       // Since we are cheating (is_base is our hint
-                       // that we are the beginning of the name): we
-                       // only do the Alias lookup for namespaces if
-                       // the name does not include any dots in it
-                       //
-                       NamespaceEntry ns = ec.DeclSpace.Namespace;
-                       if (is_base && ns != null){
-                               string alias_value = ns.LookupAlias (Name);
-                               if (alias_value != null){
-                                       Name = alias_value;
-                                       Type t;
-
-                                       if ((t = TypeManager.LookupType (Name)) != null)
-                                               return new TypeExpr (t, loc);
-                                       
-                                       // No match, maybe our parent can compose us
-                                       // into something meaningful.
-                                       return this;
-                               }
-                       }
-                       
-                       
                        //
                        // Stage 1: Performed by the parser (binding to locals or parameters).
                        //
                        Block current_block = ec.CurrentBlock;
                        if (current_block != null){
+                               if (is_base && current_block.IsVariableNameUsedInChildBlock(Name)) {
+                                       Report.Error (135, Location, "'" + Name + "' has a different meaning in a child block");
+                                       return null;
+                               }
+
                                LocalInfo vi = current_block.GetLocalInfo (Name);
                                if (vi != null){
                                        Expression var;
@@ -2108,8 +2159,34 @@ namespace Mono.CSharp {
                        if (e == null && ec.ContainerType != null)
                                e = MemberLookup (ec, ec.ContainerType, Name, loc);
 
-                       if (e == null)
+                       if (e == null) {
+                               //
+                               // Since we are cheating (is_base is our hint
+                               // that we are the beginning of the name): we
+                               // only do the Alias lookup for namespaces if
+                               // the name does not include any dots in it
+                               //
+                               NamespaceEntry ns = ec.DeclSpace.NamespaceEntry;
+                               if (is_base && ns != null){
+                                       IAlias alias_value = ns.LookupAlias (Name);
+                                       if (alias_value != null){
+                                               if (alias_value.IsType)
+                                                       return alias_value.Type;
+
+                                               Name = alias_value.Name;
+                                               Type t;
+
+                                               if ((t = TypeManager.LookupType (Name)) != null)
+                                                       return new TypeExpression (t, loc);
+                                       
+                                               // No match, maybe our parent can compose us
+                                               // into something meaningful.
+                                               return this;
+                                       }
+                               }
+
                                return ResolveAsTypeStep (ec);
+                       }
 
                        if (e is TypeExpr)
                                return e;
@@ -2175,22 +2252,20 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Fully resolved expression that evaluates to a type
        /// </summary>
-       public class TypeExpr : Expression {
-               public TypeExpr (Type t, Location l)
+       public abstract class TypeExpr : Expression, IAlias {
+               override public Expression ResolveAsTypeStep (EmitContext ec)
                {
-                       Type = t;
-                       eclass = ExprClass.Type;
-                       loc = l;
-               }
+                       TypeExpr t = DoResolveAsTypeStep (ec);
+                       if (t == null)
+                               return null;
 
-               public override Expression ResolveAsTypeStep (EmitContext ec)
-               {
-                       return this;
+                       eclass = ExprClass.Type;
+                       return t;
                }
 
                override public Expression DoResolve (EmitContext ec)
                {
-                       return this;
+                       return ResolveAsTypeTerminal (ec);
                }
 
                override public void Emit (EmitContext ec)
@@ -2198,9 +2273,124 @@ namespace Mono.CSharp {
                        throw new Exception ("Should never be called");
                }
 
+               public virtual bool CheckAccessLevel (DeclSpace ds)
+               {
+                       return ds.CheckAccessLevel (Type);
+               }
+
+               public virtual bool AsAccessible (DeclSpace ds, int flags)
+               {
+                       return ds.AsAccessible (Type, flags);
+               }
+
+               public virtual bool IsClass {
+                       get { return Type.IsClass; }
+               }
+
+               public virtual bool IsValueType {
+                       get { return Type.IsValueType; }
+               }
+
+               public virtual bool IsInterface {
+                       get { return Type.IsInterface; }
+               }
+
+               public virtual bool IsSealed {
+                       get { return Type.IsSealed; }
+               }
+
+               public virtual bool CanInheritFrom ()
+               {
+                       if (Type == TypeManager.enum_type ||
+                           (Type == TypeManager.value_type && RootContext.StdLib) ||
+                           Type == TypeManager.multicast_delegate_type ||
+                           Type == TypeManager.delegate_type ||
+                           Type == TypeManager.array_type)
+                               return false;
+
+                       return true;
+               }
+
+               public virtual bool IsAttribute {
+                       get {
+                               return Type == TypeManager.attribute_type ||
+                                       Type.IsSubclassOf (TypeManager.attribute_type);
+                       }
+               }
+
+               public virtual TypeExpr[] GetInterfaces ()
+               {
+                       return TypeManager.GetInterfaces (Type);
+               }
+
+               public abstract TypeExpr DoResolveAsTypeStep (EmitContext ec);
+
+               public virtual Type ResolveType (EmitContext ec)
+               {
+                       TypeExpr t = ResolveAsTypeTerminal (ec);
+                       if (t == null)
+                               return null;
+
+                       return t.Type;
+               }
+
+               public abstract string Name {
+                       get;
+               }
+
+               public override bool Equals (object obj)
+               {
+                       TypeExpr tobj = obj as TypeExpr;
+                       if (tobj == null)
+                               return false;
+
+                       return Type == tobj.Type;
+               }
+
+               public override int GetHashCode ()
+               {
+                       return Type.GetHashCode ();
+               }
+               
                public override string ToString ()
                {
-                       return Type.ToString ();
+                       return Name;
+               }
+
+               bool IAlias.IsType {
+                       get { return true; }
+               }
+
+               TypeExpr IAlias.Type {
+                       get {
+                               return this;
+                       }
+               }
+       }
+
+       public class TypeExpression : TypeExpr, IAlias {
+               public TypeExpression (Type t, Location l)
+               {
+                       Type = t;
+                       eclass = ExprClass.Type;
+                       loc = l;
+               }
+
+               public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+               {
+                       return this;
+               }
+
+               public override string Name {
+                       get {
+                               return Type.ToString ();
+                       }
+               }
+
+               string IAlias.Name {
+                       get {
+                               return Type.FullName != null ? Type.FullName : Type.Name;
+                       }
                }
        }
 
@@ -2212,31 +2402,124 @@ namespace Mono.CSharp {
        public class TypeLookupExpression : TypeExpr {
                string name;
                
-               public TypeLookupExpression (string name) : base (null, Location.Null)
+               public TypeLookupExpression (string name)
                {
                        this.name = name;
                }
 
-               public override Expression ResolveAsTypeStep (EmitContext ec)
+               public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
                {
-                       if (type == null)
-                               type = RootContext.LookupType (ec.DeclSpace, name, false, Location.Null);
+                       if (type == null) {
+                               TypeExpr texpr = RootContext.LookupType (
+                                       ec.DeclSpace, name, false, Location.Null);
+                               if (texpr == null)
+                                       return null;
+
+                               type = texpr.ResolveType (ec);
+                               if (type == null)
+                                       return null;
+                       }
+
                        return this;
                }
 
-               public override Expression DoResolve (EmitContext ec)
+               public override string Name {
+                       get {
+                               return name;
+                       }
+               }
+       }
+
+       public class TypeAliasExpression : TypeExpr, IAlias {
+               TypeExpr texpr;
+               TypeArguments args;
+               string name;
+
+               public TypeAliasExpression (TypeExpr texpr, TypeArguments args, Location l)
                {
-                       return ResolveAsTypeStep (ec);
+                       this.texpr = texpr;
+                       this.args = args;
+                       loc = texpr.Location;
+
+                       eclass = ExprClass.Type;
+                       if (args != null)
+                               name = texpr.Name + "<" + args.ToString () + ">";
+                       else
+                               name = texpr.Name;
                }
 
-               public override void Emit (EmitContext ec)
+               public override string Name {
+                       get { return name; }
+               }
+
+               public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
                {
-                       throw new Exception ("Should never be called");
+                       Type type = texpr.ResolveType (ec);
+                       if (type == null)
+                               return null;
+
+                       int num_args = TypeManager.GetNumberOfTypeArguments (type);
+
+                       if (args != null) {
+                               if (num_args == 0) {
+                                       Report.Error (308, loc,
+                                                     "The non-generic type `{0}' cannot " +
+                                                     "be used with type arguments.",
+                                                     TypeManager.CSharpName (type));
+                                       return null;
+                               }
+
+                               ConstructedType ctype = new ConstructedType (type, args, loc);
+                               return ctype.ResolveAsTypeTerminal (ec);
+                       } else if (num_args > 0) {
+                               Report.Error (305, loc,
+                                             "Using the generic type `{0}' " +
+                                             "requires {1} type arguments",
+                                             TypeManager.GetFullName (type), num_args);
+                               return null;
+                       }
+
+                       return new TypeExpression (type, loc);
                }
 
-               public override string ToString ()
+               public override Type ResolveType (EmitContext ec)
+               {
+                       TypeExpr t = ResolveAsTypeTerminal (ec);
+                       if (t == null)
+                               return null;
+
+                       type = t.ResolveType (ec);
+                       return type;
+               }
+
+               public override bool CheckAccessLevel (DeclSpace ds)
+               {
+                       return texpr.CheckAccessLevel (ds);
+               }
+
+               public override bool AsAccessible (DeclSpace ds, int flags)
                {
-                       return name;
+                       return texpr.AsAccessible (ds, flags);
+               }
+
+               public override bool IsClass {
+                       get { return texpr.IsClass; }
+               }
+
+               public override bool IsValueType {
+                       get { return texpr.IsValueType; }
+               }
+
+               public override bool IsInterface {
+                       get { return texpr.IsInterface; }
+               }
+
+               public override bool IsSealed {
+                       get { return texpr.IsSealed; }
+               }
+
+               public override bool IsAttribute {
+                       get { return texpr.IsAttribute; }
                }
        }
 
@@ -2249,6 +2532,7 @@ namespace Mono.CSharp {
                public MethodBase [] Methods;
                Expression instance_expression = null;
                bool is_explicit_impl = false;
+               bool has_type_arguments = false;
                
                public MethodGroupExpr (MemberInfo [] mi, Location l)
                {
@@ -2313,10 +2597,20 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool HasTypeArguments {
+                       get {
+                               return has_type_arguments;
+                       }
+
+                       set {
+                               has_type_arguments = value;
+                       }
+               }
+
                public string Name {
                        get {
-                               //return Methods [0].Name;
-                                return Methods [Methods.Length - 1].Name;
+                                return TypeManager.CSharpSignature (
+                                       Methods [Methods.Length - 1]);
                        }
                }
 
@@ -2414,7 +2708,7 @@ namespace Mono.CSharp {
                {
                        FieldInfo = fi;
                        eclass = ExprClass.Variable;
-                       type = fi.FieldType;
+                       type = TypeManager.TypeToCoreType (fi.FieldType);
                        loc = l;
                }
 
@@ -2528,14 +2822,23 @@ namespace Mono.CSharp {
 
                        FieldBase fb = TypeManager.GetField (FieldInfo);
                        if (fb != null)
-                               fb.IsAssigned = true;
+                               fb.SetAssigned ();
 
                        //
                        // InitOnly fields can only be assigned in constructors
                        //
 
                        if (ec.IsConstructor){
-                               if (ec.ContainerType == FieldInfo.DeclaringType)
+                               if (IsStatic && !ec.IsStatic)
+                                       Report_AssignToReadonly (false);
+
+                               Type ctype;
+                               if (ec.TypeContainer.CurrentType != null)
+                                       ctype = ec.TypeContainer.CurrentType.ResolveType (ec);
+                               else
+                                       ctype = ec.ContainerType;
+
+                               if (TypeManager.IsEqual (ctype, FieldInfo.DeclaringType))
                                        return this;
                        }
 
@@ -2560,11 +2863,12 @@ namespace Mono.CSharp {
 
                        if (FieldInfo is FieldBuilder){
                                FieldBase f = TypeManager.GetField (FieldInfo);
-
-                               if ((f.ModFlags & Modifiers.VOLATILE) != 0)
-                                       is_volatile = true;
-                               
-                               f.status |= Field.Status.USED;
+                               if (f != null){
+                                       if ((f.ModFlags & Modifiers.VOLATILE) != 0)
+                                               is_volatile = true;
+                                       
+                                       f.status |= Field.Status.USED;
+                               }
                        } 
                        
                        if (FieldInfo.IsStatic){
@@ -2582,9 +2886,6 @@ namespace Mono.CSharp {
                                if (!(instance_expr is IMemoryLocation)){
                                        tempo = new LocalTemporary (ec, instance_expr.Type);
                                        
-                                       if (ec.RemapToProxy)
-                                               ec.EmitThis ();
-                       
                                        InstanceExpression.Emit (ec);
                                        tempo.Store (ec);
                                        ml = tempo;
@@ -2593,10 +2894,7 @@ namespace Mono.CSharp {
                                
                                ml.AddressOf (ec, AddressOp.Load);
                        } else {
-                               if (ec.RemapToProxy)
-                                       ec.EmitThis ();
-                               else
-                                       instance_expr.Emit (ec);
+                               instance_expr.Emit (ec);
                        }
                        if (is_volatile)
                                ig.Emit (OpCodes.Volatile);
@@ -2615,7 +2913,7 @@ namespace Mono.CSharp {
                                Report_AssignToReadonly (!is_static);
                                return;
                        }
-                       
+
                        if (!is_static){
                                Expression instance = instance_expr;
 
@@ -2624,10 +2922,7 @@ namespace Mono.CSharp {
 
                                        ml.AddressOf (ec, AddressOp.Store);
                                } else {
-                                       if (ec.RemapToProxy)
-                                               ec.EmitThis ();
-                                       else
-                                               instance.Emit (ec);
+                                       instance.Emit (ec);
                                }
                        }
 
@@ -2635,11 +2930,12 @@ namespace Mono.CSharp {
 
                        if (FieldInfo is FieldBuilder){
                                FieldBase f = TypeManager.GetField (FieldInfo);
-                               
-                               if ((f.ModFlags & Modifiers.VOLATILE) != 0)
-                                       ig.Emit (OpCodes.Volatile);
-                               
-                               f.status |= Field.Status.ASSIGNED;
+                               if (f != null){
+                                       if ((f.ModFlags & Modifiers.VOLATILE) != 0)
+                                               ig.Emit (OpCodes.Volatile);
+                                       
+                                       f.status |= Field.Status.ASSIGNED;
+                               }
                        } 
 
                        if (is_static)
@@ -2654,24 +2950,38 @@ namespace Mono.CSharp {
                        
                        if (FieldInfo is FieldBuilder){
                                FieldBase f = TypeManager.GetField (FieldInfo);
-                               if ((f.ModFlags & Modifiers.VOLATILE) != 0){
-                                       Error (676, "volatile variable: can not take its address, or pass as ref/out parameter");
-                                       return;
+                               if (f != null){
+                                       if ((f.ModFlags & Modifiers.VOLATILE) != 0){
+                                               Error (676, "volatile variable: can not take its address, or pass as ref/out parameter");
+                                               return;
+                                       }
+                                       
+                                       if ((mode & AddressOp.Store) != 0)
+                                               f.status |= Field.Status.ASSIGNED;
+                                       if ((mode & AddressOp.Load) != 0)
+                                               f.status |= Field.Status.USED;
                                }
-                               
-                               if ((mode & AddressOp.Store) != 0)
-                                       f.status |= Field.Status.ASSIGNED;
-                               if ((mode & AddressOp.Load) != 0)
-                                       f.status |= Field.Status.USED;
                        } 
 
                        //
                        // Handle initonly fields specially: make a copy and then
                        // get the address of the copy.
                        //
-                       if (FieldInfo.IsInitOnly && !ec.IsConstructor){
+                       bool need_copy;
+                       if (FieldInfo.IsInitOnly){
+                               need_copy = true;
+                               if (ec.IsConstructor){
+                                       if (FieldInfo.IsStatic){
+                                               if (ec.IsStatic)
+                                                       need_copy = false;
+                                       } else
+                                               need_copy = false;
+                               }
+                       } else
+                               need_copy = false;
+                       
+                       if (need_copy){
                                LocalBuilder local;
-                               
                                Emit (ec);
                                local = ig.DeclareLocal (type);
                                ig.Emit (OpCodes.Stloc, local);
@@ -2679,9 +2989,10 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       if (FieldInfo.IsStatic)
+
+                       if (FieldInfo.IsStatic){
                                ig.Emit (OpCodes.Ldsflda, FieldInfo);
-                       else {
+                       else {
                                //
                                // In the case of `This', we call the AddressOf method, which will
                                // only load the pointer, and not perform an Ldobj immediately after
@@ -2693,13 +3004,39 @@ namespace Mono.CSharp {
                                        IMemoryLocation ml = (IMemoryLocation) instance_expr;
 
                                        ml.AddressOf (ec, AddressOp.LoadStore);
-                               } else
+                               } else {
                                        instance_expr.Emit (ec);
+
+                                       if (instance_expr.Type.IsValueType) {
+                                               LocalBuilder local = ig.DeclareLocal (instance_expr.Type);
+                                               ig.Emit(OpCodes.Stloc, local);
+                                               ig.Emit(OpCodes.Ldloca, local);
+                                               ig.Emit(OpCodes.Ldfld, FieldInfo);
+                                               LocalBuilder local2 = ig.DeclareLocal(type);
+                                               ig.Emit(OpCodes.Stloc, local2);
+                                               ig.Emit(OpCodes.Ldloca, local2);
+                                               return;
+                                       }
+                               }
                                ig.Emit (OpCodes.Ldflda, FieldInfo);
                        }
                }
        }
 
+       //
+       // A FieldExpr whose address can not be taken
+       //
+       public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
+               public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
+               {
+               }
+               
+               public new void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
+               }
+       }
+       
        /// <summary>
        ///   Expression that evaluates to a Property.  The Assign class
        ///   might set the `Value' expression if we are in an assignment.
@@ -2781,77 +3118,104 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               MethodInfo GetAccessor (Type invocation_type, string accessor_name)
+               MethodInfo FindAccessor (Type invocation_type, bool is_set)
                {
                        BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
-                               BindingFlags.Static | BindingFlags.Instance;
-                       MemberInfo[] group;
+                               BindingFlags.Static | BindingFlags.Instance |
+                               BindingFlags.DeclaredOnly;
 
-                       group = TypeManager.MemberLookup (
-                               invocation_type, invocation_type, PropertyInfo.DeclaringType,
-                               MemberTypes.Method, flags, accessor_name + "_" + PropertyInfo.Name);
+                       Type current = PropertyInfo.DeclaringType;
+                       for (; current != null; current = current.BaseType) {
+                               MemberInfo[] group = TypeManager.MemberLookup (
+                                       invocation_type, invocation_type, current,
+                                       MemberTypes.Property, flags, PropertyInfo.Name);
 
-                       //
-                       // The first method is the closest to us
-                       //
-                       if (group == null)
+                               if (group == null)
+                                       continue;
+
+                               if (group.Length != 1)
+                                       // Oooops, can this ever happen ?
+                                       return null;
+
+                               PropertyInfo pi = (PropertyInfo) group [0];
+
+                               MethodInfo get = pi.GetGetMethod (true);
+                               MethodInfo set = pi.GetSetMethod (true);
+
+                               if (is_set) {
+                                       if (set != null)
+                                               return set;
+                               } else {
+                                       if (get != null)
+                                               return get;
+                               }
+
+                               MethodInfo accessor = get != null ? get : set;
+                               if (accessor == null)
+                                       continue;
+                               if ((accessor.Attributes & MethodAttributes.NewSlot) != 0)
+                                       break;
+                       }
+
+                       return null;
+               }
+
+               MethodInfo GetAccessor (Type invocation_type, bool is_set)
+               {
+                       MethodInfo mi = FindAccessor (invocation_type, is_set);
+                       if (mi == null)
                                return null;
 
-                       foreach (MethodInfo mi in group) {
-                               MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
+                       MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
 
-                               //
-                               // If only accessible to the current class or children
-                               //
-                               if (ma == MethodAttributes.Private) {
-                                       Type declaring_type = mi.DeclaringType;
+                       //
+                       // If only accessible to the current class or children
+                       //
+                       if (ma == MethodAttributes.Private) {
+                               Type declaring_type = mi.DeclaringType;
                                        
-                                       if (invocation_type != declaring_type){
-                                               if (TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType))
-                                                       return mi;
-                                               else
-                                                       continue;
-                                       } else
+                               if (invocation_type != declaring_type){
+                                       if (TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType))
                                                return mi;
-                               }
-                               //
-                               // FamAndAssem requires that we not only derivate, but we are on the
-                               // same assembly.  
-                               //
-                               if (ma == MethodAttributes.FamANDAssem){
-                                       if (mi.DeclaringType.Assembly != invocation_type.Assembly)
-                                               continue;
                                        else
-                                               return mi;
-                               }
+                                               return null;
+                               } else
+                                       return mi;
+                       }
+                       //
+                       // FamAndAssem requires that we not only derivate, but we are on the
+                       // same assembly.  
+                       //
+                       if (ma == MethodAttributes.FamANDAssem){
+                               if (mi.DeclaringType.Assembly != invocation_type.Assembly)
+                                       return null;
+                               else
+                                       return mi;
+                       }
 
-                               // 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)
-                                               continue;
-                                       else
-                                               return mi;
-                               }
+                       // 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)
+                                       return mi;
+                       }
 
-                               // We already know that we aren't in the same assembly.
-                               if (ma == MethodAttributes.Assembly)
-                                       continue;
+                       // We already know that we aren't in the same assembly.
+                       if (ma == MethodAttributes.Assembly)
+                               return null;
 
-                               // Family and FamANDAssem require that we derive.
-                               if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
-                                       if (!TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType))
-                                               continue;
-                                       else {
+                       // Family and FamANDAssem require that we derive.
+                       if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem) || (ma == MethodAttributes.FamORAssem)){
+                               if (!TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType))
+                                       return null;
+                               else {
+                                       if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
                                                must_do_cs1540_check = true;
 
-                                               return mi;
-                                       }
+                                       return mi;
                                }
-
-                               return mi;
                        }
 
-                       return null;
+                       return mi;
                }
 
                //
@@ -2860,11 +3224,11 @@ namespace Mono.CSharp {
                //
                void ResolveAccessors (EmitContext ec)
                {
-                       getter = GetAccessor (ec.ContainerType, "get");
+                       getter = GetAccessor (ec.ContainerType, false);
                        if ((getter != null) && getter.IsStatic)
                                is_static = true;
 
-                       setter = GetAccessor (ec.ContainerType, "set");
+                       setter = GetAccessor (ec.ContainerType, true);
                        if ((setter != null) && setter.IsStatic)
                                is_static = true;
 
@@ -2907,6 +3271,16 @@ namespace Mono.CSharp {
                
                override public Expression DoResolve (EmitContext ec)
                {
+                       if (getter != null){
+                               if (TypeManager.GetArgumentTypes (getter).Length != 0){
+                                       Report.Error (
+                                               117, loc, "`{0}' does not contain a " +
+                                               "definition for `{1}'.", getter.DeclaringType,
+                                               Name);
+                                       return null;
+                               }
+                       }
+
                        if (getter == null){
                                //
                                // The following condition happens if the PropertyExpr was
@@ -2958,6 +3332,14 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       if (TypeManager.GetArgumentTypes (setter).Length != 1){
+                               Report.Error (
+                                       117, loc, "`{0}' does not contain a " +
+                                       "definition for `{1}'.", getter.DeclaringType,
+                                       Name);
+                               return null;
+                       }
+
                        if (!InstanceResolve (ec))
                                return null;
                        
@@ -2988,6 +3370,7 @@ namespace Mono.CSharp {
                                if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)){
                                        instance_expr.Emit (ec);
                                        ec.ig.Emit (OpCodes.Ldlen);
+                                       ec.ig.Emit (OpCodes.Conv_I4);
                                        return;
                                }
                        }
@@ -3098,14 +3481,15 @@ namespace Mono.CSharp {
 
                public void EmitAddOrRemove (EmitContext ec, Expression source)
                {
-                       Expression handler = ((Binary) source).Right;
+                       BinaryDelegate source_del = (BinaryDelegate) source;
+                       Expression handler = source_del.Right;
                        
                        Argument arg = new Argument (handler, Argument.AType.Expression);
                        ArrayList args = new ArrayList ();
                                
                        args.Add (arg);
                        
-                       if (((Binary) source).Oper == Binary.Operator.Addition)
+                       if (source_del.IsAddition)
                                Invocation.EmitCall (
                                        ec, false, IsStatic, instance_expr, add_accessor, args, loc);
                        else