[Mono.CSharp] Fix bug where overwriting variables cleared the wrong value
[mono.git] / mcs / mcs / class.cs
index 56a89ef00234ebc6dcc9b41dcc74fe8fa7003913..943db46deabceb0b05b664c0a6372b029a967052 100644 (file)
 
 using System;
 using System.Collections.Generic;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Security;
 using System.Security.Permissions;
-using System.Text;
 using System.Linq;
 
 #if NET_2_1
 using XmlElement = System.Object;
-#else
-using System.Xml;
 #endif
 
-using Mono.CompilerServices.SymbolWriter;
+#if STATIC
+using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
+using IKVM.Reflection;
+using IKVM.Reflection.Emit;
+#else
+using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
+using System.Reflection;
+using System.Reflection.Emit;
+#endif
 
 namespace Mono.CSharp {
 
@@ -85,12 +87,16 @@ namespace Mono.CSharp {
                                get { return tc.IsStatic; }
                        }
 
+                       public ModuleContainer Module {
+                               get { return tc.Module; }
+                       }
+
                        public string GetSignatureForError ()
                        {
                                return tc.GetSignatureForError ();
                        }
 
-                       public ExtensionMethodGroupExpr LookupExtensionMethod (TypeSpec extensionType, string name, int arity, Location loc)
+                       public IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceEntry scope)
                        {
                                return null;
                        }
