2007-12-06 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / mcs / class.cs
index 25dcf72ce063ce4ea6dba2255abeb2a207a9edc7..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;
@@ -247,7 +246,7 @@ namespace Mono.CSharp {
                                                oe.op.GetSignatureForError (), s);
                                }
 
-                               if (has_equality_or_inequality && (RootContext.WarningLevel > 2)) {
+                               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 ());
  
@@ -264,9 +263,11 @@ namespace Mono.CSharp {
                }
 
                [Flags]
-               enum CachedMethods {
-                       Equals                  = 1,
-                       GetHashCode             = 1 << 1
+               enum CachedMethods
+               {
+                       Equals                          = 1,
+                       GetHashCode                     = 1 << 1,
+                       HasStaticFieldInitializer       = 1 << 2
                }
 
 
@@ -298,7 +299,7 @@ namespace Mono.CSharp {
                protected ArrayList initialized_static_fields;
 
                // Holds the list of constants
-               MemberCoreArrayList constants;
+               protected MemberCoreArrayList constants;
 
                // Holds the methods.
                MemberCoreArrayList methods;
@@ -349,7 +350,7 @@ 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";
 
@@ -430,7 +431,6 @@ namespace Mono.CSharp {
                        if ((tc.ModFlags & Modifiers.PARTIAL) == 0) {
                                Report.SymbolRelatedToPreviousError (tc);
                                Error_MissingPartialModifier (next_part);
-                               return tc;
                        }
 
                        if (tc.Kind != next_part.Kind) {
@@ -438,7 +438,6 @@ namespace Mono.CSharp {
                                Report.Error (261, next_part.Location,
                                        "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
                                        next_part.GetSignatureForError ());
-                               return tc;
                        }
 
                        if ((tc.ModFlags & Modifiers.Accessibility) != (next_part.ModFlags & Modifiers.Accessibility) &&
@@ -448,7 +447,6 @@ namespace Mono.CSharp {
                                Report.Error (262, next_part.Location,
                                        "Partial declarations of `{0}' have conflicting accessibility modifiers",
                                        next_part.GetSignatureForError ());
-                               return tc;
                        }
 
                        if (tc.MemberName.IsGeneric) {
@@ -462,14 +460,21 @@ 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 |= next_part.ModFlags;
+                       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 = next_part.attributes;
@@ -513,9 +518,10 @@ namespace Mono.CSharp {
                
                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 MemberCoreArrayList ();
 
@@ -548,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 ();
@@ -574,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 ();
@@ -591,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)
@@ -801,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 {
@@ -813,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){
@@ -859,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' 
@@ -1511,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) {
@@ -1553,13 +1646,15 @@ namespace Mono.CSharp {
                                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;
                }
@@ -1814,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)
                {
@@ -2177,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 ());
                                }
                        }
@@ -2188,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");
@@ -2216,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)
@@ -2279,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
 
@@ -2638,6 +2737,18 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool HasStaticFieldInitializer {
+                       get {
+                               return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
+                       }
+                       set {
+                               if (value)
+                                       cached_method |= CachedMethods.HasStaticFieldInitializer;
+                               else
+                                       cached_method &= ~CachedMethods.HasStaticFieldInitializer;
+                       }
+               }
+
                //
                // IMemberContainer
                //
@@ -2654,12 +2765,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               MemberCache IMemberContainer.MemberCache {
-                       get {
-                               return member_cache;
-                       }
-               }
-
                bool IMemberContainer.IsInterface {
                        get {
                                return Kind == Kind.Interface;
@@ -2690,7 +2795,7 @@ namespace Mono.CSharp {
                        get { return "T:"; }
                }
 
-               public virtual MemberCache BaseCache {
+               public MemberCache BaseCache {
                        get {
                                if (base_cache != null)
                                        return base_cache;
@@ -2701,15 +2806,6 @@ namespace Mono.CSharp {
                                return base_cache;
                        }
                }
-               
-               private IDictionary anonymous_types;
-               public IDictionary AnonymousTypes {
-                       get {
-                               if (anonymous_types == null)
-                                       anonymous_types = new HybridDictionary();
-                               return anonymous_types;
-                       }
-               }
        }
 
        public abstract class ClassOrStruct : TypeContainer {
@@ -2744,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 ());
                                }
@@ -2797,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 ();
@@ -2912,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) {
@@ -3084,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;
@@ -3094,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 ());
                                }
                        }
 
@@ -3318,11 +3367,6 @@ namespace Mono.CSharp {
                {
                }
 
-               protected override bool CheckForDuplications ()
-               {
-                       throw new NotSupportedException ();
-               }
-
                protected override bool VerifyClsCompliance ()
                {
                        if (!base.VerifyClsCompliance ())
@@ -3383,89 +3427,23 @@ namespace Mono.CSharp {
                        if (!DefineParameters (Parameters))
                                return false;
 
-                       if (!base.CheckBase ())
-                               return false;
-
-                       return true;
-               }
-
-               // TODO: create a special method for operators only to make code better
-               protected bool IsDuplicateImplementation (MethodCore method)
-               {
-                       if (method == this)
-                               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;
                }
 
                //
@@ -3497,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;
@@ -3564,9 +3552,6 @@ namespace Mono.CSharp {
                        if (!base.CheckBase ())
                                return false;
                        
-                       if ((caching_flags & Flags.TestMethodDuplication) != 0 && !CheckForDuplications ())
-                               return false;
-
                        if (IsExplicitImpl)
                                return true;
 
@@ -3622,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;
@@ -3721,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"
@@ -3847,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) {
@@ -3896,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>
@@ -3991,7 +3974,8 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       MethodBuilder.SetCustomAttribute (cb);
+                       if (MethodBuilder != null)
+                               MethodBuilder.SetCustomAttribute (cb);
                }
 
                public override AttributeTargets AttributeTargets {
@@ -4028,7 +4012,7 @@ namespace Mono.CSharp {
                                }
 
 #if MS_COMPATIBLE
-                               MethodBuilder = Parent.TypeBuilder.DefineMethod (method_name, flags, ReturnType, null);
+                               MethodBuilder = Parent.TypeBuilder.DefineMethod (method_name, flags); //, ReturnType, null);
 #else
                                MethodBuilder = Parent.TypeBuilder.DefineMethod (method_name, flags);
 #endif
@@ -4070,17 +4054,47 @@ 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 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));
@@ -4116,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 {
@@ -4214,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;
@@ -4414,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];
@@ -4445,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;
                }
 
@@ -4543,18 +4543,50 @@ 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 static void Error1599 (Location loc, Type t)
+               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)
                {
                        Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
                }
@@ -4574,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 ())
@@ -4589,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)
                {
@@ -4606,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));
@@ -4642,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);
                }
        }
 
