2007-12-06 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / mcs / class.cs
index 0b6d4f8ddce49d8a57dfc1030bde10e9481fc292..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;
@@ -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";
 
@@ -517,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 ();
 
@@ -552,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 ();
@@ -578,12 +579,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               internal static string Error111 {
-                       get {
-                               return "`{0}' is already defined. Rename this member or use different parameter types";
-                       }
-               }
-
                public bool AddField (FieldBase field)
                {
                        if (!AddMember (field))
@@ -804,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 {
@@ -1585,6 +1582,28 @@ 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) {
@@ -1627,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;
                }
@@ -1888,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)
                {
@@ -2251,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 ());
                                }
                        }
@@ -2712,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
                //
@@ -2728,12 +2765,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               MemberCache IMemberContainer.MemberCache {
-                       get {
-                               return member_cache;
-                       }
-               }
-
                bool IMemberContainer.IsInterface {
                        get {
                                return Kind == Kind.Interface;
@@ -2764,7 +2795,7 @@ namespace Mono.CSharp {
                        get { return "T:"; }
                }
 
-               public virtual MemberCache BaseCache {
+               public MemberCache BaseCache {
                        get {
                                if (base_cache != null)
                                        return base_cache;
@@ -2811,9 +2842,8 @@ namespace Mono.CSharp {
 
                        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 ());
                                }
@@ -2864,7 +2894,7 @@ namespace Mono.CSharp {
 
                public override bool Define ()
                {
-                       if (initialized_static_fields != null && default_static_constructor == null)
+                       if (default_static_constructor == null && PartialContainer.HasStaticFieldInitializer)
                                DefineDefaultConstructor (true);
 
                        if (default_static_constructor != null)
@@ -2923,7 +2953,7 @@ 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");
                        }
                }
 
@@ -3103,7 +3133,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (IsStatic) {
+                       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 ());
@@ -3113,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 ());
                                }
                        }
 
@@ -3337,11 +3367,6 @@ namespace Mono.CSharp {
                {
                }
 
-               protected override bool CheckForDuplications ()
-               {
-                       throw new NotSupportedException ();
-               }
-
                protected override bool VerifyClsCompliance ()
                {
                        if (!base.VerifyClsCompliance ())
@@ -3402,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))
+                       if ((caching_flags & Flags.MethodOverloadsExist) != 0) {
+                               if (!Parent.MemberCache.CheckExistingMembersOverloads (this,
+                                       MemberName.IsGeneric ? MemberName.Basename : MemberName.MethodName, Parameters))
                                        return false;
 
-                               op2 = method as Operator;
-                               if (op2 == null || !(op2.OperatorType == Operator.OpType.Explicit || op2.OperatorType == Operator.OpType.Implicit))
-                                       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;
                }
 
                //
@@ -3516,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;
@@ -3583,9 +3552,6 @@ namespace Mono.CSharp {
                        if (!base.CheckBase ())
                                return false;
                        
-                       if ((caching_flags & Flags.TestMethodDuplication) != 0 && !CheckForDuplications ())
-                               return false;
-
                        if (IsExplicitImpl)
                                return true;
 
@@ -3740,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"
@@ -3866,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) {
@@ -3915,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>
@@ -4010,7 +3974,8 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       MethodBuilder.SetCustomAttribute (cb);
+                       if (MethodBuilder != null)
+                               MethodBuilder.SetCustomAttribute (cb);
                }
 
                public override AttributeTargets AttributeTargets {
@@ -4089,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));
@@ -4135,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 {
@@ -4233,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;
@@ -4433,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];
@@ -4464,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;
                }
 
@@ -4564,6 +4545,20 @@ namespace Mono.CSharp {
                {
                        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 ();
+
+                                       return;
+                               }
+
+                               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 ();
                                
@@ -4573,12 +4568,24 @@ namespace Mono.CSharp {
                                Block = null;
                                MethodData = null;
                        } catch {
-                               Console.WriteLine ("Interna compiler error at {0}: exception caught while emitting {1}",
+                               Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}",
                                                   Location, MethodBuilder);
                                throw;
                        }
                }
 
