2007-12-06 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / mcs / class.cs
index 9a09a6cb4b6958590783bbadfaadd086efc63871..9a6689ea67a82d5ce96082159ae2106e61968d9f 100644 (file)
@@ -30,7 +30,6 @@
 //     basenames in the defined_names array.
 //
 //
-#define CACHE
 using System;
 using System.Collections;
 using System.Collections.Specialized;
@@ -42,7 +41,7 @@ using System.Security;
 using System.Security.Permissions;
 using System.Text;
 
-#if BOOTSTRAP_WITH_OLDLIB
+#if BOOTSTRAP_WITH_OLDLIB || NET_2_1
 using XmlElement = System.Object;
 #else
 using System.Xml;
@@ -56,7 +55,8 @@ namespace Mono.CSharp {
                Root,
                Struct,
                Class,
-               Interface
+               Interface,
+               Enum
        }
 
        /// <summary>
@@ -75,7 +75,7 @@ namespace Mono.CSharp {
                                        try {
                                                mc.Define ();
                                        } catch (Exception e) {
-                                               throw new InternalErrorException (mc.Location, mc.GetSignatureForError (), e);
+                                               throw new InternalErrorException (mc, e);
                                        }
                                }
                        }
@@ -87,130 +87,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               public class MethodArrayList : MemberCoreArrayList
-               {
-                       [Flags]
-                       enum CachedMethods {
-                               Equals                  = 1,
-                               GetHashCode             = 1 << 1
-                       }
-                       CachedMethods cached_method;
-                       TypeContainer container;
-
-                       public MethodArrayList (TypeContainer container)
-                       {
-                               this.container = container;
-                       }
-                       /// <summary>
-                       /// Method container contains Equals method
-                       /// </summary>
-                       public bool HasEquals {
-                               set {
-                                       cached_method |= CachedMethods.Equals;
-                               }
-                               get {
-                                       return (cached_method & CachedMethods.Equals) != 0;
-                               }
-                       }
-                       /// <summary>
-                       /// Method container contains GetHashCode method
-                       /// </summary>
-                       public bool HasGetHashCode {
-                               set {
-                                       cached_method |= CachedMethods.GetHashCode;
-                               }
-                               get {
-                                       return (cached_method & CachedMethods.GetHashCode) != 0;
-                               }
-                       }
-                       public override void DefineContainerMembers ()
-                       {
-                               base.DefineContainerMembers ();
-                               if (HasEquals && !HasGetHashCode) {
-                                       Report.Warning (659, 3, container.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", container.GetSignatureForError ());
-                               }
-                       }
-               }
-
-               public sealed class IndexerArrayList : MemberCoreArrayList
-               {
-                       /// <summary>
-                       /// The indexer name for this container
-                       /// </summary>
-                       public string IndexerName = DefaultIndexerName;
-
-                       bool seen_normal_indexers = false;
-
-                       TypeContainer container;
-
-                       public IndexerArrayList (TypeContainer container)
-                       {
-                               this.container = container;
-                       }
-
-                       /// <summary>
-                       /// Defines the indexers, and also verifies that the IndexerNameAttribute in the
-                       /// class is consistent.  Either it is `Item' or it is the name defined by all the
-                       /// indexers with the `IndexerName' attribute.
-                       ///
-                       /// Turns out that the IndexerNameAttribute is applied to each indexer,
-                       /// but it is never emitted, instead a DefaultMember attribute is attached
-                       /// to the class.
-                       /// </summary>
-                       public override void DefineContainerMembers()
-                       {
-                               base.DefineContainerMembers ();
-
-                               string class_indexer_name = null;
-
-                               //
-                               // If there's both an explicit and an implicit interface implementation, the
-                               // explicit one actually implements the interface while the other one is just
-                               // a normal indexer.  See bug #37714.
-                               //
-
-                               // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
-                               foreach (Indexer i in this) {
-                                       if (i.InterfaceType != null) {
-                                               if (seen_normal_indexers)
-                                                       throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
-                                               continue;
-                                       }
-
-                                       seen_normal_indexers = true;
-
-                                       if (class_indexer_name == null) {
-                                               class_indexer_name = i.ShortName;
-                                               continue;
-                                       }
-
-                                       if (i.ShortName != class_indexer_name)
-                                               Report.Error (668, i.Location, "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
-                               }
-
-                               if (class_indexer_name != null)
-                                       IndexerName = class_indexer_name;
-                       }
-
-                       public override void Emit ()
-                       {
-                               base.Emit ();
-
-                               if (!seen_normal_indexers)
-                                       return;
-
-                               CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { IndexerName });
-                               container.TypeBuilder.SetCustomAttribute (cb);
-                       }
-               }
-
                public class OperatorArrayList: MemberCoreArrayList
                {
                        TypeContainer container;
@@ -370,11 +246,11 @@ namespace Mono.CSharp {
                                                oe.op.GetSignatureForError (), s);
                                }
 
-                               if (has_equality_or_inequality && (RootContext.WarningLevel > 2)) {
-                                       if (container.Methods == null || !container.Methods.HasEquals)
+                               if (has_equality_or_inequality && Report.WarningLevel > 2) {
+                                       if (container.Methods == null || !container.HasEquals)
                                                Report.Warning (660, 2, container.Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)", container.GetSignatureForError ());
  
-                                       if (container.Methods == null || !container.Methods.HasGetHashCode)
+                                       if (container.Methods == null || !container.HasGetHashCode)
                                                Report.Warning (661, 2, container.Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()", container.GetSignatureForError ());
                                }
                        }
@@ -386,6 +262,14 @@ namespace Mono.CSharp {
                        }
                }
 
+               [Flags]
+               enum CachedMethods
+               {
+                       Equals                          = 1,
+                       GetHashCode                     = 1 << 1,
+                       HasStaticFieldInitializer       = 1 << 2
+               }
+
 
                // Whether this is a struct, class or interface
                public readonly Kind Kind;
@@ -393,12 +277,12 @@ namespace Mono.CSharp {
                // Holds a list of classes and structures
                protected ArrayList types;
 
+               MemberCoreArrayList ordered_explicit_member_list;
+               MemberCoreArrayList ordered_member_list;
+
                // Holds the list of properties
                MemberCoreArrayList properties;
 
-               // Holds the list of enumerations
-               MemberCoreArrayList enums;
-
                // Holds the list of delegates
                MemberCoreArrayList delegates;
                
@@ -415,19 +299,16 @@ namespace Mono.CSharp {
                protected ArrayList initialized_static_fields;
 
                // Holds the list of constants
-               MemberCoreArrayList constants;
-
-               // Holds the list of
-               MemberCoreArrayList interfaces;
+               protected MemberCoreArrayList constants;
 
                // Holds the methods.
-               MethodArrayList methods;
+               MemberCoreArrayList methods;
 
                // Holds the events
                protected MemberCoreArrayList events;
 
                // Holds the indexers
-               IndexerArrayList indexers;
+               ArrayList indexers;
 
                // Holds the operators
                MemberCoreArrayList operators;
@@ -469,10 +350,15 @@ namespace Mono.CSharp {
 
                // The base member cache and our member cache
                MemberCache base_cache;
-               MemberCache member_cache;
+               protected MemberCache member_cache;
 
                public const string DefaultIndexerName = "Item";
 
+               private bool seen_normal_indexers = false;
+               private string indexer_name = DefaultIndexerName;
+
+               private CachedMethods cached_method;
+
 #if GMCS_SOURCE
                GenericTypeParameterBuilder[] gen_params;
 #endif
@@ -517,74 +403,55 @@ namespace Mono.CSharp {
                        constants.Add (constant);
                }
 
-               public void AddEnum (Mono.CSharp.Enum e)
-               {
-                       if (!AddMemberType (e))
-                               return;
-
-                       if (enums == null)
-                               enums = new MemberCoreArrayList ();
-
-                       enums.Add (e);
-               }
-
-               public TypeContainer AddTypeContainer (TypeContainer tc, bool is_interface)
+               public TypeContainer AddTypeContainer (TypeContainer tc)
                {
                        if (!AddMemberType (tc))
                                return tc;
 
-                       if (is_interface) {
-                               if (interfaces == null)
-                                       interfaces = new MemberCoreArrayList ();
-                               interfaces.Add (tc);
-                       } else {
-                               if (types == null)
-                                       types = new ArrayList (2);
-                               types.Add (tc);
-                       }
+                       if (types == null)
+                               types = new MemberCoreArrayList ();
+                       types.Add (tc);
+
                        return tc;
                }
 
-               public virtual TypeContainer AddPartial (TypeContainer nextPart, bool is_interface)
+               public virtual TypeContainer AddPartial (TypeContainer next_part)
                {
-                       return AddPartial (nextPart, nextPart.Basename, is_interface);
+                       return AddPartial (next_part, next_part.Basename);
                }
 
-               protected TypeContainer AddPartial (TypeContainer nextPart, string name, bool is_interface)
+               protected TypeContainer AddPartial (TypeContainer next_part, string name)
                {
-                       nextPart.ModFlags |= Modifiers.PARTIAL;
+                       next_part.ModFlags |= Modifiers.PARTIAL;
                        TypeContainer tc = defined_names [name] as TypeContainer;
 
                        if (tc == null)
-                               return AddTypeContainer (nextPart, is_interface);
+                               return AddTypeContainer (next_part);
 
                        if ((tc.ModFlags & Modifiers.PARTIAL) == 0) {
                                Report.SymbolRelatedToPreviousError (tc);
-                               Error_MissingPartialModifier (nextPart);
-                               return tc;
+                               Error_MissingPartialModifier (next_part);
                        }
 
-                       if (tc.Kind != nextPart.Kind) {
+                       if (tc.Kind != next_part.Kind) {
                                Report.SymbolRelatedToPreviousError (tc);
-                               Report.Error (261, nextPart.Location,
+                               Report.Error (261, next_part.Location,
                                        "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
-                                       nextPart.GetSignatureForError ());
-                               return tc;
+                                       next_part.GetSignatureForError ());
                        }
 
-                       if ((tc.ModFlags & Modifiers.Accessibility) != (nextPart.ModFlags & Modifiers.Accessibility) &&
+                       if ((tc.ModFlags & Modifiers.Accessibility) != (next_part.ModFlags & Modifiers.Accessibility) &&
                                ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
-                                (nextPart.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
+                                (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
                                Report.SymbolRelatedToPreviousError (tc);
-                               Report.Error (262, nextPart.Location,
+                               Report.Error (262, next_part.Location,
                                        "Partial declarations of `{0}' have conflicting accessibility modifiers",
-                                       nextPart.GetSignatureForError ());
-                               return tc;
+                                       next_part.GetSignatureForError ());
                        }
 
                        if (tc.MemberName.IsGeneric) {
                                TypeParameter[] tc_names = tc.TypeParameters;
-                               TypeParameterName[] part_names = nextPart.MemberName.TypeArguments.GetDeclarations ();
+                               TypeParameterName[] part_names = next_part.MemberName.TypeArguments.GetDeclarations ();
 
                                for (int i = 0; i < tc_names.Length; ++i) {
                                        if (tc_names[i].Name == part_names[i].Name)
@@ -593,23 +460,30 @@ namespace Mono.CSharp {
                                        Report.SymbolRelatedToPreviousError (part_names[i].Location, "");
                                        Report.Error (264, tc.Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
                                                tc.GetSignatureForError ());
-                                       return tc;
                                }
                        }
 
                        if (tc.partial_parts == null)
                                tc.partial_parts = new ArrayList (1);
 
-                       tc.ModFlags |= nextPart.ModFlags;
-                       if (nextPart.attributes != null) {
+                       if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
+                               tc.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.Accessibility);
+                       } else if ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
+                               tc.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.Accessibility);
+                               tc.ModFlags |= next_part.ModFlags;
+                       } else {
+                               tc.ModFlags |= next_part.ModFlags;
+                       }
+
+                       if (next_part.attributes != null) {
                                if (tc.attributes == null)
-                                       tc.attributes = nextPart.attributes;
+                                       tc.attributes = next_part.attributes;
                                else
-                                       tc.attributes.AddAttributes (nextPart.attributes.Attrs);
+                                       tc.attributes.AddAttributes (next_part.attributes.Attrs);
                        }
 
-                       nextPart.PartialContainer = tc;
-                       tc.partial_parts.Add (nextPart);
+                       next_part.PartialContainer = tc;
+                       tc.partial_parts.Add (next_part);
                        return tc;
                }
 
@@ -624,18 +498,37 @@ namespace Mono.CSharp {
                        delegates.Add (d);
                }
 
+               private void AddMemberToList (MemberCore mc, ArrayList alist, bool isexplicit)
+               {
+                       if (ordered_explicit_member_list == null)  {
+                               ordered_explicit_member_list = new MemberCoreArrayList ();
+                               ordered_member_list = new MemberCoreArrayList ();
+                       }
+
+                       if(isexplicit) {
+                               ordered_explicit_member_list.Add (mc);
+                               alist.Insert (0, mc);
+                       } 
+                       else {
+                               ordered_member_list.Add (mc);
+                               alist.Add (mc);
+                       }
+
+               }
+               
                public void AddMethod (Method method)
                {
-                       if (!AddMember (method))
+                       MemberName mn = method.MemberName;
+                       if (!AddToContainer (method, mn.IsGeneric ? mn.Basename : mn.MethodName))
                                return;
-
-                       if (methods == null)
-                               methods = new MethodArrayList (this);
                        
-                       if (method.MemberName.Left != null)
-                               methods.Insert (0, method);
+                       if (methods == null)
+                               methods = new MemberCoreArrayList ();
+
+                       if (method.MemberName.Left != null) 
+                               AddMemberToList (method, methods, true);
                        else 
-                               methods.Add (method);
+                               AddMemberToList (method, methods, false);
                }
 
                //
@@ -649,9 +542,9 @@ namespace Mono.CSharp {
                                return;
 
                        if (methods == null)
-                               methods = new MethodArrayList (this);
+                               methods = new MemberCoreArrayList ();
 
-                       methods.Add (method);
+                       AddMemberToList (method, methods, false);
                }
 
                public void AddConstructor (Constructor c)
@@ -661,24 +554,23 @@ namespace Mono.CSharp {
                        }
 
                        bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
+                       if (!AddToContainer (c, is_static ?
+                               ConstructorBuilder.ConstructorName : ConstructorBuilder.TypeConstructorName))
+                               return;
                        
                        if (is_static){
                                if (default_static_constructor != null) {
-                                       Report.SymbolRelatedToPreviousError (default_static_constructor);
-                                       Report.Error (111, c.Location, Error111, c.GetSignatureForError ());
-                                       return;
+                                   Report.SymbolRelatedToPreviousError (default_static_constructor);
+                                       Report.Error (111, c.Location,
+                                               "A member `{0}' is already defined. Rename this member or use different parameter types",
+                                               c.GetSignatureForError ());
+                                   return;
                                }
 
                                default_static_constructor = c;
                        } else {
-                               if (c.Parameters.Empty){
-                                       if (default_constructor != null) {
-                                               Report.SymbolRelatedToPreviousError (default_constructor);
-                                               Report.Error (111, c.Location, Error111, c.GetSignatureForError ());
-                                               return;
-                                       }
+                               if (c.Parameters.Empty)
                                        default_constructor = c;
-                               }
                                
                                if (instance_constructors == null)
                                        instance_constructors = new MemberCoreArrayList ();
@@ -687,16 +579,10 @@ namespace Mono.CSharp {
                        }
                }
 
-               internal static string Error111 {
-                       get {
-                               return "`{0}' is already defined. Rename this member or use different parameter types";
-                       }
-               }
-
-               public void AddField (FieldBase field)
+               public bool AddField (FieldBase field)
                {
                        if (!AddMember (field))
-                               return;
+                               return false;
 
                        if (fields == null)
                                fields = new MemberCoreArrayList ();
@@ -704,21 +590,20 @@ namespace Mono.CSharp {
                        fields.Add (field);
 
                        if ((field.ModFlags & Modifiers.STATIC) != 0)
-                               return;
+                               return true;
 
                        if (first_nonstatic_field == null) {
                                first_nonstatic_field = field;
-                               return;
+                               return true;
                        }
 
-                       if (Kind == Kind.Struct &&
-                           first_nonstatic_field.Parent != field.Parent &&
-                           RootContext.WarningLevel >= 3) {
+                       if (Kind == Kind.Struct && first_nonstatic_field.Parent != field.Parent) {
                                Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent);
                                Report.Warning (282, 3, field.Location,
                                        "struct instance field `{0}' found in different declaration from instance field `{1}'",
                                        field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ());
                        }
+                       return true;
                }
 
                public void AddProperty (Property prop)
@@ -731,9 +616,9 @@ namespace Mono.CSharp {
                                properties = new MemberCoreArrayList ();
 
                        if (prop.MemberName.Left != null)
-                               properties.Insert (0, prop);
-                       else
-                               properties.Add (prop);
+                               AddMemberToList (prop, properties, true);
+                       else 
+                               AddMemberToList (prop, properties, false);
                }
 
                public void AddEvent (Event e)
@@ -761,12 +646,12 @@ namespace Mono.CSharp {
                public void AddIndexer (Indexer i)
                {
                        if (indexers == null)
-                               indexers = new IndexerArrayList (this);
+                               indexers = new ArrayList ();
 
                        if (i.IsExplicitImpl)
-                               indexers.Insert (0, i);
-                       else
-                               indexers.Add (i);
+                               AddMemberToList (i, indexers, true);
+                       else 
+                               AddMemberToList (i, indexers, false);
                }
 
                public void AddOperator (Operator op)
@@ -814,7 +699,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public MethodArrayList Methods {
+               public MemberCoreArrayList Methods {
                        get {
                                return methods;
                        }
@@ -826,12 +711,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               public ArrayList Interfaces {
-                       get {
-                               return interfaces;
-                       }
-               }
-
                public ArrayList CompilerGenerated {
                        get {
                                return compiler_generated;
@@ -878,12 +757,6 @@ namespace Mono.CSharp {
                        }
                }
                
-               public ArrayList Enums {
-                       get {
-                               return enums;
-                       }
-               }
-
                public ArrayList Indexers {
                        get {
                                return indexers;
@@ -910,7 +783,7 @@ namespace Mono.CSharp {
 
                public string IndexerName {
                        get {
-                               return indexers == null ? DefaultIndexerName : indexers.IndexerName;
+                               return indexers == null ? DefaultIndexerName : indexer_name;
                        }
                }
 
@@ -926,8 +799,10 @@ namespace Mono.CSharp {
                public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
                {
                        if ((field.ModFlags & Modifiers.STATIC) != 0){
-                               if (initialized_static_fields == null)
+                               if (initialized_static_fields == null) {
+                                       PartialContainer.HasStaticFieldInitializer = true;
                                        initialized_static_fields = new ArrayList (4);
+                               }
 
                                initialized_static_fields.Add (expression);
                        } else {
@@ -938,11 +813,82 @@ namespace Mono.CSharp {
                        }
                }
 
+               public void ResolveFieldInitializers (EmitContext ec)
+               {
+                       // Field initializers are tricky for partial classes. They have to
+                       // share same costructor (block) but they have they own resolve scope.
+                       DeclSpace orig = ec.DeclContainer;
+
+                       if (partial_parts != null) {
+                               foreach (TypeContainer part in partial_parts) {
+                                       ec.DeclContainer = part;
+                                       part.DoResolveFieldInitializers (ec);
+                               }
+                       }
+                       ec.DeclContainer = PartialContainer;
+                       DoResolveFieldInitializers (ec);
+                       ec.DeclContainer = orig; 
+               }
+
+               void DoResolveFieldInitializers (EmitContext ec)
+               {
+                       if (ec.IsStatic) {
+                               if (initialized_static_fields == null)
+                                       return;
+
+                               bool has_complex_initializer = false;
+                               using (ec.Set (EmitContext.Flags.InFieldInitializer)) {
+                                       foreach (FieldInitializer fi in initialized_static_fields) {
+                                               fi.ResolveStatement (ec);
+                                               if (!fi.IsComplexInitializer)
+                                                       continue;
+
+                                               has_complex_initializer = true;
+                                       }
+
+                                       // Need special check to not optimize code like this
+                                       // static int a = b = 5;
+                                       // static int b = 0;
+                                       if (!has_complex_initializer && RootContext.Optimize) {
+                                               for (int i = 0; i < initialized_static_fields.Count; ++i) {
+                                                       FieldInitializer fi = (FieldInitializer) initialized_static_fields [i];
+                                                       if (fi.IsDefaultInitializer) {
+                                                               initialized_static_fields.RemoveAt (i);
+                                                               --i;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               return;
+                       }
+
+                       if (initialized_fields == null)
+                               return;
+
+                       using (ec.Set (EmitContext.Flags.InFieldInitializer)) {
+                               for (int i = 0; i < initialized_fields.Count; ++i) {
+                                       FieldInitializer fi = (FieldInitializer) initialized_fields [i];
+                                       fi.ResolveStatement (ec);
+                                       if (fi.IsDefaultInitializer && RootContext.Optimize) {
+                                               // Field is re-initialized to its default value => removed
+                                               initialized_fields.RemoveAt (i);
+                                               --i;
+                                       }
+                               }
+                       }
+               }
+
                //
                // Emits the instance field initializers
                //
                public bool EmitFieldInitializers (EmitContext ec)
                {
+                       if (partial_parts != null) {
+                               foreach (TypeContainer part in partial_parts)
+                                       part.EmitFieldInitializers (ec);
+                       }
+
                        ArrayList fields;
                        
                        if (ec.IsStatic){
@@ -984,7 +930,7 @@ namespace Mono.CSharp {
                        return base.GetClsCompliantAttributeValue ();
                }
 
-               public void AddBasesForPart (DeclSpace part, ArrayList bases)
+               public virtual void AddBasesForPart (DeclSpace part, ArrayList bases)
                {
                        // FIXME: get rid of partial_parts and store lists of bases of each part here
                        // assumed, not verified: 'part' is in 'partial_parts' 
@@ -1167,25 +1113,28 @@ namespace Mono.CSharp {
                        Report.Error (527, loc, "Type `{0}' in interface list is not an interface", type);
                }
 
-               bool DefineTypeBuilder ()
+               bool CreateTypeBuilder ()
                {
                        try {
+                               Type default_parent = null;
+                               if (Kind == Kind.Struct)
+                                       default_parent = TypeManager.value_type;
+                               else if (Kind == Kind.Enum)
+                                       default_parent = TypeManager.enum_type;
+
                                if (IsTopLevel){
                                        if (TypeManager.NamespaceClash (Name, Location)) {
                                                return false;
                                        }
 
                                        ModuleBuilder builder = CodeGen.Module.Builder;
-                                       Type default_parent = null;
-                                       if (Kind == Kind.Struct)
-                                               default_parent = TypeManager.value_type;
                                        TypeBuilder = builder.DefineType (
                                                Name, TypeAttr, default_parent, null);
                                } else {
                                        TypeBuilder builder = Parent.TypeBuilder;
 
                                        TypeBuilder = builder.DefineNestedType (
-                                               Basename, TypeAttr, null, null);
+                                               Basename, TypeAttr, default_parent, null);
                                }
                        } catch (ArgumentException) {
                                Report.RuntimeMissingSupport (Location, "static classes");
@@ -1208,6 +1157,11 @@ namespace Mono.CSharp {
                        }
 #endif
 
+                       return true;
+               }
+
+               bool DefineBaseTypes ()
+               {
                        iface_exprs = GetClassBases (out base_type);
                        if (partial_parts != null) {
                                iface_exprs = GetNormalPartialBases (ref base_type);
@@ -1236,7 +1190,7 @@ namespace Mono.CSharp {
                        if (!CheckRecursiveDefinition (this))
                                return false;
 
-                       if (base_type != null) {
+                       if (base_type != null && base_type.Type != null) {
                                TypeBuilder.SetParent (base_type.Type);
 
                                ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (base_type.Type);
@@ -1272,15 +1226,15 @@ namespace Mono.CSharp {
                //
                // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
                //
-               public override TypeBuilder DefineType ()
+               public TypeBuilder CreateType ()
                {
                        if (TypeBuilder != null)
                                return TypeBuilder;
 
                        if (error)
                                return null;
-                       
-                       if (!DefineTypeBuilder ()) {
+
+                       if (!CreateTypeBuilder ()) {
                                error = true;
                                return null;
                        }
@@ -1290,6 +1244,39 @@ namespace Mono.CSharp {
                                        part.TypeBuilder = TypeBuilder;
                        }
 
+                       if (Types != null) {
+                               foreach (TypeContainer tc in Types) {
+                                       if (tc.CreateType () == null) {
+                                               error = true;
+                                               return null;
+                                       }
+                               }
+                       }
+
+                       return TypeBuilder;
+               }
+
+               bool type_defined;
+
+               public override TypeBuilder DefineType ()
+               {
+                       if (error)
+                               return null;
+                       if (type_defined)
+                               return TypeBuilder;
+
+                       type_defined = true;
+
+                       if (CreateType () == null) {
+                               error = true;
+                               return null;
+                       }
+
+                       if (!DefineBaseTypes ()) {
+                               error = true;
+                               return null;
+                       }
+
                        if (!(this is CompilerGeneratedClass)) {
                                if (!ResolveMembers ()) {
                                        error = true;
@@ -1362,6 +1349,22 @@ namespace Mono.CSharp {
                                }
                        }
 
+                       if (events != null) {
+                               foreach (Event e in events) {
+                                       if (!e.Add.ResolveMembers ())
+                                               return false;
+                                       if (!e.Remove.ResolveMembers ())
+                                               return false;
+                               }
+                       }
+
+                       if (compiler_generated != null) {
+                               foreach (CompilerGeneratedClass c in compiler_generated) {
+                                       if (c.DefineType () == null)
+                                               return false;
+                               }
+                       }
+
                        return true;
                }
 
@@ -1484,12 +1487,6 @@ namespace Mono.CSharp {
 
                protected virtual bool DefineNestedTypes ()
                {
-                       if (Interfaces != null) {
-                               foreach (TypeContainer iface in Interfaces)
-                                       if (iface.DefineType () == null)
-                                               return false;
-                       }
-                       
                        if (Types != null) {
                                foreach (TypeContainer tc in Types)
                                        if (tc.DefineType () == null)
@@ -1502,19 +1499,6 @@ namespace Mono.CSharp {
                                                return false;
                        }
 
-                       if (Enums != null) {
-                               foreach (Enum en in Enums)
-                                       if (en.DefineType () == null)
-                                               return false;
-                       }
-
-                       if (compiler_generated != null) {
-                               foreach (CompilerGeneratedClass c in compiler_generated) {
-                                       if (c.DefineType () == null)
-                                               return false;
-                               }
-                       }
-
                        return true;
                }
 
@@ -1539,7 +1523,7 @@ namespace Mono.CSharp {
 
                        InTransit = tc;
 
-                       if (base_type != null) {
+                       if (base_type != null && base_type.Type != null) {
                                Type t = TypeManager.DropGenericTypeArguments (base_type.Type);
                                TypeContainer ptc = TypeManager.LookupTypeContainer (t);
                                if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
@@ -1598,12 +1582,34 @@ namespace Mono.CSharp {
                                ConstructedType ct = base_type as ConstructedType;
                                if ((ct != null) && !ct.CheckConstraints (this))
                                        return false;
+                               
+                               member_cache = new MemberCache (base_type.Type, this);
+                       } else if (Kind == Kind.Interface) {
+                               member_cache = new MemberCache (null, this);
+                               Type [] ifaces = TypeManager.GetInterfaces (TypeBuilder);
+                               for (int i = 0; i < ifaces.Length; ++i)
+                                       member_cache.AddInterface (TypeManager.LookupMemberCache (ifaces [i]));
+                       } else {
+                               member_cache = new MemberCache (null, this);
+                       }
+
+                       if (types != null)
+                               foreach (TypeContainer tc in types)
+                                       member_cache.AddNestedType (tc);
+
+                       if (delegates != null)
+                               foreach (Delegate d in delegates)
+                                       member_cache.AddNestedType (d);
+
+                       if (partial_parts != null) {
+                               foreach (TypeContainer part in partial_parts)
+                                       part.member_cache = member_cache;
                        }
 
                        if (!IsTopLevel) {
                                MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Basename, false);
                                if (conflict_symbol == null) {
-                                       if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0))
+                                       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) {
@@ -1626,26 +1632,29 @@ namespace Mono.CSharp {
                        //
                        DefineContainerMembers (instance_constructors);
                
-                       DefineContainerMembers (properties);
                        DefineContainerMembers (events);
-                       DefineContainerMembers (indexers);
-                       DefineContainerMembers (methods);
+                       DefineContainerMembers (ordered_explicit_member_list);
+                       DefineContainerMembers (ordered_member_list);
+
                        DefineContainerMembers (operators);
-                       DefineContainerMembers (enums);
                        DefineContainerMembers (delegates);
 
+                       ComputeIndexerName();
+                       CheckEqualsAndGetHashCode();
+
                        if (CurrentType != null) {
                                GenericType = CurrentType;
                        }
 
-
-#if CACHE
-                       member_cache = new MemberCache (this);
-                       if (partial_parts != null) {
-                               foreach (TypeContainer part in partial_parts)
-                                       part.member_cache = member_cache;
-                       }
-#endif
+#if GMCS_SOURCE
+                       //
+                       // FIXME: This hack is needed because member cache does not work
+                       // with generic types, we rely on runtime to inflate dynamic types.
+                       // TODO: This hack requires member cache refactoring to be removed
+                       //
+                       if (TypeBuilder.IsGenericType)
+                               member_cache = new MemberCache (this);
+#endif                 
 
                        return true;
                }
@@ -1655,6 +1664,61 @@ namespace Mono.CSharp {
                        if (mcal != null)
                                mcal.DefineContainerMembers ();
                }
+               
+               protected virtual void ComputeIndexerName ()
+               {
+                       if (indexers == null)
+                               return;
+
+                       string class_indexer_name = null;
+
+                       //
+                       // If there's both an explicit and an implicit interface implementation, the
+                       // explicit one actually implements the interface while the other one is just
+                       // a normal indexer.  See bug #37714.
+                       //
+
+                       // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
+                       foreach (Indexer i in indexers) {
+                               if (i.InterfaceType != null) {
+                                       if (seen_normal_indexers)
+                                               throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
+                                       continue;
+                               }
+
+                               seen_normal_indexers = true;
+
+                               if (class_indexer_name == null) {
+                                       class_indexer_name = i.ShortName;
+                                       continue;
+                               }
+
+                               if (i.ShortName != class_indexer_name)
+                                       Report.Error (668, i.Location, "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
+                       }
+
+                       if (class_indexer_name != null)
+                               indexer_name = class_indexer_name;
+               }
+
+               protected virtual void EmitIndexerName ()
+               {
+                       if (!seen_normal_indexers)
+                               return;
+
+                       CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { IndexerName });
+                       TypeBuilder.SetCustomAttribute (cb);
+               }
+
+               protected virtual void CheckEqualsAndGetHashCode ()
+               {
+                       if (methods == null)
+                               return;
+
+                       if (HasEquals && !HasGetHashCode) {
+                               Report.Warning (659, 3, this.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", this.GetSignatureForError ());
+                       }
+               }
 
                public override bool Define ()
                {
@@ -1773,7 +1837,7 @@ namespace Mono.CSharp {
                        if (PartialContainer != this)
                                throw new InternalErrorException ("should not happen");
 
-                       ArrayList [] lists = { types, enums, delegates, interfaces };
+                       ArrayList [] lists = { types, delegates };
 
                        for (int j = 0; j < lists.Length; ++j) {
                                ArrayList list = lists [j];
@@ -1796,7 +1860,7 @@ namespace Mono.CSharp {
                                                      BindingFlags bf, MemberFilter filter, object criteria,
                                                      ref ArrayList members)
                {
-                       ArrayList [] lists = { types, enums, delegates, interfaces };
+                       ArrayList [] lists = { types, delegates };
 
                        for (int j = 0; j < lists.Length; ++j) {
                                ArrayList list = lists [j];
@@ -1845,6 +1909,10 @@ namespace Mono.CSharp {
                //
                // Since the whole process is a no-op, it is fine to check for null here.
                //
+               // TODO: This approach will be one day completely removed, it's already
+               // used at few places only
+               //
+               //
                public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
                                                        MemberFilter filter, object criteria)
                {
@@ -2208,7 +2276,7 @@ namespace Mono.CSharp {
                                if ((mc.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
                                        continue;
 
-                               if (!mc.IsUsed) {
+                               if (!mc.IsUsed && (mc.caching_flags & Flags.Excluded) == 0) {
                                        Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
                                }
                        }
@@ -2219,7 +2287,7 @@ namespace Mono.CSharp {
                        //
                        // Check for internal or private fields that were never assigned
                        //
-                       if (RootContext.WarningLevel >= 3) {
+                       if (Report.WarningLevel >= 3) {
                                CheckMemberUsage (properties, "property");
                                CheckMemberUsage (methods, "method");
                                CheckMemberUsage (constants, "constant");
@@ -2247,7 +2315,7 @@ namespace Mono.CSharp {
                                                //
                                                // Only report 649 on level 4
                                                //
-                                               if (RootContext.WarningLevel < 4)
+                                               if (Report.WarningLevel < 4)
                                                        continue;
                                                
                                                if ((f.caching_flags & Flags.IsAssigned) != 0)
@@ -2271,7 +2339,12 @@ namespace Mono.CSharp {
                                bool has_compliant_args = false;
 
                                foreach (Constructor c in instance_constructors) {
-                                       c.Emit ();
+                                       try {
+                                               c.Emit ();
+                                       }
+                                       catch (Exception e) {
+                                               throw new InternalErrorException (c, e);
+                                       }
 
                                        if (has_compliant_args)
                                                continue;
@@ -2281,8 +2354,14 @@ namespace Mono.CSharp {
                                if (!has_compliant_args)
                                        Report.Error (3015, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
                        } else {
-                               foreach (Constructor c in instance_constructors)
-                                       c.Emit ();
+                               foreach (Constructor c in instance_constructors) {
+                                       try {
+                                               c.Emit ();
+                                       }
+                                       catch (Exception e) {
+                                               throw new InternalErrorException (c, e);
+                                       }
+                               }
                        }
                }
 
@@ -2299,7 +2378,7 @@ namespace Mono.CSharp {
                        if (IsGeneric) {
                                int offset = CountTypeParameters - CurrentTypeParameters.Length;
                                for (int i = offset; i < gen_params.Length; i++)
-                                       CurrentTypeParameters [i - offset].EmitAttributes ();
+                                       CurrentTypeParameters [i - offset].Emit ();
                        }
 #endif
 
@@ -2337,8 +2416,8 @@ namespace Mono.CSharp {
                                default_static_constructor.Emit ();
                        
                        if (methods != null){
-                               foreach (Method m in methods)
-                                       m.Emit ();
+                               for (int i = 0; i < methods.Count; ++i)
+                                       ((Method)methods[i]).Emit ();
                        }
 
                        if (operators != null)
@@ -2349,8 +2428,10 @@ namespace Mono.CSharp {
                                foreach (Property p in properties)
                                        p.Emit ();
 
-                       if (indexers != null){
-                               indexers.Emit ();
+                       if (indexers != null) {
+                               foreach (Indexer indx in indexers)
+                                       indx.Emit ();
+                               EmitIndexerName ();
                        }
                        
                        if (fields != null)
@@ -2368,12 +2449,6 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (enums != null) {
-                               foreach (Enum e in enums) {
-                                       e.Emit ();
-                               }
-                       }
-
                        if (pending != null)
                                if (pending.VerifyPendingMethods ())
                                        return;
@@ -2405,15 +2480,10 @@ namespace Mono.CSharp {
                                //
 //                             Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
 //                             Console.WriteLine (e.Message);
-                       } catch {
-                               Console.WriteLine ("In type: " + Name);
-                               throw;
+                       } catch (Exception e) {
+                               throw new InternalErrorException (this, e);
                        }
                        
-                       if (Enums != null)
-                               foreach (Enum en in Enums)
-                                       en.CloseType ();
-
                        if (Types != null){
                                foreach (TypeContainer tc in Types)
                                        if (tc.Kind == Kind.Struct)
@@ -2434,13 +2504,13 @@ namespace Mono.CSharp {
                        
                        types = null;
                        properties = null;
-                       enums = null;
                        delegates = null;
                        fields = null;
                        initialized_fields = null;
                        initialized_static_fields = null;
                        constants = null;
-                       interfaces = null;
+                       ordered_explicit_member_list = null;
+                       ordered_member_list = null;
                        methods = null;
                        events = null;
                        indexers = null;
@@ -2623,14 +2693,60 @@ namespace Mono.CSharp {
                        return false;
                }
 
+               public override Type LookupAnyGeneric (string typeName)
+               {
+                       if (types != null) {
+                               foreach (TypeContainer tc in types) {
+                                       if (!tc.IsGeneric)
+                                               continue;
+
+                                       int pos = tc.Basename.LastIndexOf ('`');
+                                       if (pos == typeName.Length && String.Compare (typeName, 0, tc.Basename, 0, pos) == 0)
+                                               return tc.TypeBuilder;
+                               }
+                       }
+
+                       return base.LookupAnyGeneric (typeName);
+               }
+
                public void Mark_HasEquals ()
                {
-                       Methods.HasEquals = true;
+                       cached_method |= CachedMethods.Equals;
                }
 
                public void Mark_HasGetHashCode ()
                {
-                       Methods.HasGetHashCode = true;
+                       cached_method |= CachedMethods.GetHashCode;
+               }
+
+               /// <summary>
+               /// Method container contains Equals method
+               /// </summary>
+               public bool HasEquals {
+                       get {
+                               return (cached_method & CachedMethods.Equals) != 0;
+                       }
+               }
+               /// <summary>
+               /// Method container contains GetHashCode method
+               /// </summary>
+               public bool HasGetHashCode {
+                       get {
+                               return (cached_method & CachedMethods.GetHashCode) != 0;
+                       }
+               }
+
+               public bool HasStaticFieldInitializer {
+                       get {
+                               return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
+                       }
+                       set {
+                               if (value)
+                                       cached_method |= CachedMethods.HasStaticFieldInitializer;
+                               else
+                                       cached_method &= ~CachedMethods.HasStaticFieldInitializer;
+                       }
                }
 
                //
@@ -2649,12 +2765,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               MemberCache IMemberContainer.MemberCache {
-                       get {
-                               return member_cache;
-                       }
-               }
-
                bool IMemberContainer.IsInterface {
                        get {
                                return Kind == Kind.Interface;
@@ -2685,7 +2795,7 @@ namespace Mono.CSharp {
                        get { return "T:"; }
                }
 
-               public virtual MemberCache BaseCache {
+               public MemberCache BaseCache {
                        get {
                                if (base_cache != null)
                                        return base_cache;
@@ -2730,11 +2840,10 @@ namespace Mono.CSharp {
                {
                        base.VerifyMembers ();
 
-                       if ((events != null) && (RootContext.WarningLevel >= 3)) {
+                       if ((events != null) && Report.WarningLevel >= 3) {
                                foreach (Event e in events){
-                                       if ((e.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
-                                               continue;
-
+                                       // Note: The event can be assigned from same class only, so we can report
+                                       // this warning for all accessibility modes
                                        if ((e.caching_flags & Flags.IsUsed) == 0)
                                                Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
                                }
@@ -2783,64 +2892,10 @@ namespace Mono.CSharp {
                        c.Block = new ToplevelBlock (null, Location);
                }
 
-               void DefineFieldInitializers ()
-               {
-                       if (initialized_fields != null) {
-                               for (int i = 0; i < initialized_fields.Count; ++i) {
-                                       FieldInitializer fi = (FieldInitializer)initialized_fields[i];
-
-                                       EmitContext ec = new EmitContext (fi.TypeContainer, fi.TypeContainer,
-                                               Location, null, null, ModFlags);
-                                       ec.IsFieldInitializer = true;
-
-                                       fi.ResolveStatement (ec);
-                                       if (fi.IsDefaultInitializer && RootContext.Optimize) {
-                                               // Field is re-initialized to its default value => removed
-                                               initialized_fields.RemoveAt (i);
-                                               --i;
-                                       }
-                               }
-                       }
-
-                       if (initialized_static_fields != null) {
-                               bool has_complex_initializer = false;
-
-                               foreach (FieldInitializer fi in initialized_static_fields) {
-                                       EmitContext ec = new EmitContext (fi.TypeContainer, fi.TypeContainer,
-                                               Location, null, null, ModFlags);
-                                       ec.IsStatic = true;
-                                       ec.IsFieldInitializer = true;
-
-                                       fi.ResolveStatement (ec);
-                                       if (!fi.IsComplexInitializer)
-                                               continue;
-
-                                       has_complex_initializer = true;
-                               }
-
-                               // Need special check to not optimize code like this
-                               // static int a = b = 5;
-                               // static int b = 0;
-                               if (!has_complex_initializer && RootContext.Optimize) {
-                                       for (int i = 0; i < initialized_static_fields.Count; ++i) {
-                                               FieldInitializer fi = (FieldInitializer)initialized_static_fields[i];
-                                               if (fi.IsDefaultInitializer) {
-                                                       initialized_static_fields.RemoveAt (i);
-                                                       --i;
-                                               }
-                                       }
-                               }
-
-                               if (default_static_constructor == null && initialized_static_fields.Count > 0) {
-                                       DefineDefaultConstructor (true);
-                               }
-                       }
-
-               }
-
                public override bool Define ()
                {
-                       DefineFieldInitializers ();
+                       if (default_static_constructor == null && PartialContainer.HasStaticFieldInitializer)
+                               DefineDefaultConstructor (true);
 
                        if (default_static_constructor != null)
                                default_static_constructor.Define ();
@@ -2861,7 +2916,7 @@ namespace Mono.CSharp {
 
                public override ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name)
                {
-                       return NamespaceEntry.LookupExtensionMethod (extensionType, true, name);
+                       return NamespaceEntry.LookupExtensionMethod (extensionType, this, name);
                }
 
                protected override TypeAttributes TypeAttr {
@@ -2898,10 +2953,18 @@ namespace Mono.CSharp {
                        this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
 
                        if (IsStatic && RootContext.Version == LanguageVersion.ISO_1) {
-                               Report.FeatureIsNotISO1 (Location, "static classes");
+                               Report.FeatureIsNotAvailable (Location, "static classes");
                        }
                }
 
+               public override void AddBasesForPart (DeclSpace part, ArrayList bases)
+               {
+                       if (part.Name == "System.Object")
+                               Report.Error (537, part.Location,
+                                       "The class System.Object cannot have a base class or implement an interface.");
+                       base.AddBasesForPart (part, bases);
+               }
+
                public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
                {
                        if (a.Type == TypeManager.attribute_usage_type) {
@@ -3070,8 +3133,8 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (IsStatic) {
-                               if (base_class != TypeManager.system_object_expr) {
+                       if (PartialContainer.IsStaticClass) {
+                               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;
@@ -3080,7 +3143,7 @@ namespace Mono.CSharp {
                                if (ifaces != null) {
                                        foreach (TypeExpr t in ifaces)
                                                Report.SymbolRelatedToPreviousError (t.Type);
-                                       Report.Error (714, Location, "`{0}': static classes cannot implement interfaces", GetSignatureForError ());
+                                       Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
                                }
                        }
 
@@ -3304,11 +3367,6 @@ namespace Mono.CSharp {
                {
                }
 
-               protected override bool CheckForDuplications ()
-               {
-                       throw new NotSupportedException ();
-               }
-
                protected override bool VerifyClsCompliance ()
                {
                        if (!base.VerifyClsCompliance ())
@@ -3355,114 +3413,37 @@ namespace Mono.CSharp {
                
                public ToplevelBlock Block {
                        get {
-                               return block;
-                       }
-
-                       set {
-                               block = value;
-                       }
-               }
-
-               protected bool DoDefineParameters ()
-               {
-                       IResolveContext rc = GenericMethod == null ? this : (IResolveContext)ds;
-
-                       // Check if arguments were correct
-                       if (!Parameters.Resolve (rc))
-                               return false;
-
-                       return CheckParameters (Parameters);
-               }
-
-               protected override bool CheckBase ()
-               {
-                       // Check whether arguments were correct.
-                       if (!DoDefineParameters ())
-                               return false;
-
-                       if (!base.CheckBase ())
-                               return false;
+                               return block;
+                       }
 
-                       return true;
+                       set {
+                               block = value;
+                       }
                }
 
-               // TODO: create a special method for operators only to make code better
-               protected bool IsDuplicateImplementation (MethodCore method)
+               protected override bool CheckBase ()
                {
-                       if (method == this)
+                       // Check whether arguments were correct.
+                       if (!DefineParameters (Parameters))
                                return false;
 
-                       Operator op2 = null;
-                       Operator op1 = null;
-
-                       if (!(method.MemberName.Equals (MemberName)))
-                       {
-                               op1 = this as Operator;
-                               if (op1 == null || !(op1.OperatorType == Operator.OpType.Explicit || op1.OperatorType == Operator.OpType.Implicit))
-                                       return false;
-
-                               op2 = method as Operator;
-                               if (op2 == null || !(op2.OperatorType == Operator.OpType.Explicit || op2.OperatorType == Operator.OpType.Implicit))
+                       if ((caching_flags & Flags.MethodOverloadsExist) != 0) {
+                               if (!Parent.MemberCache.CheckExistingMembersOverloads (this,
+                                       MemberName.IsGeneric ? MemberName.Basename : MemberName.MethodName, Parameters))
                                        return false;
-                       } else {
-                               op1 = this as Operator;
-                               op2 = method as Operator;
-                       }
-
-                       Type[] param_types = method.ParameterTypes;
-                       // This never happen. Rewrite this as Equal
-                       if (param_types == null && ParameterTypes == null)
-                               return true;
-                       if (param_types == null || ParameterTypes == null)
-                               return false;
-
-                       if (param_types.Length != ParameterTypes.Length)
-                               return false;
-
-                       if (method.Parameters.HasArglist != Parameters.HasArglist)
-                               return false;
-                       
-                       bool equal = true;
-
-                       for (int i = 0; i < param_types.Length; i++) {
-                               if (param_types [i] != ParameterTypes [i])
-                                       equal = false;
-                       }
-
-                       if (IsExplicitImpl && (method.InterfaceType != InterfaceType))
-                               equal = false;
-
-                       // TODO: make operator compatible with MethodCore to avoid this
-                       if (op1 != null && op2 != null) {
-                               if (MemberType != method.MemberType)
-                                       equal = false;
-                       }
 
-                       if (equal) {
-                               //
-                               // Try to report 663: method only differs on out/ref
-                               //
-                               Parameters info = ParameterInfo;
-                               Parameters other_info = method.ParameterInfo;
-                               for (int i = 0; i < info.Count; i++){
-                                       if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
-                                               Report.SymbolRelatedToPreviousError (method);
-                                               Report.Error (663, Location, "`{0}': Methods cannot differ only on their use of ref and out on a parameters",
-                                                             GetSignatureForError ());
+                               // TODO: Find a better way how to check reserved accessors collision
+                               Method m = this as Method;
+                               if (m != null) {
+                                       if (!m.CheckForDuplications ())
                                                return false;
-                                       }
                                }
-
-                               Report.SymbolRelatedToPreviousError (method);
-                               if (this is Operator && method is Operator)
-                                       Report.Error (557, Location, "Duplicate user-defined conversion in type `{0}'", Parent.Name);
-                               else
-                                       Report.Error (111, Location, TypeContainer.Error111, GetSignatureForError ());
-
-                               return true;
                        }
 
-                       return false;
+                       if (!base.CheckBase ())
+                               return false;
+
+                       return true;
                }
 
                //
@@ -3494,6 +3475,16 @@ namespace Mono.CSharp {
                        get { return "M:"; }
                }
 
+               public override bool EnableOverloadChecks (MemberCore overload)
+               {
+                       if (overload is MethodCore || overload is AbstractPropertyEventMethod) {
+                               caching_flags |= Flags.MethodOverloadsExist;
+                               return true;
+                       }
+
+                       return false;
+               }
+
                public virtual void SetYields ()
                {
                        ModFlags |= Modifiers.METHOD_YIELDS;
@@ -3530,6 +3521,8 @@ namespace Mono.CSharp {
                //
                public bool IsExplicitImpl;
 
+               protected bool is_external_implementation;
+
                //
                // The interface type we are explicitly implementing
                //
@@ -3559,9 +3552,6 @@ namespace Mono.CSharp {
                        if (!base.CheckBase ())
                                return false;
                        
-                       if ((caching_flags & Flags.TestMethodDuplication) != 0 && !CheckForDuplications ())
-                               return false;
-
                        if (IsExplicitImpl)
                                return true;
 
@@ -3617,7 +3607,7 @@ namespace Mono.CSharp {
                        }
 
                        if (conflict_symbol == null) {
-                               if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
+                               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 ());
                                }
                                return true;
@@ -3642,7 +3632,7 @@ namespace Mono.CSharp {
                // `name' is the user visible name for reporting errors (this is used to
                // provide the right name regarding method names and properties)
                //
-               bool CheckMethodAgainstBase (Type baseMethodType)
+               bool CheckMethodAgainstBase (Type base_method_type)
                {
                        bool ok = true;
 
@@ -3673,15 +3663,15 @@ namespace Mono.CSharp {
                                        ok = false;
                                }
 
-                               if (!TypeManager.IsEqual (MemberType, TypeManager.TypeToCoreType (baseMethodType))) {
+                               if (!TypeManager.IsEqual (MemberType, TypeManager.TypeToCoreType (base_method_type))) {
                                        Report.SymbolRelatedToPreviousError (base_method);
                                        if (this is PropertyBasedMember) {
                                                Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'", 
-                                                       GetSignatureForError (), TypeManager.CSharpName (baseMethodType), TypeManager.CSharpSignature (base_method));
+                                                       GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
                                        }
                                        else {
                                                Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
-                                                       GetSignatureForError (), TypeManager.CSharpName (baseMethodType), TypeManager.CSharpSignature (base_method));
+                                                       GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
                                        }
                                        ok = false;
                                }
@@ -3716,23 +3706,20 @@ namespace Mono.CSharp {
                        if ((base_classp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
                                //
                                // when overriding protected internal, the method can be declared
-                               // protected internal only within the same assembly
+                               // protected internal only within the same assembly or assembly
+                               // which has InternalsVisibleTo
                                //
-
                                if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
-                                       if (Parent.TypeBuilder.Assembly != base_method.DeclaringType.Assembly){
-                                               //
-                                               // assemblies differ - report an error
-                                               //
-                                               
-                                               return false;
-                                       } else if (thisp != base_classp) {
+                                       if (Parent.TypeBuilder.Assembly != base_method.DeclaringType.Assembly)
+                                               return TypeManager.IsFriendAssembly (base_method.DeclaringType.Assembly);
+
+                                       if (thisp != base_classp) {
                                                //
                                                // same assembly, but other attributes differ - report an error
                                                //
                                                
                                                return false;
-                                       };
+                                       }
                                } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
                                        //
                                        // if it's not "protected internal", it must be "protected"
@@ -3757,66 +3744,35 @@ namespace Mono.CSharp {
                        }
                }
 
-               public bool CheckAbstractAndExtern (bool has_block)
+               protected bool DefineParameters (Parameters parameters)
                {
-                       if (Parent.PartialContainer.Kind == Kind.Interface)
-                               return true;
-
-                       if (has_block) {
-                               if ((ModFlags & Modifiers.EXTERN) != 0) {
-                                       Report.Error (179, Location, "`{0}' cannot declare a body because it is marked extern",
-                                               GetSignatureForError ());
-                                       return false;
-                               }
-
-                               if ((ModFlags & Modifiers.ABSTRACT) != 0) {
-                                       Report.Error (500, Location, "`{0}' cannot declare a body because it is marked abstract",
-                                               GetSignatureForError ());
-                                       return false;
-                               }
-                       } else {
-                               if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
-                                       Report.Error (501, Location, "`{0}' must declare a body because it is not marked abstract or extern",
-                                               GetSignatureForError ());
-                                       return false;
-                               }
-                       }
+                       IResolveContext rc = GenericMethod == null ? this : (IResolveContext)ds;
 
-                       return true;
-               }
+                       if (!parameters.Resolve (rc))
+                               return false;
 
-               protected bool CheckParameters (Parameters parameters)
-               {
                        bool error = false;
-
-                       foreach (Type partype in parameters.Types){
-                               if (partype.IsPointer){
-                                       if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
-                                               error = true;
-                               }
-
-                               if (ds.AsAccessible (partype, ModFlags))
+                       foreach (Parameter p in parameters.FixedParameters) {
+                               if (p.CheckAccessibility (this))
                                        continue;
 
-                               Report.SymbolRelatedToPreviousError (partype);
+                               Report.SymbolRelatedToPreviousError (p.ParameterType);
                                if (this is Indexer)
                                        Report.Error (55, Location,
                                                "Inconsistent accessibility: parameter type `" +
-                                               TypeManager.CSharpName (partype) + "' is less " +
+                                               TypeManager.CSharpName (p.ParameterType) + "' is less " +
                                                "accessible than indexer `" + GetSignatureForError () + "'");
                                else if (this is Operator)
                                        Report.Error (57, Location,
                                                "Inconsistent accessibility: parameter type `" +
-                                               TypeManager.CSharpName (partype) + "' is less " +
+                                               TypeManager.CSharpName (p.ParameterType) + "' is less " +
                                                "accessible than operator `" + GetSignatureForError () + "'");
                                else
                                        Report.Error (51, Location,
-                                               "Inconsistent accessibility: parameter type `" +
-                                               TypeManager.CSharpName (partype) + "' is less " +
-                                               "accessible than method `" + GetSignatureForError () + "'");
+                                               "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
+                                               TypeManager.CSharpName (p.ParameterType), GetSignatureForError ());
                                error = true;
                        }
-
                        return !error;
                }
 
@@ -3873,6 +3829,12 @@ namespace Mono.CSharp {
                                if (iface_texpr == null)
                                        return false;
 
+                               if ((ModFlags & Modifiers.PARTIAL) != 0) {
+                                       Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
+                                               GetSignatureForError ());
+                                       return false;
+                               }
+
                                InterfaceType = iface_texpr.Type;
 
                                if (!InterfaceType.IsInterface) {
@@ -3889,6 +3851,19 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               public override void Emit()
+               {
+                       // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
+                       // We are more strict than Microsoft and report CS0626 as error
+                       if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) {
+                               Report.Error (626, Location,
+                                       "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
+                                       GetSignatureForError ());
+                       }
+
+                       base.Emit ();
+               }
+
                protected void Error_CannotChangeAccessModifiers (MemberInfo base_method, MethodAttributes ma, string suffix)
                {
                        Report.SymbolRelatedToPreviousError (base_method);
@@ -3909,11 +3884,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               /// <summary>
-               /// For custom member duplication search in a container
-               /// </summary>
-               protected abstract bool CheckForDuplications ();
-
                /// <summary>
                /// Gets base method and its return type
                /// </summary>
@@ -3985,9 +3955,8 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       if (a.Type == TypeManager.methodimpl_attr_type &&
-                               (a.GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0) {
-                               MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
+                       if (a.IsInternalMethodImplAttribute) {
+                               is_external_implementation = true;
                        }
 
                        if (a.Type == TypeManager.dllimport_type) {
@@ -3995,8 +3964,7 @@ namespace Mono.CSharp {
                                if ((ModFlags & extern_static) != extern_static) {
                                        Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
                                }
-
-                               return;
+                               is_external_implementation = true;
                        }
 
                        if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
@@ -4006,7 +3974,8 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       MethodBuilder.SetCustomAttribute (cb);
+                       if (MethodBuilder != null)
+                               MethodBuilder.SetCustomAttribute (cb);
                }
 
                public override AttributeTargets AttributeTargets {
@@ -4042,7 +4011,11 @@ namespace Mono.CSharp {
                                                '.' + method_name;
                                }
 
+#if MS_COMPATIBLE
+                               MethodBuilder = Parent.TypeBuilder.DefineMethod (method_name, flags); //, ReturnType, null);
+#else
                                MethodBuilder = Parent.TypeBuilder.DefineMethod (method_name, flags);
+#endif
 
                                if (!GenericMethod.Define (MethodBuilder, block))
                                        return false;
@@ -4081,20 +4054,52 @@ namespace Mono.CSharp {
                        if (!CheckAbstractAndExtern (block != null))
                                return false;
 
+                       if ((ModFlags & Modifiers.PARTIAL) != 0) {
+                               for (int i = 0; i < Parameters.Count; ++i ) {
+                                       if (Parameters.ParameterModifier (i) == Parameter.Modifier.OUT) {
+                                               Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier",
+                                                       GetSignatureForError ());
+                                               return false;
+                                       }
+                               }
+                       }
+
                        if (!CheckBase ())
                                return false;
+                       
+                       if (IsPartialDefinition) {
+                               caching_flags &= ~Flags.Excluded_Undetected;
+                               caching_flags |= Flags.Excluded;
+                               // Add to member cache only when a partial method implementation is not there
+                               if ((caching_flags & Flags.MethodOverloadsExist) == 0) {
+                                       MethodBase mb = new PartialMethodDefinitionInfo (this);
+                                       Parent.MemberCache.AddMember (mb, this);
+                                       TypeManager.AddMethod (mb, this);
+                               }
+
+                               return true;
+                       }
 
                        MethodData = new MethodData (
                                this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method);
 
                        if (!MethodData.Define (Parent.PartialContainer))
                                return false;
-
+                                       
                        MethodBuilder = MethodData.MethodBuilder;
 
-                       if (MemberType.IsAbstract && MemberType.IsSealed) {
-                               Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
-                               return false;
+#if GMCS_SOURCE                                                
+                       if (MethodBuilder.IsGenericMethod)
+                               Parent.MemberCache.AddGenericMember (MethodBuilder, this);
+#endif                 
+                       
+                       Parent.MemberCache.AddMember (MethodBuilder, this);
+
+                       if (!TypeManager.IsGenericParameter (MemberType)) {
+                               if (MemberType.IsAbstract && MemberType.IsSealed) {
+                                       Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
+                                       return false;
+                               }
                        }
 
                        return true;
@@ -4102,6 +4107,10 @@ namespace Mono.CSharp {
 
                public override void Emit ()
                {
+#if GMCS_SOURCE                        
+                       if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0)
+                               MethodBuilder.SetCustomAttribute (TypeManager.compiler_generated_attr);
+#endif
                        if (OptAttributes != null)
                                OptAttributes.Emit ();
 
@@ -4121,10 +4130,16 @@ namespace Mono.CSharp {
                                GetSignatureForError ());
                }
 
-               public override bool MarkForDuplicationCheck ()
-               {
-                       caching_flags |= Flags.TestMethodDuplication;
-                       return true;
+               public bool IsPartialDefinition {
+                       get {
+                               return (ModFlags & Modifiers.PARTIAL) != 0 && Block == null;
+                       }
+               }
+
+               public bool IsPartialImplementation {
+                       get {
+                               return (ModFlags & Modifiers.PARTIAL) != 0 && Block != null;
+                       }
                }
 
                public override string[] ValidAttributeTargets {
@@ -4138,7 +4153,7 @@ namespace Mono.CSharp {
                public CallingConventions CallingConventions {
                        get {
                                CallingConventions cc = Parameters.CallingConvention;
-                               if (Parameters.HasArglist)
+                               if (Parameters.HasArglist && block != null)
                                        block.HasVarargs = true;
 
                                if (!IsInterface)
@@ -4219,7 +4234,7 @@ namespace Mono.CSharp {
                                return true;
                        }
 
-                       IMethodData md = TypeManager.GetMethod (base_method);
+                       IMethodData md = TypeManager.GetMethod (TypeManager.DropGenericMethodArguments (base_method));
                        if (md == null) {
                                if (AttributeTester.IsConditionalMethodExcluded (base_method)) {
                                        caching_flags |= Flags.Excluded;
@@ -4397,6 +4412,7 @@ namespace Mono.CSharp {
                                }
 
                                if (MethodData.implementing != null) {
+                                       Report.SymbolRelatedToPreviousError (MethodData.implementing.DeclaringType);
                                        Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
                                                GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
                                        return;
@@ -4418,20 +4434,9 @@ namespace Mono.CSharp {
                        base.ApplyAttributeBuilder (a, cb);
                }
 
-               protected override bool CheckForDuplications ()
+               public bool CheckForDuplications ()
                {
-                       ArrayList ar = Parent.PartialContainer.Methods;
-                       if (ar != null) {
-                               int arLen = ar.Count;
-                                       
-                               for (int i = 0; i < arLen; i++) {
-                                       Method m = (Method) ar [i];
-                                       if (IsDuplicateImplementation (m))
-                                               return false;
-                               }
-                       }
-
-                       ar = Parent.PartialContainer.Properties;
+                       ArrayList ar = Parent.PartialContainer.Properties;
                        if (ar != null) {
                                for (int i = 0; i < ar.Count; ++i) {
                                        PropertyBase pb = (PropertyBase) ar [i];
@@ -4449,15 +4454,6 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       ar = Parent.PartialContainer.Events;
-                       if (ar != null) {
-                               for (int i = 0; i < ar.Count; ++i) {
-                                       Event ev = (Event) ar [i];
-                                       if (ev.AreAccessorsDuplicateImplementation (this))
-                                               return false;
-                               }
-                       }
-
                        return true;
                }
 
@@ -4479,7 +4475,7 @@ namespace Mono.CSharp {
                                Report.Warning (465, 1, Location, "Introducing a 'Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
                        }
 
-                       if (base_method != null) {
+                       if (base_method != null && (ModFlags & Modifiers.NEW) == 0) {
                                if (Parameters.Count == 1 && ParameterTypes [0] == TypeManager.object_type && Name == "Equals")
                                        Parent.PartialContainer.Mark_HasEquals ();
                                else if (Parameters.Empty && Name == "GetHashCode")
@@ -4547,15 +4543,47 @@ namespace Mono.CSharp {
                // 
                public override void Emit ()
                {
-                       Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
-                       MethodData.Emit (Parent);
-                       base.Emit ();
+                       try {
+                               Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
+                               if (IsPartialDefinition) {
+                                       //
+                                       // Do attribute checks only when partial implementation does not exist
+                                       //
+                                       if (MethodBuilder == null)
+                                               base.Emit ();
 
-                       if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
-                               MethodBuilder.SetCustomAttribute (TypeManager.extension_attribute_attr);
+                                       return;
+                               }
 
-                       Block = null;
-                       MethodData = null;
+                               if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0)
+                                       Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration",
+                                               GetSignatureForError ());
+
+                               MethodData.Emit (Parent);
+                               base.Emit ();
+                               
+                               if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
+                                       MethodBuilder.SetCustomAttribute (TypeManager.extension_attribute_attr);
+                               
+                               Block = null;
+                               MethodData = null;
+                       } catch {
+                               Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}",
+                                                  Location, MethodBuilder);
+                               throw;
+                       }
+               }
+
+               public override bool EnableOverloadChecks (MemberCore overload)
+               {
+                       // TODO: It can be deleted when members will be defined in correct order
+                       if (overload is Operator)
+                               return overload.EnableOverloadChecks (this);
+
+                       if (overload is Indexer)
+                               return false;
+
+                       return base.EnableOverloadChecks (overload);
                }
 
                public static void Error1599 (Location loc, Type t)
@@ -4578,6 +4606,20 @@ namespace Mono.CSharp {
                        return mi;
                }
 
+               public void SetPartialDefinition (Method methodDefinition)
+               {
+                       caching_flags |= Flags.PartialDefinitionExists;
+                       methodDefinition.MethodBuilder = MethodBuilder;
+                       if (methodDefinition.attributes == null)
+                               return;
+
+                       if (attributes == null) {
+                               attributes = methodDefinition.attributes;
+                       } else {
+                               attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
+                       }
+               }
+
                protected override bool VerifyClsCompliance ()
                {
                        if (!base.VerifyClsCompliance ())
@@ -4593,10 +4635,10 @@ namespace Mono.CSharp {
                }
        }
 
-       public abstract class ConstructorInitializer {
-               ArrayList argument_list;
-               protected ConstructorInfo base_constructor;
-               Location loc;
+       public abstract class ConstructorInitializer : Expression
+       {
+               readonly ArrayList argument_list;
+               MethodGroupExpr base_constructor_group;
                
                public ConstructorInitializer (ArrayList argument_list, Location loc)
                {
@@ -4610,27 +4652,20 @@ namespace Mono.CSharp {
                        }
                }
 
-               public bool Resolve (ConstructorBuilder caller_builder, Block block, EmitContext ec)
+               public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
                {
-                       Expression base_constructor_group;
-                       Type t;
-                       bool error = false;
-
-                       ec.CurrentBlock = block;
-
                        if (argument_list != null){
                                foreach (Argument a in argument_list){
                                        if (!a.Resolve (ec, loc))
                                                return false;
                                }
                        }
-                       ec.CurrentBlock = null;
 
                        if (this is ConstructorBaseInitializer) {
                                if (ec.ContainerType.BaseType == null)
                                        return true;
 
-                               t = ec.ContainerType.BaseType;
+                               type = ec.ContainerType.BaseType;
                                if (ec.ContainerType.IsValueType) {
                                        Report.Error (522, loc,
                                                "`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder));
@@ -4646,60 +4681,48 @@ namespace Mono.CSharp {
                                if (ec.ContainerType.IsValueType && argument_list == null)
                                        return true;
                                
-                               t = ec.ContainerType;
+                               type = ec.ContainerType;
                        }
 
-                       base_constructor_group = Expression.MemberLookup (
-                               ec.ContainerType, t, ".ctor", MemberTypes.Constructor,
+                       base_constructor_group = MemberLookupFinal (
+                               ec, null, type, ConstructorBuilder.ConstructorName, MemberTypes.Constructor,
                                BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
-                               loc);
-                       
-                       if (base_constructor_group == null){
-                               error = true;
-                               base_constructor_group = Expression.MemberLookup (
-                                       t, null, t, ".ctor", MemberTypes.Constructor,
-                                       BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
-                                       loc);
-                       }
-
-                       int errors = Report.Errors;
-                       if (base_constructor_group != null)
-                               base_constructor = (ConstructorInfo)
-                                       ((MethodGroupExpr) base_constructor_group).OverloadResolve (
-                                       ec, argument_list,
-                                       false, loc);
+                               loc) as MethodGroupExpr;
                        
-                       if (base_constructor == null) {
-                               if (errors == Report.Errors)
-                                       Invocation.Error_WrongNumArguments (loc, TypeManager.CSharpSignature (caller_builder),
-                                               argument_list == null ? 0 : argument_list.Count);
+                       if (base_constructor_group == null)
                                return false;
-                       }
-
-                       if (error) {
-                               Report.SymbolRelatedToPreviousError (base_constructor);
-                               Expression.ErrorIsInaccesible (loc, TypeManager.CSharpSignature (base_constructor));
-                               base_constructor = null;
+                       
+                       base_constructor_group = base_constructor_group.OverloadResolve (
+                               ec, argument_list, false, loc);
+                       
+                       if (base_constructor_group == null)
                                return false;
-                       }
                        
-                       if (base_constructor == caller_builder){
+                       ConstructorInfo base_ctor = (ConstructorInfo)base_constructor_group;
+                       
+                       if (base_ctor == caller_builder){
                                Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
-                               return false;
                        }
-                       
+                                               
                        return true;
                }
 
-               public virtual void Emit (EmitContext ec)
+               public override Expression DoResolve (EmitContext ec)
                {
-                       if (base_constructor != null){
-                               ec.Mark (loc, false);
-                               if (ec.IsStatic)
-                                       Invocation.EmitCall (ec, true, true, null, base_constructor, argument_list, loc);
-                               else
-                                       Invocation.EmitCall (ec, true, false, ec.GetThis (loc), base_constructor, argument_list, loc);
-                       }
+                       throw new NotSupportedException ();
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       // It can be null for static initializers
+                       if (base_constructor_group == null)
+                               return;
+                       
+                       ec.Mark (loc, false);
+                       if (!ec.IsStatic)
+                               base_constructor_group.InstanceExpression = ec.GetThis (loc);
+                       
+                       base_constructor_group.EmitCall (ec, argument_list);
                }
        }
 
@@ -4729,6 +4752,7 @@ namespace Mono.CSharp {
                public ConstructorInitializer Initializer;
                ListDictionary declarative_security;
                ArrayList anonymous_methods;
+               bool has_compliant_args;
 
                // <summary>
                //   Modifiers allowed for a constructor.
@@ -4742,13 +4766,8 @@ namespace Mono.CSharp {
                        Modifiers.EXTERN |              
                        Modifiers.PRIVATE;
 
-               static string[] attribute_targets = new string [] { "method" };
-
-               public Iterator Iterator {
-                       get { return null; }
-               }
+               static readonly string[] attribute_targets = new string [] { "method" };
 
-               bool has_compliant_args = false;
                //
                // The spec claims that static is not permitted, but
                // my very own code has static constructors.
@@ -4769,6 +4788,9 @@ namespace Mono.CSharp {
                        get { return AttributeTargets.Constructor; }
                }
 
+               public Iterator Iterator {
+                       get { return null; }
+               }
 
                //
                // Returns true if this is a default constructor
@@ -4793,9 +4815,8 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       if (a.Type == TypeManager.methodimpl_attr_type &&
-                               (a.GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0) {
-                               ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
+                       if (a.IsInternalMethodImplAttribute) {
+                               is_external_implementation = true;
                        }
 
                        ConstructorBuilder.SetCustomAttribute (cb);
@@ -4820,21 +4841,6 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               protected override bool CheckForDuplications ()
-               {
-                       ArrayList ar = Parent.PartialContainer.InstanceConstructors;
-                       if (ar != null) {
-                               int arLen = ar.Count;
-                                       
-                               for (int i = 0; i < arLen; i++) {
-                                       Constructor m = (Constructor) ar [i];
-                                       if (IsDuplicateImplementation (m))
-                                               return false;
-                               }
-                       }
-                       return true;
-               }
-
                protected override bool CheckBase ()
                {
                        if ((ModFlags & Modifiers.STATIC) != 0) {
@@ -4849,11 +4855,12 @@ namespace Mono.CSharp {
                        }
 
                        // Check whether arguments were correct.
-                       if (!DoDefineParameters ())
+                       if (!DefineParameters (Parameters))
                                return false;
 
-                       if (!CheckForDuplications ())
-                               return false;
+                       if ((caching_flags & Flags.MethodOverloadsExist) != 0)
+                               Parent.MemberCache.CheckExistingMembersOverloads (this, ConstructorBuilder.ConstructorName,
+                                       Parameters);
 
                        if (Parent.PartialContainer.Kind == Kind.Struct) {
                                if (ParameterTypes.Length == 0) {
@@ -4868,7 +4875,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if ((RootContext.WarningLevel >= 4) && ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.PROTECTED) != 0)) {
+                       if ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.PROTECTED) != 0) {
                                Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", GetSignatureForError ());
                        }
                        
@@ -4927,7 +4934,14 @@ namespace Mono.CSharp {
                                ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
                        }
                        
+                       Parent.MemberCache.AddMember (ConstructorBuilder, this);
                        TypeManager.AddMethod (ConstructorBuilder, this);
+                       
+                       // It's here only to report an error
+                       if ((ModFlags & Modifiers.METHOD_YIELDS) != 0) {
+                               member_type = TypeManager.void_type;
+                               Iterator.CreateIterator (this, Parent, null, ModFlags);
+                       }
 
                        return true;
                }
@@ -4940,8 +4954,20 @@ namespace Mono.CSharp {
                        if (OptAttributes != null)
                                OptAttributes.Emit ();
 
+                       base.Emit ();
+
                        EmitContext ec = CreateEmitContext (null, null);
 
+                       //
+                       // If we use a "this (...)" constructor initializer, then
+                       // do not emit field initializers, they are initialized in the other constructor
+                       //
+                       bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) ||
+                               !(Initializer is ConstructorThisInitializer);
+
+                       if (emit_field_initializers)
+                               Parent.PartialContainer.ResolveFieldInitializers (ec);
+
                        if (block != null) {
                                // If this is a non-static `struct' constructor and doesn't have any
                                // initializer, it must initialize all of the struct's fields.
@@ -4957,14 +4983,13 @@ namespace Mono.CSharp {
                                if (Parent.PartialContainer.Kind == Kind.Class && Initializer == null)
                                        Initializer = new GeneratedBaseInitializer (Location);
 
-
                                //
                                // Spec mandates that Initializers will not have
                                // `this' access
                                //
                                ec.IsStatic = true;
                                if ((Initializer != null) &&
-                                   !Initializer.Resolve (ConstructorBuilder, block, ec))
+                                   !Initializer.Resolve (ConstructorBuilder, ec))
                                        return;
                                ec.IsStatic = false;
                        }
@@ -4974,48 +4999,33 @@ namespace Mono.CSharp {
                        SourceMethod source = SourceMethod.Create (
                                Parent, ConstructorBuilder, block);
 
-                       //
-                       // Classes can have base initializers and instance field initializers.
-                       //
-                       if (Parent.PartialContainer.Kind == Kind.Class){
-                               if ((ModFlags & Modifiers.STATIC) == 0){
-
-                                       //
-                                       // If we use a "this (...)" constructor initializer, then
-                                       // do not emit field initializers, they are initialized in the other constructor
-                                       //
-                                       if (!(Initializer != null && Initializer is ConstructorThisInitializer))
-                                               Parent.PartialContainer.EmitFieldInitializers (ec);
-                               }
-                       }
-
                        bool unreachable = false;
                        if (block != null) {
                                if (!ec.ResolveTopBlock (null, block, ParameterInfo, this, out unreachable))
                                        return;
+
                                ec.EmitMeta (block);
 
+                               if (Report.Errors > 0)
+                                       return;
+
+                               if (emit_field_initializers)
+                                       Parent.PartialContainer.EmitFieldInitializers (ec);
+
                                if (block.ScopeInfo != null) {
                                        ExpressionStatement init = block.ScopeInfo.GetScopeInitializer (ec);
                                        init.EmitStatement (ec);
                                }
-                       }
 
-                       if (Initializer != null) {
-                               Initializer.Emit (ec);
-                       }
+                               if (Initializer != null)
+                                       Initializer.Emit (ec);
                        
-                       if ((ModFlags & Modifiers.STATIC) != 0)
-                               Parent.PartialContainer.EmitFieldInitializers (ec);
-
-                       if (block != null)
                                ec.EmitResolvedTopBlock (block, unreachable);
+                       }
 
                        if (source != null)
                                source.CloseMethod ();
 
-                       base.Emit ();
-
                        if (declarative_security != null) {
                                foreach (DictionaryEntry de in declarative_security) {
                                        ConstructorBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
@@ -5050,7 +5060,7 @@ namespace Mono.CSharp {
                        
                        if (ParameterInfo.Count > 0) {
                                ArrayList al = (ArrayList)Parent.MemberCache.Members [".ctor"];
-                               if (al.Count > 3)
+                               if (al.Count > 2)
                                        MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder);
  
                                if (Parent.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
@@ -5102,7 +5112,9 @@ namespace Mono.CSharp {
                public EmitContext CreateEmitContext (DeclSpace ds, ILGenerator ig)
                {
                        ILGenerator ig_ = ConstructorBuilder.GetILGenerator ();
-                       return new EmitContext (this, Parent, Location, ig_, null, ModFlags, true);
+                       EmitContext ec = new EmitContext (this, Parent, Location, ig_, TypeManager.void_type, ModFlags, true);
+                       ec.CurrentBlock = block;
+                       return ec;
                }
 
                public bool IsExcluded()
@@ -5238,18 +5250,17 @@ namespace Mono.CSharp {
                                                return false;
                                        }
 
-                                       method_name = TypeManager.GetFullName (member.InterfaceType) +
+                                       method_name = member.InterfaceType.FullName + 
                                                '.' + method_name;
                                } else {
                                        if (implementing != null) {
                                                AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
                                                if (prop_method == null) {
-                                                       if (implementing.IsSpecialName) {
+                                                       if (TypeManager.IsSpecialMethod (implementing)) {
                                                                Report.SymbolRelatedToPreviousError (implementing);
                                                                Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}.{2}'",
                                                                        method.GetSignatureForError (), TypeManager.CSharpSignature (implementing),
                                                                        implementing.Name.StartsWith ("get_") ? "get" : "set");
-                                                               return false;
                                                        }
                                                } else if (implementing.DeclaringType.IsInterface) {
                                                        if (!implementing.IsSpecialName) {
@@ -5340,8 +5351,6 @@ namespace Mono.CSharp {
                                        flags |= MethodAttributes.Final;
                        }
 
-                       EmitContext ec = method.CreateEmitContext (container, null);
-
                        DefineMethodBuilder (container, method_name, method.ParameterInfo.Types);
 
                        if (builder == null)
@@ -5383,6 +5392,7 @@ namespace Mono.CSharp {
                                if (implementing != null)
                                        parent_method = implementing;
 
+                               EmitContext ec = method.CreateEmitContext (container, null);
                                if (!GenericMethod.DefineType (ec, builder, parent_method, is_override))
                                        return false;
                        }
@@ -5395,31 +5405,7 @@ namespace Mono.CSharp {
                /// Create the MethodBuilder for the method 
                /// </summary>
                void DefineMethodBuilder (TypeContainer container, string method_name, Type[] ParameterTypes)
-               {
-                       if ((modifiers & Modifiers.EXTERN) != 0) {
-                               if (method.OptAttributes != null) {
-                                       Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type);
-                                       if (dllimport_attribute != null) {
-                                               flags |= MethodAttributes.PinvokeImpl;
-                                               builder = dllimport_attribute.DefinePInvokeMethod (
-                                                       container.TypeBuilder, method_name, flags,
-                                                       method, ParameterTypes);
-
-                                               return;
-                                       }
-                               }
-
-                               // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
-                               // We are more strict than Microsoft and report CS0626 like error
-                               if (method.OptAttributes == null ||
-                                       !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type)) {
-                                       Report.Error (626, method.Location,
-                                               "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
-                                               member.GetSignatureForError ());
-                                       return;
-                               }
-                       }
-
+               {
                        if (builder == null) {
                                builder = container.TypeBuilder.DefineMethod (
                                        method_name, flags, method.CallingConventions,
@@ -5439,8 +5425,10 @@ namespace Mono.CSharp {
                // 
                public void Emit (DeclSpace parent)
                {
+                       ToplevelBlock block = method.Block;
+
                        EmitContext ec;
-                       if ((flags & MethodAttributes.PinvokeImpl) == 0)
+                       if (block != null)
                                ec = method.CreateEmitContext (parent, builder.GetILGenerator ());
                        else
                                ec = method.CreateEmitContext (parent, null);
@@ -5449,8 +5437,6 @@ namespace Mono.CSharp {
 
                        if (GenericMethod != null)
                                GenericMethod.EmitAttributes ();
-
-                       ToplevelBlock block = method.Block;
                        
                        SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
 
@@ -5582,7 +5568,7 @@ namespace Mono.CSharp {
                                return false;
                        }
    
-                       if ((RootContext.WarningLevel >= 4) &&
+                       if (Report.WarningLevel >= 4 &&
                            ((Parent.ModFlags & Modifiers.SEALED) != 0) &&
                            ((ModFlags & Modifiers.PROTECTED) != 0) &&
                            ((ModFlags & Modifiers.OVERRIDE) == 0) && (Name != "Finalize")) {
@@ -5745,6 +5731,9 @@ namespace Mono.CSharp {
                        if (MemberType == null || Type == null)
                                return false;
 
+                       if (TypeManager.IsGenericParameter (MemberType))
+                               return true;
+
                        if (MemberType == TypeManager.void_type) {
                                // TODO: wrong location
                                Expression.Error_VoidInvalidInTheContext (Location);
@@ -5782,6 +5771,12 @@ namespace Mono.CSharp {
 
                public override void Emit ()
                {
+#if GMCS_SOURCE
+                       if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0) {
+                               FieldBuilder.SetCustomAttribute (TypeManager.compiler_generated_attr);
+                       }
+#endif
+
                        if (OptAttributes != null) {
                                OptAttributes.Emit ();
                        }
@@ -5793,11 +5788,11 @@ namespace Mono.CSharp {
                        base.Emit ();
                }
 
-               public static void Error_VariableOfStaticClass (Location loc, string variableName, Type staticClass)
+               public static void Error_VariableOfStaticClass (Location loc, string variable_name, Type static_class)
                {
-                       Report.SymbolRelatedToPreviousError (staticClass);
+                       Report.SymbolRelatedToPreviousError (static_class);
                        Report.Error (723, loc, "`{0}': cannot declare variables of static types",
-                               variableName);
+                               variable_name);
                }
 
                public Expression Initializer {
@@ -5900,7 +5895,7 @@ namespace Mono.CSharp {
                        base (parent, type, mod, AllowedModifiers, new MemberName (name, loc), attrs)
                {
                        if (RootContext.Version == LanguageVersion.ISO_1)
-                               Report.FeatureIsNotISO1 (loc, "fixed size buffers");
+                               Report.FeatureIsNotAvailable (loc, "fixed size buffers");
 
                        this.size_expr = size_expr;
                }
@@ -5915,9 +5910,11 @@ namespace Mono.CSharp {
                        if (Parent.PartialContainer.Kind != Kind.Struct) {
                                Report.Error (1642, Location, "`{0}': Fixed size buffer fields may only be members of structs",
                                        GetSignatureForError ());
-                               return false;
                        }
 
+                       if (!Parent.IsInUnsafeScope)
+                               Expression.UnsafeError (Location);
+
                        if (!base.Define ())
                                return false;
 
@@ -5927,7 +5924,7 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       EmitContext ec = new EmitContext (this, Parent, Location, null, null, ModFlags);
+                       EmitContext ec = new EmitContext (this, Parent, Location, null, TypeManager.void_type, ModFlags);
                        Constant c = size_expr.ResolveAsConstant (ec, this);
                        if (c == null)
                                return false;
@@ -5962,6 +5959,8 @@ namespace Mono.CSharp {
                        RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
 
                        FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
+
+                       Parent.MemberCache.AddMember (FieldBuilder, this);
                        TypeManager.RegisterFieldBase (FieldBuilder, this);
 
                        return true;
@@ -6023,8 +6022,8 @@ namespace Mono.CSharp {
                        Modifiers.INTERNAL |
                        Modifiers.PRIVATE |
                        Modifiers.STATIC |
-                       Modifiers.VOLATILE |
-                       Modifiers.UNSAFE |
+                       Modifiers.VOLATILE |
+                       Modifiers.UNSAFE |
                        Modifiers.READONLY;
 
                public Field (DeclSpace parent, Expression type, int mod, string name,
@@ -6034,69 +6033,58 @@ namespace Mono.CSharp {
                {
                }
 
+               bool CanBeVolatile ()
+               {
+#if GMCS_SOURCE                        
+                       if (TypeManager.IsGenericParameter (MemberType)) {
+                               GenericConstraints constraints = TypeManager.GetTypeParameterConstraints (MemberType);
+                               if (constraints == null)
+                                       return false;
+
+                               return constraints.IsReferenceType;
+                       }
+#endif                 
+
+                       if (!MemberType.IsValueType)
+                               return true;
+
+                       if (MemberType.IsEnum)
+                               return true;
+
+                       if (MemberType == TypeManager.bool_type || MemberType == TypeManager.char_type ||
+                               MemberType == TypeManager.sbyte_type || MemberType == TypeManager.byte_type ||
+                               MemberType == TypeManager.short_type || MemberType == TypeManager.ushort_type ||
+                               MemberType == TypeManager.int32_type || MemberType == TypeManager.uint32_type ||
+                               MemberType == TypeManager.float_type)
+                               return true;
+
+                       return false;
+               }
+
                public override bool Define ()
                {
                        if (!base.Define ())
                                return false;
 
-                       if (RootContext.WarningLevel > 1){
-                               Type ptype = Parent.TypeBuilder.BaseType;
-
-                               // ptype is only null for System.Object while compiling corlib.
-                               if (ptype != null){
-                                       TypeContainer.FindMembers (
-                                               ptype, MemberTypes.Method,
-                                               BindingFlags.Public |
-                                               BindingFlags.Static | BindingFlags.Instance,
-                                               System.Type.FilterName, Name);
-                               }
-                       }
-
                        if ((ModFlags & Modifiers.VOLATILE) != 0){
-                               if (!MemberType.IsClass){
-                                       Type vt = MemberType;
-                                       
-                                       if (TypeManager.IsEnumType (vt))
-                                               vt = TypeManager.EnumToUnderlying (MemberType);
-
-                                       if (!((vt == TypeManager.bool_type) ||
-                                             (vt == TypeManager.sbyte_type) ||
-                                             (vt == TypeManager.byte_type) ||
-                                             (vt == TypeManager.short_type) ||
-                                             (vt == TypeManager.ushort_type) ||
-                                             (vt == TypeManager.int32_type) ||
-                                             (vt == TypeManager.uint32_type) ||    
-                                             (vt == TypeManager.char_type) ||
-                                             (vt == TypeManager.float_type) ||
-                                             (!vt.IsValueType))){
-                                               Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'",
-                                                       GetSignatureForError (), TypeManager.CSharpName (vt));
-                                               return false;
-                                       }
+                               if (!CanBeVolatile ()) {
+                                       Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'",
+                                               GetSignatureForError (), TypeManager.CSharpName (MemberType));
                                }
 
                                if ((ModFlags & Modifiers.READONLY) != 0){
                                        Report.Error (678, Location, "`{0}': A field cannot be both volatile and readonly",
                                                GetSignatureForError ());
-                                       return false;
                                }
                        }
 
                        FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
 
-                       if (Parent.PartialContainer.Kind == Kind.Struct && 
-                           ((fa & FieldAttributes.Static) == 0) &&
-                           MemberType == Parent.TypeBuilder &&
-                           !TypeManager.IsBuiltinType (MemberType)){
-                               Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name + 
-                                             "' causes a cycle in the structure layout");
-                               return false;
-                       }
-
                        try {
                                FieldBuilder = Parent.TypeBuilder.DefineField (
                                        Name, MemberType, Modifiers.FieldAttr (ModFlags));
 
+                               Parent.MemberCache.AddMember (FieldBuilder, this);
                                TypeManager.RegisterFieldBase (FieldBuilder, this);
                        }
                        catch (ArgumentException) {
@@ -6105,8 +6093,15 @@ namespace Mono.CSharp {
                        }
 
                        if (initializer != null)
-                               Parent.PartialContainer.RegisterFieldForInitialization (this,
-                                       new FieldInitializer (FieldBuilder, initializer, Parent));
+                               ((TypeContainer) Parent).RegisterFieldForInitialization (this,
+                                       new FieldInitializer (FieldBuilder, initializer));
+
+                       if (Parent.PartialContainer.Kind == Kind.Struct && (fa & FieldAttributes.Static) == 0 &&
+                               MemberType == Parent.TypeBuilder && !TypeManager.IsBuiltinType (MemberType) && initializer == null) {
+                               Report.Error (523, Location, "Struct member `{0}' causes a cycle in the structure layout",
+                                       GetSignatureForError ());
+                               return false;
+                       }
 
                        return true;
                }
@@ -6293,7 +6288,7 @@ namespace Mono.CSharp {
 
                virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
                {
-                       System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
+                       throw new NotSupportedException ("You forgot to define special attribute target handling");
                }
 
                // It is not supported for the accessors
@@ -6306,6 +6301,10 @@ namespace Mono.CSharp {
                {
                        EmitMethod (parent);
 
+#if GMCS_SOURCE                        
+                       if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0)
+                               method_data.MethodBuilder.SetCustomAttribute (TypeManager.compiler_generated_attr);
+#endif                 
                        if (OptAttributes != null)
                                OptAttributes.Emit ();
 
@@ -6323,6 +6322,20 @@ namespace Mono.CSharp {
                        method_data.Emit (parent);
                }
 
+               public override bool EnableOverloadChecks (MemberCore overload)
+               {
+                       // This can only happen with indexers and it will
+                       // be catched as indexer difference
+                       if (overload is AbstractPropertyEventMethod)
+                               return true;
+
+                       if (overload is MethodCore) {
+                               caching_flags |= Flags.MethodOverloadsExist;
+                               return true;
+                       }
+                       return false;
+               }
+
                public override bool IsClsComplianceRequired()
                {
                        return false;
@@ -6335,7 +6348,7 @@ namespace Mono.CSharp {
 
                        Type[] param_types = method.ParameterTypes;
 
-                       if (param_types.Length != ParameterTypes.Length)
+                       if (param_types == null || param_types.Length != ParameterTypes.Length)
                                return false;
 
                        for (int i = 0; i < param_types.Length; i++)
@@ -6343,7 +6356,8 @@ namespace Mono.CSharp {
                                        return false;
 
                        Report.SymbolRelatedToPreviousError (method);
-                       Report.Error (111, Location, TypeContainer.Error111, method.GetSignatureForError ());
+                       Report.Error (82, Location, "A member `{0}' is already reserved",
+                               method.GetSignatureForError ());
                        return true;
                }
 
@@ -6363,6 +6377,11 @@ namespace Mono.CSharp {
                        }
                }
 
+               public virtual bool ResolveMembers ()
+               {
+                       return true;
+               }
+
                //
                //   Represents header string for documentation comment.
                //
@@ -6394,6 +6413,12 @@ namespace Mono.CSharp {
 
                        public override MethodBuilder Define (DeclSpace parent)
                        {
+                               if (!CheckForDuplications ())
+                                       return null;
+
+                               if (IsDummy)
+                                       return null;
+                               
                                base.Define (parent);
                                
                                method_data = new MethodData (method, ModFlags, flags, this);
@@ -6462,13 +6487,15 @@ namespace Mono.CSharp {
 
                        protected virtual void DefineParameters ()
                        {
-                               parameters = new Parameters (
-                                       new Parameter[] { new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, Location) },
-                                       new Type[] { method.MemberType });
+                               parameters = Parameters.CreateFullyResolved (
+                                       new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, Location));
                        }
 
                        public override MethodBuilder Define (DeclSpace parent)
                        {
+                               if (!CheckForDuplications ())
+                                       return null;
+                               
                                if (IsDummy)
                                        return null;
 
@@ -6521,7 +6548,7 @@ namespace Mono.CSharp {
                                anonymous_methods = accessor.AnonymousMethods;
 
                                if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
-                                       Report.FeatureIsNotISO1 (Location, "access modifiers on properties");
+                                       Report.FeatureIsNotAvailable (Location, "access modifiers on properties");
                                }
                        }
 
@@ -6529,6 +6556,15 @@ namespace Mono.CSharp {
                                get { return iterator; }
                        }
 
+                       public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+                       {
+                               if (a.IsInternalMethodImplAttribute) {
+                                       method.is_external_implementation = true;
+                               }
+
+                               base.ApplyAttributeBuilder (a, cb);
+                       }
+
                        public override AttributeTargets AttributeTargets {
                                get {
                                        return AttributeTargets.Method;
@@ -6540,7 +6576,7 @@ namespace Mono.CSharp {
                                return method.IsClsComplianceRequired ();
                        }
 
-                       public bool ResolveMembers ()
+                       public override bool ResolveMembers ()
                        {
                                if (yields) {
                                        iterator = Iterator.CreateIterator (this, Parent, null, ModFlags);
@@ -6560,16 +6596,13 @@ namespace Mono.CSharp {
 
                        public virtual MethodBuilder Define (DeclSpace parent)
                        {
-                               if (!method.CheckAbstractAndExtern (block != null))
-                                       return null;
-
                                TypeContainer container = parent.PartialContainer;
 
                                //
                                // Check for custom access modifier
                                //
-                               if (ModFlags == 0) {
-                                       ModFlags = method.ModFlags;
+                               if ((ModFlags & Modifiers.Accessibility) == 0) {
+                                       ModFlags |= method.ModFlags;
                                        flags = method.flags;
                                } else {
                                        if (container.Kind == Kind.Interface)
@@ -6587,6 +6620,7 @@ namespace Mono.CSharp {
                                        flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
                                }
 
+                               CheckAbstractAndExtern (block != null);
                                return null;
                        }
 
@@ -6616,6 +6650,7 @@ namespace Mono.CSharp {
                        
                        void CheckModifiers (int modflags)
                        {
+                               modflags &= Modifiers.Accessibility;
                                int flags = 0;
                                int mflags = method.ModFlags & Modifiers.Accessibility;
 
@@ -6638,10 +6673,12 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       public override bool MarkForDuplicationCheck ()
+                       protected bool CheckForDuplications () 
                        {
-                               caching_flags |= Flags.TestMethodDuplication;
-                               return true;
+                               if ((caching_flags & Flags.MethodOverloadsExist) == 0)
+                                       return true;
+
+                               return Parent.MemberCache.CheckExistingMembersOverloads (this, Name, ParameterInfo);
                        }
                }
 
@@ -6694,7 +6731,8 @@ namespace Mono.CSharp {
                        //
                        // Accessors modifiers check
                        //
-                       if (Get.ModFlags != 0 && Set.ModFlags != 0) {
+                       if ((Get.ModFlags & Modifiers.Accessibility) != 0 &&
+                               (Set.ModFlags & Modifiers.Accessibility) != 0) {
                                Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
                                                GetSignatureForError ());
                                return false;
@@ -6708,7 +6746,12 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       if (MemberType.IsAbstract && MemberType.IsSealed) {
+#if MS_COMPATIBLE
+                       if (MemberType.IsGenericParameter)
+                               return true;
+#endif
+
+                       if ((MemberType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
                                Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
                                return false;
                        }
@@ -6718,20 +6761,17 @@ namespace Mono.CSharp {
 
                bool DefineGet ()
                {
-                       if (Get.IsDummy)
-                               return true;
-
                        GetBuilder = Get.Define (Parent);
-                       return GetBuilder != null;
+                       return (Get.IsDummy) ? true : GetBuilder != null;
                }
 
                bool DefineSet (bool define)
                {
-                       if (!define || Set.IsDummy)
+                       if (!define)
                                return true;
 
                        SetBuilder = Set.Define (Parent);
-                       return SetBuilder != null;
+                       return (Set.IsDummy) ? true : SetBuilder != null;
                }
 
                protected bool DefineAccessors ()
@@ -6872,7 +6912,7 @@ namespace Mono.CSharp {
                        Modifiers.SEALED |
                        Modifiers.OVERRIDE |
                        Modifiers.ABSTRACT |
-                       Modifiers.UNSAFE |
+                       Modifiers.UNSAFE |
                        Modifiers.EXTERN |
                        Modifiers.METHOD_YIELDS |
                        Modifiers.VIRTUAL;
@@ -6880,13 +6920,53 @@ namespace Mono.CSharp {
                const int AllowedInterfaceModifiers =
                        Modifiers.NEW;
 
+               void CreateAutomaticProperty (Block block, Accessor get_block, Accessor set_block)
+               {
+                       // Make the field
+                       Field field = new Field (
+                               Parent, Type,
+                               Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & Modifiers.STATIC),
+                           "<" + Name + ">k__BackingField", null, Location);
+                       ((TypeContainer)Parent).AddField (field);
+
+                       // Make get block
+                       get_block.Block = new ToplevelBlock (block, null, Location);
+                       Return r = new Return (new SimpleName(field.Name, Location), Location);
+                       get_block.Block.AddStatement (r);
+                       get_block.ModFlags |= Modifiers.COMPILER_GENERATED;
+
+                       // Make set block
+                       Parameters parameters = new Parameters (new Parameter (Type, "value", Parameter.Modifier.NONE, null, Location));
+                       set_block.Block = new ToplevelBlock (block, parameters, Location);
+                       Assign a = new Assign (new SimpleName(field.Name, Location), new SimpleName ("value", Location));
+                       set_block.Block.AddStatement (new StatementExpression(a));
+                       set_block.ModFlags |= Modifiers.COMPILER_GENERATED;
+               }
+
                public Property (DeclSpace parent, Expression type, int mod, bool is_iface,
                                 MemberName name, Attributes attrs, Accessor get_block,
                                 Accessor set_block, bool define_set_first)
+                       : this (parent, type, mod, is_iface, name, attrs, get_block, set_block,
+                               define_set_first, null)
+               {
+               }
+               
+               public Property (DeclSpace parent, Expression type, int mod, bool is_iface,
+                                MemberName name, Attributes attrs, Accessor get_block,
+                                Accessor set_block, bool define_set_first, Block current_block)
                        : base (parent, type, mod,
                                is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
                                is_iface, name, attrs, define_set_first)
                {
+                       if (!is_iface && (mod & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
+                               get_block != null && get_block.Block == null &&
+                               set_block != null && set_block.Block == null) {
+                               if (RootContext.Version <= LanguageVersion.ISO_2)
+                                       Report.FeatureIsNotAvailable (Location, "automatically implemented properties");
+                               
+                               CreateAutomaticProperty (current_block, get_block, set_block);
+                       }
+
                        if (get_block == null)
                                Get = new GetMethod (this);
                        else
@@ -6919,13 +6999,18 @@ namespace Mono.CSharp {
                        PropertyBuilder = Parent.TypeBuilder.DefineProperty (
                                MemberName.ToString (), PropertyAttributes.None, MemberType, null);
 
-                       if (!Get.IsDummy)
+                       if (!Get.IsDummy) {
                                PropertyBuilder.SetGetMethod (GetBuilder);
-                               
-                       if (!Set.IsDummy)
+                               Parent.MemberCache.AddMember (GetBuilder, Get);
+                       }
+
+                       if (!Set.IsDummy) {
                                PropertyBuilder.SetSetMethod (SetBuilder);
+                               Parent.MemberCache.AddMember (SetBuilder, Set);
+                       }
                        
                        TypeManager.RegisterProperty (PropertyBuilder, this);
+                       Parent.MemberCache.AddMember (PropertyBuilder, this);
                        return true;
                }
 
@@ -7088,16 +7173,38 @@ namespace Mono.CSharp {
        public class EventProperty: Event {
                abstract class AEventPropertyAccessor : AEventAccessor
                {
+                       readonly ArrayList anonymous_methods;
+
                        public AEventPropertyAccessor (Event method, Accessor accessor, string prefix):
                                base (method, accessor, prefix)
                        {
+                               this.anonymous_methods = accessor.AnonymousMethods;
                        }
 
                        public override MethodBuilder Define (DeclSpace ds)
                        {
-                               method.CheckAbstractAndExtern (block != null);
+                               CheckAbstractAndExtern (block != null);
                                return base.Define (ds);
                        }
+                       
+                       public override string GetSignatureForError ()
+                       {
+                               return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
+                       }
+
+                       public override bool ResolveMembers ()
+                       {
+                               if (anonymous_methods == null)
+                                       return true;
+
+                               foreach (AnonymousMethodExpression ame in anonymous_methods) {
+                                       if (!ame.CreateAnonymousHelpers ())
+                                               return false;
+                               }
+
+                               return true;
+                       }
+
                }
 
                sealed class AddDelegateMethod: AEventPropertyAccessor
@@ -7145,9 +7252,7 @@ namespace Mono.CSharp {
                        if (!base.Define ())
                                return false;
 
-                       if (IsExplicitImpl)
-                               SetMemberIsUsed ();
-
+                       SetMemberIsUsed ();
                        return true;
                }
 
@@ -7174,12 +7279,16 @@ namespace Mono.CSharp {
                                if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
                                        return;
 
-                               ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
+                               MethodBuilder mb = method_data.MethodBuilder;
+                               ILGenerator ig = mb.GetILGenerator ();
 
                                // TODO: because we cannot use generics yet
                                FieldInfo field_info = ((EventField)method).FieldBuilder;
 
-                               method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Synchronized);
+                               if (parent is Class) {
+                                       mb.SetImplementationFlags (mb.GetMethodImplementationFlags () | MethodImplAttributes.Synchronized);
+                               }
+                               
                                if ((method.ModFlags & Modifiers.STATIC) != 0) {
                                        ig.Emit (OpCodes.Ldsfld, field_info);
                                        ig.Emit (OpCodes.Ldarg_0);
@@ -7275,6 +7384,9 @@ namespace Mono.CSharp {
                        if (TypeManager.IsGenericType (MemberType))
                                SetMemberIsUsed();
 
+                       if (Add.IsInterfaceImplementation)
+                               SetMemberIsUsed ();
+
                        FieldBuilder = Parent.TypeBuilder.DefineField (
                                Name, MemberType,
                                FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
@@ -7287,8 +7399,8 @@ namespace Mono.CSharp {
                                        return false;
                                }
 
-                               Parent.PartialContainer.RegisterFieldForInitialization (this,
-                                       new FieldInitializer (FieldBuilder, Initializer, Parent));
+                               ((TypeContainer) Parent).RegisterFieldForInitialization (this,
+                                       new FieldInitializer (FieldBuilder, Initializer));
                        }
 
                        return true;
@@ -7314,18 +7426,33 @@ namespace Mono.CSharp {
                                : base (method, prefix)
                        {
                                this.method = method;
+                               this.ModFlags = method.ModFlags;
                        }
 
                        protected AEventAccessor (Event method, Accessor accessor, string prefix)
                                : base (method, accessor, prefix)
                        {
                                this.method = method;
+                               this.ModFlags = method.ModFlags;
                        }
 
                        public override Iterator Iterator {
                                get { return null; }
                        }
 
+                       public bool IsInterfaceImplementation {
+                               get { return method_data.implementing != null; }
+                       }
+
+                       public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+                       {
+                               if (a.IsInternalMethodImplAttribute) {
+                                       method.is_external_implementation = true;
+                               }
+
+                               base.ApplyAttributeBuilder (a, cb);
+                       }
+
                        protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
                        {
                                if (a.Target == AttributeTargets.Parameter) {
@@ -7462,9 +7589,8 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       parameters = new Parameters (
-                               new Parameter[] { new Parameter (MemberType, "value", Parameter.Modifier.NONE, null, Location) },
-                               new Type[] { MemberType } );
+                       parameters = Parameters.CreateFullyResolved (
+                               new Parameter (MemberType, "value", Parameter.Modifier.NONE, null, Location));
 
                        if (!CheckBase ())
                                return false;
@@ -7484,6 +7610,11 @@ namespace Mono.CSharp {
                        EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, EventAttributes.None, MemberType);                                           
                        EventBuilder.SetAddOnMethod (AddBuilder);
                        EventBuilder.SetRemoveOnMethod (RemoveBuilder);
+
+                       Parent.MemberCache.AddMember (EventBuilder, this);
+                       Parent.MemberCache.AddMember (AddBuilder, Add);
+                       Parent.MemberCache.AddMember (RemoveBuilder, Remove);
+                       
                        return true;
                }
 
@@ -7521,8 +7652,8 @@ namespace Mono.CSharp {
        }
 
  
-       public class Indexer : PropertyBase {
-
+       public class Indexer : PropertyBase
+       {
                class GetIndexerMethod : GetMethod
                {
                        public GetIndexerMethod (PropertyBase method):
@@ -7534,6 +7665,16 @@ namespace Mono.CSharp {
                                base (method, accessor)
                        {
                        }
+                       
+                       public override bool EnableOverloadChecks (MemberCore overload)
+                       {
+                               if (base.EnableOverloadChecks (overload)) {
+                                       overload.caching_flags |= Flags.MethodOverloadsExist;
+                                       return true;
+                               }
+
+                               return false;
+                       }                       
 
                        public override Parameters ParameterInfo {
                                get {
@@ -7559,6 +7700,16 @@ namespace Mono.CSharp {
                                parameters = Parameters.MergeGenerated (((Indexer)method).parameters,
                                        new Parameter (method.MemberType, "value", Parameter.Modifier.NONE, null, method.Location));
                        }
+                       
+                       public override bool EnableOverloadChecks (MemberCore overload)
+                       {
+                               if (base.EnableOverloadChecks (overload)) {
+                                       overload.caching_flags |= Flags.MethodOverloadsExist;
+                                       return true;
+                               }
+
+                               return false;
+                       }                       
                }
 
                const int AllowedModifiers =
@@ -7586,6 +7737,9 @@ namespace Mono.CSharp {
                                is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
                                is_iface, name, attrs, define_set_first)
                {
+                       if (type == TypeManager.system_void_expr)
+                               Report.Error (620, name.Location, "An indexer return type cannot be `void'");
+                       
                        this.parameters = parameters;
 
                        if (get_block == null)
@@ -7599,49 +7753,6 @@ namespace Mono.CSharp {
                                Set = new SetIndexerMethod (this, set_block);
                }
                
-               protected override bool CheckForDuplications ()
-               {
-                       ArrayList ar = Parent.PartialContainer.Indexers;
-                       if (ar != null) {
-                               int arLen = ar.Count;
-                                       
-                               for (int i = 0; i < arLen; i++) {
-                                       Indexer m = (Indexer) ar [i];
-                                       if (IsDuplicateImplementation (m))
-                                               return false;
-                               }
-                       }
-
-                       return true;
-               }
-
-               bool IsDuplicateImplementation (Indexer indexer)
-               {
-                       if (this == indexer)
-                               return false;
-
-                       if (!MemberName.Equals (indexer.MemberName))
-                               return false;
-
-                       Type[] param_types = indexer.parameters.Types;
-
-                       // When it is not yet defined
-                       if (param_types == null)
-                               return false;
-
-                       if (param_types.Length != parameters.Count)
-                               return false;
-
-                       for (int i = 0; i < param_types.Length; i++)
-                               if (param_types [i] != parameters.Types [i])
-                                       return false;
-
-                       Report.SymbolRelatedToPreviousError (indexer);
-                       Report.Error (111, Location, TypeContainer.Error111, indexer.GetSignatureForError ());
-                       return true;
-               }
-
-
                public override bool Define ()
                {
                        if (!DoDefineBase ())
@@ -7650,16 +7761,8 @@ namespace Mono.CSharp {
                        if (!base.Define ())
                                return false;
 
-                       if (!parameters.Resolve (ds))
-                               return false;
-
-                       if (!CheckParameters (parameters))
-                               return false;
-
-                       if (MemberType == TypeManager.void_type) {
-                               Report.Error (620, Location, "Indexers cannot have void type");
+                       if (!DefineParameters (parameters))
                                return false;
-                       }
 
                        if (OptAttributes != null) {
                                Attribute indexer_attr = OptAttributes.Search (TypeManager.indexer_name_type);
@@ -7701,6 +7804,12 @@ namespace Mono.CSharp {
                        if (!CheckBase ())
                                return false;
 
+
+                       if ((caching_flags & Flags.MethodOverloadsExist) != 0) {
+                               if (!Parent.MemberCache.CheckExistingMembersOverloads (this, Name, parameters))
+                                       return false;
+                       }
+
                        flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
                        
                        if (!DefineAccessors ())
@@ -7718,29 +7827,34 @@ namespace Mono.CSharp {
                        //
                        // Now name the parameters
                        //
-                       Parameter [] p = parameters.FixedParameters;
-                       if (p != null) {
-                               // TODO: should be done in parser and it needs to do cycle
-                               if ((p [0].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
-                                       CSharpParser.Error_ParameterModifierNotValid (Location);
-                                       return false;
-                               }
-                       }
-
                        PropertyBuilder = Parent.TypeBuilder.DefineProperty (
                                Name, PropertyAttributes.None, MemberType, parameters.Types);
-                       
-                       if (!Get.IsDummy)
+
+                       if (!Get.IsDummy) {
                                PropertyBuilder.SetGetMethod (GetBuilder);
+                               Parent.MemberCache.AddMember (GetBuilder, Get);
+                       }
 
-                       if (!Set.IsDummy)
+                       if (!Set.IsDummy) {
                                PropertyBuilder.SetSetMethod (SetBuilder);
+                               Parent.MemberCache.AddMember (SetBuilder, Set);
+                       }
                                
                        TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, parameters.Types);
-
+                       Parent.MemberCache.AddMember (PropertyBuilder, this);
                        return true;
                }
 
+               public override bool EnableOverloadChecks (MemberCore overload)
+               {
+                       if (overload is Indexer) {
+                               caching_flags |= Flags.MethodOverloadsExist;
+                               return true;
+                       }
+
+                       return false;
+               }
+
                public override string GetDocCommentName (DeclSpace ds)
                {
                        return DocUtil.GetMethodDocCommentName (this, parameters, ds);
@@ -7759,12 +7873,6 @@ namespace Mono.CSharp {
                        return sb.ToString ();
                }
 
-               public override bool MarkForDuplicationCheck ()
-               {
-                       caching_flags |= Flags.TestMethodDuplication;
-                       return true;
-               }
-
                protected override PropertyInfo ResolveBaseProperty ()
                {
                        return Parent.PartialContainer.BaseCache.FindMemberToOverride (
@@ -7852,33 +7960,6 @@ namespace Mono.CSharp {
                        base.ApplyAttributeBuilder (a, cb);
                }
                
-               protected override bool CheckForDuplications ()
-               {
-                       ArrayList ar = Parent.PartialContainer.Operators;
-                       if (ar != null) {
-                               int arLen = ar.Count;
-                                       
-                               for (int i = 0; i < arLen; i++) {
-                                       Operator o = (Operator) ar [i];
-                                       if (IsDuplicateImplementation (o))
-                                               return false;
-                               }
-                       }
-
-                       ar = Parent.PartialContainer.Methods;
-                       if (ar != null) {
-                               int arLen = ar.Count;
-                                       
-                               for (int i = 0; i < arLen; i++) {
-                                       Method m = (Method) ar [i];
-                                       if (IsDuplicateImplementation (m))
-                                               return false;
-                               }
-                       }
-
-                       return true;
-               }
-
                public override bool Define ()
                {
                        const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
@@ -7887,13 +7968,15 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       // imlicit and explicit operator of same types are not allowed
-                       if (OperatorType == OpType.Explicit || OperatorType == OpType.Implicit)
-                               MarkForDuplicationCheck ();
-
                        if (!base.Define ())
                                return false;
 
+                       // imlicit and explicit operator of same types are not allowed
+                       if (OperatorType == OpType.Explicit)
+                               Parent.MemberCache.CheckExistingMembersOverloads (this, "op_Implicit", Parameters);
+                       else if (OperatorType == OpType.Implicit)
+                               Parent.MemberCache.CheckExistingMembersOverloads (this, "op_Explicit", Parameters);
+
                        if (MemberType == TypeManager.void_type) {
                                Report.Error (590, Location, "User-defined operators cannot return void");
                                return false;
@@ -7902,41 +7985,59 @@ namespace Mono.CSharp {
                        Type declaring_type = MethodData.DeclaringType;
                        Type return_type = MemberType;
                        Type first_arg_type = ParameterTypes [0];
+                       
+                       Type first_arg_type_unwrap = first_arg_type;
+                       if (TypeManager.IsNullableType (first_arg_type))
+                               first_arg_type_unwrap = TypeManager.GetTypeArguments (first_arg_type) [0];
+                       
+                       Type return_type_unwrap = return_type;
+                       if (TypeManager.IsNullableType (return_type))
+                               return_type_unwrap = TypeManager.GetTypeArguments (return_type) [0];                    
 
+                       //
                        // Rules for conversion operators
-                       
+                       //
                        if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
-                               if (first_arg_type == return_type && first_arg_type == declaring_type){
+                               if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type){
                                        Report.Error (555, Location,
                                                "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
                                        return false;
                                }
                                
-                               if ((first_arg_type != declaring_type) && (return_type != declaring_type) &&
-                                   !TypeManager.IsNullableTypeOf (first_arg_type, declaring_type) &&
-                                   !TypeManager.IsNullableTypeOf (return_type, declaring_type)) {
-                                       Report.Error (
-                                               556, Location, 
-                                               "User-defined conversion must convert to or from the " +
-                                               "enclosing type");
+                               Type conv_type;
+                               if (TypeManager.IsEqual (declaring_type, return_type) || declaring_type == return_type_unwrap) {
+                                       conv_type = first_arg_type;
+                               } else if (TypeManager.IsEqual (declaring_type, first_arg_type) || declaring_type == first_arg_type_unwrap) {
+                                       conv_type = return_type;
+                               } else {
+                                       Report.Error (556, Location, 
+                                               "User-defined conversion must convert to or from the enclosing type");
                                        return false;
                                }
 
-                               if (first_arg_type.IsInterface || return_type.IsInterface){
-                                       Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
-                                               GetSignatureForError ());
-                                       return false;
-                               }
-                               
-                               if (first_arg_type.IsSubclassOf (return_type) || return_type.IsSubclassOf (first_arg_type)) {
-                                       if (declaring_type.IsSubclassOf (return_type) || declaring_type.IsSubclassOf (first_arg_type)) {
-                                               Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from base class",
+                               //
+                               // Because IsInterface and IsClass are not supported
+                               //
+                               if (!TypeManager.IsGenericParameter (conv_type)) {
+                                       if (conv_type.IsInterface) {
+                                               Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
                                                        GetSignatureForError ());
                                                return false;
                                        }
-                                       Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from derived class",
-                                               GetSignatureForError ());
-                                       return false;
+
+                                       if (conv_type.IsClass) {
+                                               if (TypeManager.IsSubclassOf (declaring_type, conv_type)) {
+                                                       Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
+                                                               GetSignatureForError ());
+                                                       return false;
+                                               }
+
+                                               if (TypeManager.IsSubclassOf (conv_type, declaring_type)) {
+                                                       Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
+                                                               GetSignatureForError ());
+                                                       return false;
+                                               }
+                                       }
                                }
                        } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
                                if (first_arg_type != declaring_type || ParameterTypes [1] != TypeManager.int32_type) {
@@ -8246,3 +8347,4 @@ namespace Mono.CSharp {
                }
        }
 }
+