@@ -4725,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.
@@ -4738,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.
@@ -4765,6 +4788,9 @@ namespace Mono.CSharp {
                        get { return AttributeTargets.Constructor; }
                }
 
+               public Iterator Iterator {
+                       get { return null; }
+               }
 
                //
                // Returns true if this is a default constructor
@@ -4815,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) {
@@ -4847,8 +4858,9 @@ namespace Mono.CSharp {
                        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) {
@@ -4863,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 ());
                        }
                        
@@ -4922,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;
                }
@@ -4935,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.
@@ -4952,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;
                        }
@@ -4969,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);
@@ -5045,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)) {
@@ -5097,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()
@@ -5239,12 +5256,11 @@ namespace Mono.CSharp {
                                        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) {
@@ -5335,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)
@@ -5378,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;
                        }
@@ -5553,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")) {
@@ -5880,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;
                }
@@ -5895,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;
 
@@ -5907,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;
@@ -5942,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;
@@ -6014,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) {
@@ -6085,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;
                }
@@ -6273,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
@@ -6307,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;
@@ -6327,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;
                }
 
@@ -6457,9 +6487,8 @@ 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)
@@ -6519,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");
                                }
                        }
 
@@ -6644,29 +6673,12 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       public override bool MarkForDuplicationCheck ()
-                       {
-                               caching_flags |= Flags.TestMethodDuplication;
-                               return true;
-                       }
-
                        protected bool CheckForDuplications () 
                        {
-                               if ((caching_flags & Flags.TestMethodDuplication) == 0)
+                               if ((caching_flags & Flags.MethodOverloadsExist) == 0)
                                        return true;
-                               
-                               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;
-                                       }
-                               }
 
-                               return true;
+                               return Parent.MemberCache.CheckExistingMembersOverloads (this, Name, ParameterInfo);
                        }
                }
 
@@ -6734,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;
                        }
@@ -6895,7 +6912,7 @@ namespace Mono.CSharp {
                        Modifiers.SEALED |
                        Modifiers.OVERRIDE |
                        Modifiers.ABSTRACT |
-                       Modifiers.UNSAFE |
+                       Modifiers.UNSAFE |
                        Modifiers.EXTERN |
                        Modifiers.METHOD_YIELDS |
                        Modifiers.VIRTUAL;
@@ -6909,8 +6926,7 @@ namespace Mono.CSharp {
                        Field field = new Field (
                                Parent, Type,
                                Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & Modifiers.STATIC),
-                               CompilerGeneratedClass.MakeName ("CompilerGeneratedField"),
-                               null, Location);
+                           "<" + Name + ">k__BackingField", null, Location);
                        ((TypeContainer)Parent).AddField (field);
 
                        // Make get block
@@ -6942,12 +6958,14 @@ namespace Mono.CSharp {
                                is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
                                is_iface, name, attrs, define_set_first)
                {
-                       if (RootContext.Version >= LanguageVersion.LINQ &&
-                               !is_iface &&
-                               (mod & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
+                       if (!is_iface && (mod & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
                                get_block != null && get_block.Block == null &&
-                               set_block != null && set_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);
@@ -6981,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;
                }
 
@@ -7229,9 +7252,7 @@ namespace Mono.CSharp {
                        if (!base.Define ())
                                return false;
 
-                       if (IsExplicitImpl)
-                               SetMemberIsUsed ();
-
+                       SetMemberIsUsed ();
                        return true;
                }
 
@@ -7264,7 +7285,10 @@ namespace Mono.CSharp {
                                // TODO: because we cannot use generics yet
                                FieldInfo field_info = ((EventField)method).FieldBuilder;
 
-                               mb.SetImplementationFlags (mb.GetMethodImplementationFlags () | 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);
@@ -7360,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));
@@ -7372,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;
@@ -7413,6 +7440,10 @@ namespace Mono.CSharp {
                                get { return null; }
                        }
 
+                       public bool IsInterfaceImplementation {
+                               get { return method_data.implementing != null; }
+                       }
+
                        public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
                        {
                                if (a.IsInternalMethodImplAttribute) {
@@ -7558,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;
@@ -7580,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;
                }
 
@@ -7617,8 +7652,8 @@ namespace Mono.CSharp {
        }
 
  
-       public class Indexer : PropertyBase {
-
+       public class Indexer : PropertyBase
+       {
                class GetIndexerMethod : GetMethod
                {
                        public GetIndexerMethod (PropertyBase method):
@@ -7630,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 {
@@ -7655,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 =
@@ -7698,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 ())
@@ -7792,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 ())
@@ -7809,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);
@@ -7850,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 (
@@ -7943,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;
@@ -7978,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;
@@ -7993,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) {