+               public override bool EnableOverloadChecks (MemberCore overload)
+               {
+                       // TODO: It can be deleted when members will be defined in correct order
+                       if (overload is Operator)
+                               return overload.EnableOverloadChecks (this);
+
+                       if (overload is Indexer)
+                               return false;
+
+                       return base.EnableOverloadChecks (overload);
+               }
+
                public static void Error1599 (Location loc, Type t)
                {
                        Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
@@ -4599,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 ())
@@ -4670,13 +4691,13 @@ namespace Mono.CSharp {
                        
                        if (base_constructor_group == null)
                                return false;
-
+                       
                        base_constructor_group = base_constructor_group.OverloadResolve (
                                ec, argument_list, false, loc);
                        
                        if (base_constructor_group == null)
                                return false;
-
+                       
                        ConstructorInfo base_ctor = (ConstructorInfo)base_constructor_group;
                        
                        if (base_ctor == caller_builder){
@@ -4820,21 +4841,6 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               protected override bool CheckForDuplications ()
-               {
-                       ArrayList ar = Parent.PartialContainer.InstanceConstructors;
-                       if (ar != null) {
-                               int arLen = ar.Count;
-                                       
-                               for (int i = 0; i < arLen; i++) {
-                                       Constructor m = (Constructor) ar [i];
-                                       if (IsDuplicateImplementation (m))
-                                               return false;
-                               }
-                       }
-                       return true;
-               }
-
                protected override bool CheckBase ()
                {
                        if ((ModFlags & Modifiers.STATIC) != 0) {
@@ -4852,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) {
@@ -4927,7 +4934,14 @@ namespace Mono.CSharp {
                                ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
                        }
                        
+                       Parent.MemberCache.AddMember (ConstructorBuilder, this);
                        TypeManager.AddMethod (ConstructorBuilder, this);
+                       
+                       // It's here only to report an error
+                       if ((ModFlags & Modifiers.METHOD_YIELDS) != 0) {
+                               member_type = TypeManager.void_type;
+                               Iterator.CreateIterator (this, Parent, null, ModFlags);
+                       }
 
                        return true;
                }
@@ -5046,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)) {
@@ -5242,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) {
@@ -5882,10 +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");
-
-                       if ((mod & Modifiers.VOLATILE) != 0)
-                               Modifiers.Error_InvalidModifier (loc, Modifiers.Name (Modifiers.VOLATILE));
+                               Report.FeatureIsNotAvailable (loc, "fixed size buffers");
 
                        this.size_expr = size_expr;
                }
@@ -5949,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;
@@ -6021,56 +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 ((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) {
@@ -6081,6 +6095,14 @@ namespace Mono.CSharp {
                        if (initializer != null)
                                ((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;
                }
 
@@ -6300,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;
@@ -6320,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;
                }
 
@@ -6511,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");
                                }
                        }
 
@@ -6636,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);
                        }
                }
 
@@ -6892,7 +6912,7 @@ namespace Mono.CSharp {
                        Modifiers.SEALED |
                        Modifiers.OVERRIDE |
                        Modifiers.ABSTRACT |
-                       Modifiers.UNSAFE |
+                       Modifiers.UNSAFE |
                        Modifiers.EXTERN |
                        Modifiers.METHOD_YIELDS |
                        Modifiers.VIRTUAL;
@@ -6906,8 +6926,7 @@ namespace Mono.CSharp {
                        Field field = new Field (
                                Parent, Type,
                                Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & Modifiers.STATIC),
-                               CompilerGeneratedClass.MakeName (null, "CompilerGeneratedField"),
-                               null, Location);
+                           "<" + Name + ">k__BackingField", null, Location);
                        ((TypeContainer)Parent).AddField (field);
 
                        // Make get block
@@ -6939,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);
@@ -6978,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;
                }
 
@@ -7226,9 +7252,7 @@ namespace Mono.CSharp {
                        if (!base.Define ())
                                return false;
 
-                       if (IsExplicitImpl)
-                               SetMemberIsUsed ();
-
+                       SetMemberIsUsed ();
                        return true;
                }
 
@@ -7261,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);
@@ -7357,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));
@@ -7410,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) {
@@ -7576,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;
                }
 
@@ -7613,8 +7652,8 @@ namespace Mono.CSharp {
        }
 
  
-       public class Indexer : PropertyBase {
-
+       public class Indexer : PropertyBase
+       {
                class GetIndexerMethod : GetMethod
                {
                        public GetIndexerMethod (PropertyBase method):
@@ -7626,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 {
@@ -7651,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 =
@@ -7694,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 ())
@@ -7788,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 ())
@@ -7805,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);
@@ -7846,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 (
@@ -7939,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;
@@ -7974,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;
@@ -7989,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) {