@@ -166,7 +172,11 @@ namespace Mono.CSharp {
                List<MemberCore> operators;
 
                // Holds the compiler generated classes
-               List<CompilerGeneratedClass> compiler_generated;
+               protected List<CompilerGeneratedClass> compiler_generated;
+
+               Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
+
+               Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
 
                //
                // Pointers to the default constructor and the default static constructor
@@ -180,13 +190,14 @@ namespace Mono.CSharp {
                // This is an arbitrary choice.  We are interested in looking at _some_ non-static field,
                // and the first one's as good as any.
                //
-               FieldBase first_nonstatic_field = null;
+               FieldBase first_nonstatic_field;
 
                //
                // This one is computed after we can distinguish interfaces
                // from classes from the arraylist `type_bases' 
                //
-               TypeExpr base_type;
+               protected TypeSpec base_type;
+               protected TypeExpr base_type_expr;
                protected TypeExpr[] iface_exprs;
 
                protected List<FullNamedExpression> type_bases;
@@ -213,6 +224,8 @@ namespace Mono.CSharp {
 
                List<TypeContainer> partial_parts;
 
+               public int DynamicSitesCounter;
+
                /// <remarks>
                ///  The pending methods that need to be implemented
                //   (interfaces or abstract methods)
@@ -266,6 +279,18 @@ namespace Mono.CSharp {
                        }
                }
 
+               public virtual AssemblyDefinition DeclaringAssembly {
+                       get {
+                               return Module.DeclaringAssembly;
+                       }
+               }
+
+               IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
+                       get {
+                               return Module.DeclaringAssembly;
+                       }
+               }
+
                public TypeSpec Definition {
                        get {
                                return spec;
@@ -285,6 +310,11 @@ namespace Mono.CSharp {
                        return AddToContainer (symbol, symbol.MemberName.Basename);
                }
 
+               public bool AddMember (MemberCore symbol, string name)
+               {
+                       return AddToContainer (symbol, name);
+               }
+
                protected virtual bool AddMemberType (TypeContainer ds)
                {
                        return AddToContainer (ds, ds.Basename);
@@ -363,6 +393,8 @@ namespace Mono.CSharp {
                                tc.ModFlags |= next_part.ModFlags;
                        }
 
+                       tc.spec.Modifiers = tc.ModFlags;
+
                        if (next_part.attributes != null) {
                                if (tc.attributes == null)
                                        tc.attributes = next_part.attributes;
@@ -382,9 +414,10 @@ namespace Mono.CSharp {
                        RemoveMemberType (next_part);
                }
                
-               public void AddDelegate (Delegate d)
+               public virtual TypeSpec AddDelegate (Delegate d)
                {
                        AddTypeContainer (d);
+                       return null;
                }
 
                private void AddMemberToList (MemberCore mc, List<MemberCore> alist, bool isexplicit)
@@ -427,8 +460,7 @@ namespace Mono.CSharp {
                public void AddConstructor (Constructor c)
                {
                        bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
-                       if (!AddToContainer (c, is_static ?
-                               ConstructorBuilder.ConstructorName : ConstructorBuilder.TypeConstructorName))
+                       if (!AddToContainer (c, is_static ? Constructor.ConstructorName : Constructor.TypeConstructorName))
                                return;
                        
                        if (is_static && c.ParameterInfo.IsEmpty){
@@ -481,8 +513,7 @@ namespace Mono.CSharp {
 
                public void AddProperty (Property prop)
                {
-                       if (!AddMember (prop) || 
-                               !AddMember (prop.Get) || !AddMember (prop.Set))
+                       if (!AddMember (prop))
                                return;
 
                        if (properties == null)
@@ -499,14 +530,6 @@ namespace Mono.CSharp {
                        if (!AddMember (e))
                                return;
 
-                       if (e is EventProperty) {
-                               if (!AddMember (e.Add))
-                                       return;
-
-                               if (!AddMember (e.Remove))
-                                       return;
-                       }
-
                        if (events == null)
                                events = new List<MemberCore> ();
 
@@ -589,7 +612,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public virtual TypeSpec BaseType {
+               public TypeSpec BaseType {
                        get {
                                return spec.BaseType;
                        }
@@ -631,15 +654,9 @@ namespace Mono.CSharp {
                        }
                }
 
-               public IList<CompilerGeneratedClass> CompilerGeneratedClasses {
-                       get {
-                               return compiler_generated;
-                       }
-               }
-
                protected override TypeAttributes TypeAttr {
                        get {
-                               return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) | base.TypeAttr;
+                               return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
                        }
                }
 
@@ -666,7 +683,7 @@ namespace Mono.CSharp {
                                if (OptAttributes == null)
                                        return false;
 
-                               return OptAttributes.Contains (PredefinedAttributes.Get.ComImport);
+                               return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
                        }
                }
 
@@ -744,7 +761,7 @@ namespace Mono.CSharp {
                                return;
 
                        for (int i = 0; i < initialized_fields.Count; ++i) {
-                               FieldInitializer fi = (FieldInitializer) initialized_fields [i];
+                               FieldInitializer fi = initialized_fields [i];
                                ExpressionStatement s = fi.ResolveStatement (ec);
                                if (s == null)
                                        continue;
@@ -780,7 +797,7 @@ namespace Mono.CSharp {
                        if (OptAttributes == null)
                                return null;
 
-                       Attribute a = OptAttributes.Search (PredefinedAttributes.Get.CoClass);
+                       Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
                        if (a == null)
                                return null;
 
@@ -794,12 +811,8 @@ namespace Mono.CSharp {
                                a = OptAttributes.Search (pa);
                        }
 
-                       if (a == null) {
-                               if (BaseType != TypeManager.attribute_type)
-                                       return BaseType.GetAttributeUsage (pa);
-
+                       if (a == null)
                                return null;
-                       }
 
                        return a.GetAttributeUsageAttribute ();
                }
@@ -838,11 +851,15 @@ namespace Mono.CSharp {
                                        continue;
 
                                if (i == 0 && Kind == MemberKind.Class && !fne_resolved.Type.IsInterface) {
-                                       if (fne_resolved.Type == InternalType.Dynamic)
+                                       if (fne_resolved.Type == InternalType.Dynamic) {
                                                Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
                                                        GetSignatureForError ());
-                                       else
-                                               base_class = fne_resolved;
+
+                                               continue;
+                                       }
+                                       
+                                       base_type = fne_resolved.Type;
+                                       base_class = fne_resolved;
                                        continue;
                                }
 
@@ -851,7 +868,7 @@ namespace Mono.CSharp {
 
                                if (fne_resolved.Type.IsInterface) {
                                        for (int ii = 0; ii < j; ++ii) {
-                                               if (TypeManager.IsEqual (fne_resolved.Type, ifaces [ii].Type)) {
+                                               if (fne_resolved.Type == ifaces [ii].Type) {
                                                        Report.Error (528, Location, "`{0}' is already listed in interface list",
                                                                fne_resolved.GetSignatureForError ());
                                                        break;
@@ -882,7 +899,7 @@ namespace Mono.CSharp {
                        return ifaces;
                }
 
-               TypeExpr[] GetNormalPartialBases (ref TypeExpr base_class)
+               TypeExpr[] GetNormalPartialBases ()
                {
                        var ifaces = new List<TypeExpr> (0);
                        if (iface_exprs != null)
@@ -891,18 +908,15 @@ namespace Mono.CSharp {
                        foreach (TypeContainer part in partial_parts) {
                                TypeExpr new_base_class;
                                TypeExpr[] new_ifaces = part.ResolveBaseTypes (out new_base_class);
-                               if (new_base_class != TypeManager.system_object_expr) {
-                                       if (base_class == TypeManager.system_object_expr)
-                                               base_class = new_base_class;
-                                       else {
-                                               if (new_base_class != null && !TypeManager.IsEqual (new_base_class.Type, base_class.Type)) {
-                                                       Report.SymbolRelatedToPreviousError (base_class.Location, "");
-                                                       Report.Error (263, part.Location,
-                                                               "Partial declarations of `{0}' must not specify different base classes",
-                                                               part.GetSignatureForError ());
-
-                                                       return null;
-                                               }
+                               if (new_base_class != null) {
+                                       if (base_type_expr != null && new_base_class.Type != base_type) {
+                                               Report.SymbolRelatedToPreviousError (new_base_class.Location, "");
+                                               Report.Error (263, part.Location,
+                                                       "Partial declarations of `{0}' must not specify different base classes",
+                                                       part.GetSignatureForError ());
+                                       } else {
+                                               base_type_expr = new_base_class;
+                                               base_type = base_type_expr.Type;
                                        }
                                }
 
@@ -958,10 +972,10 @@ namespace Mono.CSharp {
                                        if (o_b == null || o_b.OperatorType != matching_type)
                                                continue;
 
-                                       if (!TypeManager.IsEqual (o_a.ReturnType, o_b.ReturnType))
+                                       if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
                                                continue;
 
-                                       if (!TypeSpecComparer.Default.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
+                                       if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
                                                continue;
 
                                        operators[i] = null;
@@ -1002,19 +1016,19 @@ namespace Mono.CSharp {
                        int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null ? 1 : 0;
 
                        if (IsTopLevel) {
-                               if (GlobalRootNamespace.Instance.IsNamespace (Name)) {
+                               // TODO: Completely wrong
+                               if (Module.GlobalRootNamespace.IsNamespace (Name)) {
                                        Report.Error (519, Location, "`{0}' clashes with a predefined namespace", Name);
-                                       return false;
                                }
 
-                               ModuleBuilder builder = Module.Compiled.Builder;
-                               TypeBuilder = builder.DefineType (Name, TypeAttr, null, type_size);
+                               TypeBuilder = Module.CreateBuilder (Name, TypeAttr, type_size);
                        } else {
-                               TypeBuilder builder = Parent.TypeBuilder;
-
-                               TypeBuilder = builder.DefineNestedType (Basename, TypeAttr, null, type_size);
+                               TypeBuilder = Parent.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size);
                        }
 
+                       if (DeclaringAssembly.Importer != null)
+                               DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
+
                        spec.SetMetaInfo (TypeBuilder);
                        spec.MemberCache = new MemberCache (this);
                        spec.DeclaringType = Parent.CurrentType;
@@ -1038,11 +1052,97 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               //
+               // Creates a proxy base method call inside this container for hoisted base member calls
+               //
+               public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
+               {
+                       Method proxy_method;
+
+                       //
+                       // One proxy per base method is enough
+                       //
+                       if (hoisted_base_call_proxies == null) {
+                               hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
+                               proxy_method = null;
+                       } else {
+                               hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
+                       }
+
+                       if (proxy_method == null) {
+                               string name = CompilerGeneratedClass.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
+                               var base_parameters = new Parameter[method.Parameters.Count];
+                               for (int i = 0; i < base_parameters.Length; ++i) {
+                                       var base_param = method.Parameters.FixedParameters[i];
+                                       base_parameters[i] = new Parameter (new TypeExpression (method.Parameters.Types[i], Location),
+                                               base_param.Name, base_param.ModFlags, null, Location);
+                                       base_parameters[i].Resolve (this, i);
+                               }
+
+                               var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
+                               if (method.Parameters.HasArglist) {
+                                       cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
+                                       cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve (Location);
+                               }
+
+                               GenericMethod generic_method;
+                               MemberName member_name;
+                               if (method.IsGeneric) {
+                                       //
+                                       // Copy all base generic method type parameters info
+                                       //
+                                       var hoisted_tparams = method.GenericDefinition.TypeParameters;
+                                       var targs = new TypeArguments ();
+                                       var type_params = new TypeParameter[hoisted_tparams.Length];
+                                       for (int i = 0; i < type_params.Length; ++i) {
+                                               var tp = hoisted_tparams[i];
+                                               targs.Add (new TypeParameterName (tp.Name, null, Location));
+                                               type_params[i] = new TypeParameter (tp, null, null, new MemberName (tp.Name), null);
+                                       }
+
+                                       member_name = new MemberName (name, targs, Location);
+                                       generic_method = new GenericMethod (NamespaceEntry, this, member_name, type_params,
+                                               new TypeExpression (method.ReturnType, Location), cloned_params);
+                               } else {
+                                       member_name = new MemberName (name);
+                                       generic_method = null;
+                               }
+
+                               // Compiler generated proxy
+                               proxy_method = new Method (this, generic_method, new TypeExpression (method.ReturnType, Location),
+                                       Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
+                                       member_name, cloned_params, null);
+
+                               var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location);
+
+                               var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
+                               mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
+
+                               // Get all the method parameters and pass them as arguments
+                               var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
+                               Statement statement;
+                               if (method.ReturnType == TypeManager.void_type)
+                                       statement = new StatementExpression (real_base_call);
+                               else
+                                       statement = new Return (real_base_call, Location);
+
+                               block.AddStatement (statement);
+                               proxy_method.Block = block;
+
+                               methods.Add (proxy_method);
+                               proxy_method.Define ();
+
+                               hoisted_base_call_proxies.Add (method, proxy_method);
+                       }
+
+                       return proxy_method.Spec;
+               }
+
                bool DefineBaseTypes ()
                {
-                       iface_exprs = ResolveBaseTypes (out base_type);
+                       iface_exprs = ResolveBaseTypes (out base_type_expr);
                        if (partial_parts != null) {
-                               iface_exprs = GetNormalPartialBases (ref base_type);
+                               iface_exprs = GetNormalPartialBases ();
                        }
 
                        var cycle = CheckRecursiveDefinition (this);
@@ -1052,13 +1152,15 @@ namespace Mono.CSharp {
                                        Report.Error (529, Location,
                                                "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
                                            GetSignatureForError (), cycle.GetSignatureForError ());
+
+                                       iface_exprs = null;
                                } else {
                                        Report.Error (146, Location,
                                                "Circular base class dependency involving `{0}' and `{1}'",
                                                GetSignatureForError (), cycle.GetSignatureForError ());
-                               }
 
-                               base_type = null;
+                                       base_type = null;
+                               }
                        }
 
                        if (iface_exprs != null) {
@@ -1115,23 +1217,13 @@ namespace Mono.CSharp {
                                return true;
                        }
 
-                       TypeSpec base_ts;
-                       if (base_type != null)
-                               base_ts = base_type.Type;
-                       else if (spec.IsStruct)
-                               base_ts = TypeManager.value_type;
-                       else if (spec.IsEnum)
-                               base_ts = TypeManager.enum_type;
-                       else if (spec.IsDelegate)
-                               base_ts = TypeManager.multicast_delegate_type;
-                       else
-                               base_ts = null;
-
-                       if (base_ts != null) {
-                               spec.BaseType = base_ts;
+                       if (base_type != null) {
+                               spec.BaseType = base_type;
 
                                // Set base type after type creation
-                               TypeBuilder.SetParent (base_ts.GetMetaInfo ());
+                               TypeBuilder.SetParent (base_type.GetMetaInfo ());
+                       } else {
+                               TypeBuilder.SetParent (null);
                        }
 
                        return true;
@@ -1148,9 +1240,8 @@ namespace Mono.CSharp {
                        if (instance_constructors != null) {
                                foreach (MethodCore m in instance_constructors) {
                                        var p = m.ParameterInfo;
-                                       if (!p.IsEmpty && p[p.Count - 1].HasDefaultValue) {
-                                               var rc = new ResolveContext (m);
-                                               p.ResolveDefaultValues (rc);
+                                       if (!p.IsEmpty) {
+                                               p.ResolveDefaultValues (m);
                                        }
                                }
                        }
@@ -1158,20 +1249,15 @@ namespace Mono.CSharp {
                        if (methods != null) {
                                foreach (MethodCore m in methods) {
                                        var p = m.ParameterInfo;
-                                       if (!p.IsEmpty && p[p.Count - 1].HasDefaultValue) {
-                                               var rc = new ResolveContext (m);
-                                               p.ResolveDefaultValues (rc);
+                                       if (!p.IsEmpty) {
+                                               p.ResolveDefaultValues (m);
                                        }
                                }
                        }
 
                        if (indexers != null) {
                                foreach (Indexer i in indexers) {
-                                       var p = i.ParameterInfo;
-                                       if (p[p.Count - 1].HasDefaultValue) {
-                                           var rc = new ResolveContext (i);
-                                               p.ResolveDefaultValues (rc);
-                                       }
+                                       i.ParameterInfo.ResolveDefaultValues (i);
                                }
                        }
 
@@ -1184,17 +1270,17 @@ namespace Mono.CSharp {
                //
                // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
                //
-               public TypeBuilder CreateType ()
+               public bool CreateType ()
                {
                        if (TypeBuilder != null)
-                               return TypeBuilder;
+                               return !error;
 
                        if (error)
-                               return null;
+                               return false;
 
                        if (!CreateTypeBuilder ()) {
                                error = true;
-                               return null;
+                               return false;
                        }
 
                        if (partial_parts != null) {
@@ -1207,36 +1293,31 @@ namespace Mono.CSharp {
 
                        if (Types != null) {
                                foreach (TypeContainer tc in Types) {
-                                       if (tc.CreateType () == null) {
-                                               error = true;
-                                               return null;
-                                       }
+                                       tc.CreateType ();
                                }
                        }
 
-                       return TypeBuilder;
+                       return true;
                }
 
-               public override TypeBuilder DefineType ()
+               public override void DefineType ()
                {
                        if (error)
-                               return null;
+                               return;
                        if (type_defined)
-                               return TypeBuilder;
+                               return;
 
                        type_defined = true;
 
                        if (!DefineBaseTypes ()) {
                                error = true;
-                               return null;
+                               return;
                        }
 
                        if (!DefineNestedTypes ()) {
                                error = true;
-                               return null;
+                               return;
                        }
-
-                       return TypeBuilder;
                }
 
                public override void SetParameterInfo (List<Constraints> constraints_list)
@@ -1268,9 +1349,22 @@ namespace Mono.CSharp {
                // Replaces normal spec with predefined one when compiling corlib
                // and this type container defines predefined type
                //
-               public void SetPredefinedSpec (PredefinedTypeSpec spec)
-               {
+               public void SetPredefinedSpec (BuildinTypeSpec spec)
+               {
+                       // When compiling build-in types we start with two
+                       // version of same type. One is of BuildinTypeSpec and
+                       // second one is ordinary TypeSpec. The unification
+                       // happens at later stage when we know which type
+                       // really matches the buildin type signature. However
+                       // that means TypeSpec create during CreateType of this
+                       // type has to be replaced with buildin one
+                       // 
+                       spec.SetMetaInfo (TypeBuilder);
+                       spec.MemberCache = this.spec.MemberCache;
+                       spec.DeclaringType = this.spec.DeclaringType;
+
                        this.spec = spec;
+                       current_type = null;
                }
 
                void UpdateTypeParameterConstraints (TypeContainer part)
@@ -1335,8 +1429,7 @@ namespace Mono.CSharp {
                {
                        if (Types != null) {
                                foreach (TypeContainer tc in Types)
-                                       if (tc.DefineType () == null)
-                                               return false;
+                                       tc.DefineType ();
                        }
 
                        return true;
@@ -1349,10 +1442,10 @@ namespace Mono.CSharp {
 
                        InTransit = tc;
 
-                       if (base_type != null && base_type.Type != null) {
-                               var ptc = base_type.Type.MemberDefinition as TypeContainer;
+                       if (base_type_expr != null) {
+                               var ptc = base_type.MemberDefinition as TypeContainer;
                                if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
-                                       return base_type.Type;
+                                       return base_type;
                        }
 
                        if (iface_exprs != null) {
@@ -1396,6 +1489,9 @@ namespace Mono.CSharp {
                {
                        if (iface_exprs != null) {
                                foreach (TypeExpr iface in iface_exprs) {
+                                       if (iface == null)
+                                               continue;
+
                                        var iface_type = iface.Type;
 
                                        // Ensure the base is always setup
@@ -1417,7 +1513,7 @@ namespace Mono.CSharp {
 
                                                ct.CheckConstraints (this);
 
-                                               if (ct.HasDynamicArguments ()) {
+                                               if (ct.HasDynamicArguments () && !IsCompilerGenerated) {
                                                        Report.Error (1966, iface.Location,
                                                                "`{0}': cannot implement a dynamic interface `{1}'",
                                                                GetSignatureForError (), iface.GetSignatureForError ());
@@ -1428,15 +1524,20 @@ namespace Mono.CSharp {
                        }
 
                        if (base_type != null) {
-                               ObsoleteAttribute obsolete_attr = base_type.Type.GetAttributeObsolete ();
+                               ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
                                if (obsolete_attr != null && !IsObsolete)
                                        AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), Location, Report);
 
-                               var ct = base_type as GenericTypeExpr;
+                               var ct = base_type_expr as GenericTypeExpr;
                                if (ct != null)
                                        ct.CheckConstraints (this);
 
-                               var baseContainer = base_type.Type.MemberDefinition as ClassOrStruct;
+                               if (base_type.Interfaces != null) {
+                                       foreach (var iface in base_type.Interfaces)
+                                               spec.AddInterface (iface);
+                               }
+
+                               var baseContainer = base_type.MemberDefinition as ClassOrStruct;
                                if (baseContainer != null) {
                                        baseContainer.Define ();
 
@@ -1454,25 +1555,6 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (!IsTopLevel) {
-                               MemberSpec candidate;
-                               var conflict_symbol = MemberCache.FindBaseMember (this, out candidate);
-                               if (conflict_symbol == null && candidate == null) {
-                                       if ((ModFlags & Modifiers.NEW) != 0)
-                                               Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
-                                                       GetSignatureForError ());
-                               } else {
-                                       if ((ModFlags & Modifiers.NEW) == 0) {
-                                               if (candidate == null)
-                                                       candidate = conflict_symbol;
-
-                                               Report.SymbolRelatedToPreviousError (candidate);
-                                               Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
-                                                       GetSignatureForError (), candidate.GetSignatureForError ());
-                                       }
-                               }
-                       }
-
                        DefineContainerMembers (constants);
                        DefineContainerMembers (fields);
 
@@ -1505,13 +1587,18 @@ namespace Mono.CSharp {
                        ComputeIndexerName();
                        CheckEqualsAndGetHashCode();
 
+                       if (Kind == MemberKind.Interface && iface_exprs != null) {
+                               MemberCache.RemoveHiddenMembers (spec);
+                       }
+
                        return true;
                }
 
                protected virtual void DefineContainerMembers (System.Collections.IList mcal) // IList<MemberCore>
                {
                        if (mcal != null) {
-                               foreach (MemberCore mc in mcal) {
+                               for (int i = 0; i < mcal.Count; ++i) {
+                                       MemberCore mc = (MemberCore) mcal[i];
                                        try {
                                                mc.Define ();
                                        } catch (Exception e) {
@@ -1562,13 +1649,16 @@ namespace Mono.CSharp {
                        if (!seen_normal_indexers)
                                return;
 
-                       PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
+                       PredefinedAttribute pa = Module.PredefinedAttributes.DefaultMember;
                        if (pa.Constructor == null &&
                                !pa.ResolveConstructor (Location, TypeManager.string_type))
                                return;
 
-                       CustomAttributeBuilder cb = new CustomAttributeBuilder (pa.Constructor, new string [] { GetAttributeDefaultMember () });
-                       TypeBuilder.SetCustomAttribute (cb);
+                       var encoder = new AttributeEncoder ();
+                       encoder.Encode (GetAttributeDefaultMember ());
+                       encoder.EncodeEmptyNamedArguments ();
+
+                       pa.EmitAttribute (TypeBuilder, encoder);
                }
 
                protected virtual void CheckEqualsAndGetHashCode ()
@@ -1660,7 +1750,7 @@ namespace Mono.CSharp {
                                                if (f.OptAttributes != null || PartialContainer.HasStructLayout)
                                                        continue;
                                                
-                                               Constant c = New.Constantify (f.MemberType);
+                                               Constant c = New.Constantify (f.MemberType, f.Location);
                                                Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value `{1}'",
                                                        f.GetSignatureForError (), c == null ? "null" : c.AsString ());
                                        }
@@ -1670,6 +1760,25 @@ namespace Mono.CSharp {
 
                public override void Emit ()
                {
+                       if (!IsTopLevel) {
+                               MemberSpec candidate;
+                               var conflict_symbol = MemberCache.FindBaseMember (this, out candidate);
+                               if (conflict_symbol == null && candidate == null) {
+                                       if ((ModFlags & Modifiers.NEW) != 0)
+                                               Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
+                                                       GetSignatureForError ());
+                               } else {
+                                       if ((ModFlags & Modifiers.NEW) == 0) {
+                                               if (candidate == null)
+                                                       candidate = conflict_symbol;
+
+                                               Report.SymbolRelatedToPreviousError (candidate);
+                                               Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
+                                                       GetSignatureForError (), candidate.GetSignatureForError ());
+                                       }
+                               }
+                       }
+
                        if (all_tp_builders != null) {
                                int current_starts_index = CurrentTypeParametersStartIndex;
                                for (int i = 0; i < all_tp_builders.Length; i++) {
@@ -1682,7 +1791,12 @@ namespace Mono.CSharp {
                        }
 
                        if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
-                               PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (TypeBuilder);
+                               Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
+
+#if STATIC
+                       if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
+                               TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
+#endif
 
                        base.Emit ();
                }
@@ -1788,7 +1902,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public void CloseType ()
+               public virtual void CloseType ()
                {
                        if ((caching_flags & Flags.CloseTypeCreated) != 0)
                                return;
@@ -1796,8 +1910,12 @@ namespace Mono.CSharp {
                        // Close base type container first to avoid TypeLoadException
                        if (spec.BaseType != null) {
                                var btype = spec.BaseType.MemberDefinition as TypeContainer;
-                               if (btype != null)
+                               if (btype != null) {
                                        btype.CloseType ();
+
+                                       if ((caching_flags & Flags.CloseTypeCreated) != 0)
+                                               return;
+                               }
                        }
 
                        try {
@@ -1844,10 +1962,11 @@ namespace Mono.CSharp {
                // Performs the validation on a Method's modifiers (properties have
                // the same properties).
                //
+               // TODO: Why is it not done at parse stage ?
+               //
                public bool MethodModifiersValid (MemberCore mc)
                {
                        const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
-                       const Modifiers va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
                        const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
                        bool ok = true;
                        var flags = mc.ModFlags;
@@ -1863,13 +1982,6 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (Kind == MemberKind.Struct){
-                               if ((flags & va) != 0){
-                                       ModifiersExtensions.Error_InvalidModifier (mc.Location, "virtual or abstract", Report);
-                                       ok = false;
-                               }
-                       }
-
                        if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
                                Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
                                        mc.GetSignatureForError ());
@@ -1955,7 +2067,7 @@ namespace Mono.CSharp {
                        var ifaces = spec.Interfaces;
                        if (ifaces != null) {
                                foreach (TypeSpec t in ifaces){
-                                       if (TypeManager.IsEqual (t, mb.InterfaceType))
+                                       if (t == mb.InterfaceType)
                                                return true;
                                }
                        }
@@ -1987,11 +2099,87 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               public MemberCache LoadMembers (TypeSpec declaringType)
+               bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
+               {
+                       return Module.DeclaringAssembly == assembly;
+               }
+
+               public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
                {
                        throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
                }
 
+               //
+               // Public function used to locate types.
+               //
+               // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
+               //
+               // Returns: Type or null if they type can not be found.
+               //
+               public override FullNamedExpression LookupNamespaceOrType (string name, int arity, Location loc, bool ignore_cs0104)
+               {
+                       FullNamedExpression e;
+                       if (arity == 0 && Cache.TryGetValue (name, out e))
+                               return e;
+
+                       e = null;
+                       int errors = Report.Errors;
+
+                       if (arity == 0) {
+                               TypeParameter[] tp = CurrentTypeParameters;
+                               if (tp != null) {
+                                       TypeParameter tparam = TypeParameter.FindTypeParameter (tp, name);
+                                       if (tparam != null)
+                                               e = new TypeParameterExpr (tparam, Location.Null);
+                               }
+                       }
+
+                       if (e == null) {
+                               TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
+
+                               if (t != null)
+                                       e = new TypeExpression (t, Location.Null);
+                               else if (Parent != null) {
+                                       e = Parent.LookupNamespaceOrType (name, arity, loc, ignore_cs0104);
+                               } else
+                                       e = NamespaceEntry.LookupNamespaceOrType (name, arity, loc, ignore_cs0104);
+                       }
+
+                       // TODO MemberCache: How to cache arity stuff ?
+                       if (errors == Report.Errors && arity == 0)
+                               Cache[name] = e;
+
+                       return e;
+               }
+
+               TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
+               {
+                       // TODO: GenericMethod only
+                       if (PartialContainer == null)
+                               return null;
+
+                       // Has any nested type
+                       // Does not work, because base type can have
+                       //if (PartialContainer.Types == null)
+                       //      return null;
+
+                       var container = PartialContainer.CurrentType;
+
+                       // Is not Root container
+                       if (container == null)
+                               return null;
+
+                       var t = MemberCache.FindNestedType (container, name, arity);
+                       if (t == null)
+                               return null;
+
+                       // FIXME: Breaks error reporting
+                       if (!t.IsAccessible (CurrentType))
+                               return null;
+
+                       return t;
+               }
+
                public void Mark_HasEquals ()
                {
                        cached_method |= CachedMethods.Equals;
@@ -2048,7 +2236,7 @@ namespace Mono.CSharp {
 
        public abstract class ClassOrStruct : TypeContainer
        {
-               Dictionary<SecurityAction, PermissionSet> declarative_security;
+               SecurityType declarative_security;
 
                public ClassOrStruct (NamespaceEntry ns, DeclSpace parent,
                                      MemberName name, Attributes attrs, MemberKind kind)
@@ -2058,14 +2246,14 @@ namespace Mono.CSharp {
 
                protected override bool AddToContainer (MemberCore symbol, string name)
                {
-                       if (name == MemberName.Name) {
+                       if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
                                if (symbol is TypeParameter) {
                                        Report.Error (694, symbol.Location,
                                                "Type parameter `{0}' has same name as containing type, or method",
                                                symbol.GetSignatureForError ());
                                        return false;
                                }
-
+                       
                                InterfaceMemberBase imb = symbol as InterfaceMemberBase;
                                if (imb == null || !imb.IsExplicitImpl) {
                                        Report.SymbolRelatedToPreviousError (this);
@@ -2090,22 +2278,23 @@ namespace Mono.CSharp {
                                                Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
                                }
                        }
+
+                       if (types != null) {
+                               foreach (var t in types)
+                                       t.VerifyMembers ();
+                       }
                }
 
                public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
                {
                        if (a.IsValidSecurityAttribute ()) {
-                               if (declarative_security == null)
-                                       declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
-
-                               a.ExtractSecurityPermissionSet (declarative_security);
+                               a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
                                return;
                        }
 
                        if (a.Type == pa.StructLayout) {
                                PartialContainer.HasStructLayout = true;
-
-                               if (a.GetLayoutKindValue () == LayoutKind.Explicit)
+                               if (a.IsExplicitLayoutKind ())
                                        PartialContainer.HasExplicitLayout = true;
                        }
 
@@ -2165,12 +2354,16 @@ namespace Mono.CSharp {
 
                        if (declarative_security != null) {
                                foreach (var de in declarative_security) {
+#if STATIC
+                                       TypeBuilder.__AddDeclarativeSecurity (de);
+#else
                                        TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
+#endif
                                }
                        }
                }
 
-               public override ExtensionMethodGroupExpr LookupExtensionMethod (TypeSpec extensionType, string name, int arity, Location loc)
+               public override IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceEntry scope)
                {
                        DeclSpace top_level = Parent;
                        if (top_level != null) {
@@ -2178,11 +2371,13 @@ namespace Mono.CSharp {
                                        top_level = top_level.Parent;
 
                                var candidates = NamespaceEntry.NS.LookupExtensionMethod (extensionType, this, name, arity);
-                               if (candidates != null)
-                                       return new ExtensionMethodGroupExpr (candidates, NamespaceEntry, extensionType, loc);
+                               if (candidates != null) {
+                                       scope = NamespaceEntry;
+                                       return candidates;
+                               }
                        }
 
-                       return NamespaceEntry.LookupExtensionMethod (extensionType, name, arity, loc);
+                       return NamespaceEntry.LookupExtensionMethod (extensionType, name, arity, ref scope);
                }
 
                protected override TypeAttributes TypeAttr {
@@ -2334,7 +2529,11 @@ namespace Mono.CSharp {
                        base.Emit ();
 
                        if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
-                               PredefinedAttributes.Get.Extension.EmitAttribute (TypeBuilder);
+                               Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
+
+                       if (base_type != null && base_type.HasDynamicElement) {
+                               Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
+                       }
                }
 
                protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
@@ -2343,10 +2542,8 @@ namespace Mono.CSharp {
 
                        if (base_class == null) {
                                if (spec != TypeManager.object_type)
-                                       base_class = TypeManager.system_object_expr;
+                                       base_type = TypeManager.object_type;
                        } else {
-                               var base_type = base_class.Type;
-
                                if (base_type.IsGenericParameter){
                                        Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
                                                GetSignatureForError (), base_type.GetSignatureForError ());
@@ -2358,18 +2555,22 @@ namespace Mono.CSharp {
                                        Report.SymbolRelatedToPreviousError (base_class.Type);
                                        Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
                                                GetSignatureForError (), base_type.GetSignatureForError ());
-                               } else if (base_type.IsSealed){
+                               } else if (base_type.IsSealed) {
                                        Report.SymbolRelatedToPreviousError (base_class.Type);
                                        Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
                                                GetSignatureForError (), base_type.GetSignatureForError ());
+                               } else if (PartialContainer.IsStatic && base_class.Type != TypeManager.object_type) {
+                                       Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
+                                               GetSignatureForError (), base_class.GetSignatureForError ());
                                }
 
-                               if (base_type is PredefinedTypeSpec && !(spec is PredefinedTypeSpec) &&
+                               if (base_type is BuildinTypeSpec && !(spec is BuildinTypeSpec) &&
                                        (base_type == TypeManager.enum_type || base_type == TypeManager.value_type || base_type == TypeManager.multicast_delegate_type ||
                                        base_type == TypeManager.delegate_type || base_type == TypeManager.array_type)) {
                                        Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
                                                GetSignatureForError (), base_type.GetSignatureForError ());
-                                       base_class = TypeManager.system_object_expr;
+
+                                       base_type = TypeManager.object_type;
                                }
 
                                if (!IsAccessibleAs (base_type)) {
@@ -2379,18 +2580,10 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (PartialContainer.IsStatic) {
-                               if (base_class.Type != TypeManager.object_type) {
-                                       Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
-                                               GetSignatureForError (), base_class.GetSignatureForError ());
-                                       return ifaces;
-                               }
-
-                               if (ifaces != null) {
-                                       foreach (TypeExpr t in ifaces)
-                                               Report.SymbolRelatedToPreviousError (t.Type);
-                                       Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
-                               }
+                       if (PartialContainer.IsStatic && ifaces != null) {
+                               foreach (TypeExpr t in ifaces)
+                                       Report.SymbolRelatedToPreviousError (t.Type);
+                               Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
                        }
 
                        return ifaces;
@@ -2408,7 +2601,7 @@ namespace Mono.CSharp {
                        if (OptAttributes == null)
                                return null;
 
-                       Attribute[] attrs = OptAttributes.SearchMulti (PredefinedAttributes.Get.Conditional);
+                       Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
                        if (attrs == null)
                                return null;
 
@@ -2472,13 +2665,19 @@ namespace Mono.CSharp {
                        //
                        // When struct constains fixed fixed and struct layout has explicitly
                        // set CharSet, its value has to be propagated to compiler generated
-                       // fixed field types
+                       // fixed types
                        //
-                       if (a.Type == pa.StructLayout && Fields != null && a.HasField ("CharSet")) {
+                       if (a.Type == pa.StructLayout && Fields != null) {
+                               var value = a.GetNamedValue ("CharSet");
+                               if (value == null)
+                                       return;
+
                                for (int i = 0; i < Fields.Count; ++i) {
                                        FixedField ff = Fields [i] as FixedField;
-                                       if (ff != null)
-                                               ff.SetCharSet (TypeBuilder.Attributes);
+                                       if (ff == null)
+                                               continue;
+
+                                       ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
                                }
                        }
                }
@@ -2497,7 +2696,7 @@ namespace Mono.CSharp {
                                if (!ftype.IsStruct)
                                        continue;
 
-                               if (ftype is PredefinedTypeSpec)
+                               if (ftype is BuildinTypeSpec)
                                        continue;
 
                                foreach (var targ in ftype.TypeArguments) {
@@ -2567,14 +2766,9 @@ namespace Mono.CSharp {
                                while (mt.IsPointer)
                                        mt = TypeManager.GetElementType (mt);
 
-                               if (mt.MemberDefinition == this) {
-                                       for (var p = Parent; p != null; p = p.Parent) {
-                                               if (p.Kind == MemberKind.Class) {
-                                                       has_unmanaged_check_done = true;
-                                                       return false;
-                                               }
-                                       }
-                                       continue;
+                               if (mt.IsGenericOrParentIsGeneric || mt.IsGenericParameter) {
+                                       has_unmanaged_check_done = true;
+                                       return false;
                                }
 
                                if (TypeManager.IsUnmanagedType (mt))
@@ -2592,7 +2786,7 @@ namespace Mono.CSharp {
                protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
                {
                        TypeExpr[] ifaces = base.ResolveBaseTypes (out base_class);
-                       base_class = TypeManager.system_valuetype_expr;
+                       base_type = TypeManager.value_type;
                        return ifaces;
                }
 
@@ -2692,7 +2886,46 @@ namespace Mono.CSharp {
                }
        }
 
-       public abstract class InterfaceMemberBase : MemberBase {
+       public abstract class InterfaceMemberBase : MemberBase
+       {
+               //
+               // Common modifiers allowed in a class declaration
+               //
+               protected const Modifiers AllowedModifiersClass =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE |
+                       Modifiers.STATIC |
+                       Modifiers.VIRTUAL |
+                       Modifiers.SEALED |
+                       Modifiers.OVERRIDE |
+                       Modifiers.ABSTRACT |
+                       Modifiers.UNSAFE |
+                       Modifiers.EXTERN;
+
+               //
+               // Common modifiers allowed in a struct declaration
+               //
+               protected const Modifiers AllowedModifiersStruct =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE |
+                       Modifiers.STATIC |
+                       Modifiers.OVERRIDE |
+                       Modifiers.UNSAFE |
+                       Modifiers.EXTERN;
+
+               //
+               // Common modifiers allowed in a interface declaration
+               //
+               protected const Modifiers AllowedModifiersInterface =
+                       Modifiers.NEW |
+                       Modifiers.UNSAFE;
+
                //
                // Whether this is an interface member.
                //
@@ -2778,13 +3011,13 @@ namespace Mono.CSharp {
 
                                ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
                                if (oa != null) {
-                                       if (OptAttributes == null || !OptAttributes.Contains (PredefinedAttributes.Get.Obsolete)) {
+                                       if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
                                                Report.SymbolRelatedToPreviousError (base_member);
                                                Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
                                                        GetSignatureForError (), TypeManager.GetFullNameSignature (base_member));
                                        }
                                } else {
-                                       if (OptAttributes != null && OptAttributes.Contains (PredefinedAttributes.Get.Obsolete)) {
+                                       if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
                                                Report.SymbolRelatedToPreviousError (base_member);
                                                Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
                                                        GetSignatureForError (), TypeManager.GetFullNameSignature (base_member));
@@ -2808,17 +3041,19 @@ namespace Mono.CSharp {
                        } else {
                                if ((ModFlags & Modifiers.NEW) == 0) {
                                        ModFlags |= Modifiers.NEW;
-                                       Report.SymbolRelatedToPreviousError (base_member);
-                                       if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
-                                               Report.Warning (114, 2, Location, "`{0}' hides inherited member `{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword",
-                                                       GetSignatureForError (), base_member.GetSignatureForError ());
-                                       } else {
-                                               Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
-                                                       GetSignatureForError (), base_member.GetSignatureForError ());
+                                       if (!IsCompilerGenerated) {
+                                               Report.SymbolRelatedToPreviousError (base_member);
+                                               if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
+                                                       Report.Warning (114, 2, Location, "`{0}' hides inherited member `{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword",
+                                                               GetSignatureForError (), base_member.GetSignatureForError ());
+                                               } else {
+                                                       Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
+                                                               GetSignatureForError (), base_member.GetSignatureForError ());
+                                               }
                                        }
                                }
 
-                               if (!IsInterface && base_member.IsAbstract) {
+                               if (!IsInterface && base_member.IsAbstract && candidate == null) {
                                        Report.SymbolRelatedToPreviousError (base_member);
                                        Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
                                                GetSignatureForError (), base_member.GetSignatureForError ());
@@ -2841,7 +3076,7 @@ namespace Mono.CSharp {
                {
                        bool ok = true;
 
-                       if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE | Modifiers.OVERRIDE_UNCHECKED)) == 0) {
+                       if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
                                Report.SymbolRelatedToPreviousError (base_member);
                                Report.Error (506, Location,
                                        "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
@@ -2879,34 +3114,30 @@ namespace Mono.CSharp {
                        var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
 
                        if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
+                               //
+                               // It must be at least "protected"
+                               //
+                               if ((thisp & Modifiers.PROTECTED) == 0) {
+                                       return false;
+                               }
+
                                //
                                // when overriding protected internal, the method can be declared
                                // protected internal only within the same assembly or assembly
                                // which has InternalsVisibleTo
                                //
-                               if ((thisp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
-                                       return TypeManager.IsThisOrFriendAssembly (this_member.Assembly, base_member.Assembly);
-                               } 
-                               if ((thisp & Modifiers.PROTECTED) != Modifiers.PROTECTED) {
-                                       //
-                                       // if it's not "protected internal", it must be "protected"
-                                       //
-
-                                       return false;
-                               }
-                               if (this_member.Parent.PartialContainer.Module.Assembly == base_member.Assembly) {
-                                       //
-                                       // protected within the same assembly - an error
-                                       //
-                                       return false;
+                               if ((thisp & Modifiers.INTERNAL) != 0) {
+                                       return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
                                }
-                               if ((thisp & ~(Modifiers.PROTECTED | Modifiers.INTERNAL)) !=
-                                          (base_classp & ~(Modifiers.PROTECTED | Modifiers.INTERNAL))) {
-                                       //
-                                       // protected ok, but other attributes differ - report an error
-                                       //
+
+                               //
+                               // protected overriding protected internal inside same assembly
+                               // requires internal modifier as well
+                               //
+                               if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
                                        return false;
                                }
+
                                return true;
                        }
 
@@ -3027,11 +3258,18 @@ namespace Mono.CSharp {
 
                protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
                {
+                       var base_modifiers = base_member.Modifiers;
+
+                       // Remove internal modifier from types which are not internally accessible
+                       if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
+                               !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
+                               base_modifiers = Modifiers.PROTECTED;
+
                        Report.SymbolRelatedToPreviousError (base_member);
                        Report.Error (507, member.Location,
                                "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
                                member.GetSignatureForError (),
-                               ModifiersExtensions.AccessibilityName (base_member.Modifiers),
+                               ModifiersExtensions.AccessibilityName (base_modifiers),
                                base_member.GetSignatureForError ());
                }
 
@@ -3123,6 +3361,22 @@ namespace Mono.CSharp {
                                GenericMethod.ModFlags = ModFlags;
                }
 
+               #region Properties
+
+               public TypeSpec MemberType {
+                       get {
+                               return member_type;
+                       }
+               }
+
+               public FullNamedExpression TypeExpression {
+                       get {
+                               return type_expr;
+                       }
+               }
+
+               #endregion
+
                //
                // Main member define entry
                //
@@ -3209,10 +3463,6 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public TypeSpec MemberType {
-                       get { return member_type; }
-               }
-
                protected virtual bool ResolveMemberType ()
                {
                        if (member_type != null)