**** Merged r36987 from MCS ****
[mono.git] / mcs / gmcs / decl.cs
index 7b2b9be2875e061f1d378f614ba1a6e0ff7a2a84..f3ac24f95594b18fcded3a291f91e515f83e7bb7 100755 (executable)
@@ -7,6 +7,7 @@
 // Licensed under the terms of the GNU GPL
 //
 // (C) 2001 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell, Inc
 //
 // TODO: Move the method verification stuff from the class.cs and interface.cs here
 //
@@ -17,11 +18,12 @@ using System.Collections;
 using System.Globalization;
 using System.Reflection.Emit;
 using System.Reflection;
+using System.Xml;
 
 namespace Mono.CSharp {
 
        public class MemberName {
-               public readonly string Name;
+               public string Name;
                public readonly TypeArguments TypeArguments;
 
                public readonly MemberName Left;
@@ -90,24 +92,11 @@ namespace Mono.CSharp {
                public string GetMethodName ()
                {
                        if (Left != null)
-                               return Left.GetFullName () + "." + Name;
+                               return Left.GetTypeName () + "." + Name;
                        else
                                return Name;
                }
 
-               public string GetFullName ()
-               {
-                       string full_name;
-                       if (TypeArguments != null)
-                               full_name = Name + "<" + TypeArguments + ">";
-                       else
-                               full_name = Name;
-                       if (Left != null)
-                               return Left.GetFullName () + "." + full_name;
-                       else
-                               return full_name;
-               }
-
                public static string MakeName (string name, TypeArguments args)
                {
                        if (args == null)
@@ -175,6 +164,14 @@ namespace Mono.CSharp {
                        }
                }
 
+               public MemberName Clone ()
+               {
+                       if (Left != null)
+                               return new MemberName (Left.Clone (), Name, TypeArguments);
+                       else
+                               return new MemberName (Name, TypeArguments);
+               }
+
                public string Basename {
                        get {
                                if (TypeArguments != null)
@@ -186,6 +183,9 @@ namespace Mono.CSharp {
 
                public override string ToString ()
                {
+                       throw new Exception ("This exception is thrown because someone is miss-using\n" +
+                                            "MemberName.ToString in the compiler.  Please report this bug");
+
                        string full_name;
                        if (TypeArguments != null)
                                full_name = Name + "<" + TypeArguments + ">";
@@ -207,9 +207,14 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Public name
                /// </summary>
-               public string Name;
+               public string Name {
+                       get {
+                               return MemberName.GetName (!(this is GenericMethod) && !(this is Method));
+                       }
+               }
 
-               public readonly MemberName MemberName;
+                // Is not readonly because of IndexerName attribute
+               public MemberName MemberName;
 
                /// <summary>
                ///   Modifier flags that the user specified in the source code
@@ -223,6 +228,17 @@ namespace Mono.CSharp {
                /// </summary>
                public readonly Location Location;
 
+               /// <summary>
+               ///   XML documentation comment
+               /// </summary>
+               public string DocComment;
+
+               /// <summary>
+               ///   Represents header string for documentation comment 
+               ///   for each member types.
+               /// </summary>
+               public abstract string DocCommentHeader { get; }
+
                [Flags]
                public enum Flags {
                        Obsolete_Undetected = 1,                // Obsolete attribute has not been detected yet
@@ -234,21 +250,20 @@ namespace Mono.CSharp {
                        HasClsCompliantAttribute = 1 << 6,                      // Type has CLSCompliantAttribute
                        ClsCompliantAttributeTrue = 1 << 7,                     // Type has CLSCompliant (true)
                        Excluded_Undetected = 1 << 8,           // Conditional attribute has not been detected yet
-                       Excluded = 1 << 9                                       // Method is conditional
-
+                       Excluded = 1 << 9,                                      // Method is conditional
+                       TestMethodDuplication = 1 << 10         // Test for duplication must be performed
                }
   
                /// <summary>
                ///   MemberCore flags at first detected then cached
                /// </summary>
-               protected Flags caching_flags;
+               internal Flags caching_flags;
 
                public MemberCore (TypeContainer parent, MemberName name, Attributes attrs,
                                   Location loc)
                        : base (attrs)
                {
                        Parent = parent;
-                       Name = name.GetName (!(this is GenericMethod) && !(this is Method));
                        MemberName = name;
                        Location = loc;
                        caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected;
@@ -279,6 +294,14 @@ namespace Mono.CSharp {
                        return Name;
                }
 
+               /// <summary>
+               /// Use this method when MethodBuilder is null
+               /// </summary>
+               public virtual string GetSignatureForError (TypeContainer tc)
+               {
+                       return Name;
+               }
+
                /// <summary>
                /// Base Emit method. This is also entry point for CLS-Compliant verification.
                /// </summary>
@@ -292,6 +315,12 @@ namespace Mono.CSharp {
                        VerifyClsCompliance (Parent);
                }
 
+               public bool InUnsafe {
+                       get {
+                               return ((ModFlags & Modifiers.UNSAFE) != 0) || Parent.UnsafeContext;
+                       }
+               }
+
                // 
                // Whehter is it ok to use an unsafe pointer in this type container
                //
@@ -325,11 +354,8 @@ namespace Mono.CSharp {
                        if (OptAttributes == null)
                                return null;
 
-                       // TODO: remove this allocation
-                       EmitContext ec = new EmitContext (ds.Parent, ds, ds.Location,
-                               null, null, ds.ModFlags, false);
-
-                       Attribute obsolete_attr = OptAttributes.Search (TypeManager.obsolete_attribute_type, ec);
+                       Attribute obsolete_attr = OptAttributes.Search (
+                               TypeManager.obsolete_attribute_type, ds.EmitContext);
                        if (obsolete_attr == null)
                                return null;
 
@@ -362,7 +388,7 @@ namespace Mono.CSharp {
                /// <summary>
                /// Returns true when MemberCore is exposed from assembly.
                /// </summary>
-               protected bool IsExposedFromAssembly (DeclSpace ds)
+               public bool IsExposedFromAssembly (DeclSpace ds)
                {
                        if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
                                return false;
@@ -382,9 +408,8 @@ namespace Mono.CSharp {
                bool GetClsCompliantAttributeValue (DeclSpace ds)
                {
                        if (OptAttributes != null) {
-                               EmitContext ec = new EmitContext (ds.Parent, ds, ds.Location,
-                                                                 null, null, ds.ModFlags, false);
-                               Attribute cls_attribute = OptAttributes.GetClsCompliantAttribute (ec);
+                               Attribute cls_attribute = OptAttributes.Search (
+                                       TypeManager.cls_compliant_attribute_type, ds.EmitContext);
                                if (cls_attribute != null) {
                                        caching_flags |= Flags.HasClsCompliantAttribute;
                                        return cls_attribute.GetClsCompliantAttributeValue (ds);
@@ -411,7 +436,7 @@ namespace Mono.CSharp {
                protected virtual bool VerifyClsCompliance (DeclSpace ds)
                {
                        if (!IsClsCompliaceRequired (ds)) {
-                               if (HasClsCompliantAttribute && !IsExposedFromAssembly (ds)) {
+                               if ((RootContext.WarningLevel >= 2) && HasClsCompliantAttribute && !IsExposedFromAssembly (ds)) {
                                        Report.Warning (3019, Location, "CLS compliance checking will not be performed on '{0}' because it is private or internal", GetSignatureForError ());
                                }
                                return false;
@@ -421,6 +446,7 @@ namespace Mono.CSharp {
                                if (HasClsCompliantAttribute) {
                                        Report.Error (3014, Location, "'{0}' cannot be marked as CLS-compliant because the assembly does not have a CLSCompliant attribute", GetSignatureForError ());
                                }
+                               return false;
                        }
 
                        int index = Name.LastIndexOf ('.');
@@ -432,6 +458,34 @@ namespace Mono.CSharp {
 
                protected abstract void VerifyObsoleteAttribute ();
 
+               //
+               // Raised (and passed an XmlElement that contains the comment)
+               // when GenerateDocComment is writing documentation expectedly.
+               //
+               internal virtual void OnGenerateDocComment (DeclSpace ds, XmlElement intermediateNode)
+               {
+               }
+
+               //
+               // Returns a string that represents the signature for this 
+               // member which should be used in XML documentation.
+               //
+               public virtual string GetDocCommentName (DeclSpace ds)
+               {
+                       if (ds == null || this is DeclSpace)
+                               return DocCommentHeader + Name;
+                       else
+                               return String.Concat (DocCommentHeader, ds.Name, ".", Name);
+               }
+
+               //
+               // Generates xml doc comments (if any), and if required,
+               // handle warning report.
+               //
+               internal virtual void GenerateDocComment (DeclSpace ds)
+               {
+                       DocUtil.GenerateDocComment (this, ds);
+               }
        }
 
        /// <summary>
@@ -454,7 +508,7 @@ namespace Mono.CSharp {
                ///   currently defining.  We need to lookup members on this
                ///   instead of the TypeBuilder.
                /// </summary>
-               public TypeExpr CurrentType;
+               public Type CurrentType;
 
                //
                // This is the namespace in which this typecontainer
@@ -466,14 +520,18 @@ namespace Mono.CSharp {
                
                public string Basename;
                
-               /// <summary>
-               ///   defined_names is used for toplevel objects
-               /// </summary>
                protected Hashtable defined_names;
 
                readonly bool is_generic;
                readonly int count_type_params;
 
+               // The emit context for toplevel objects.
+               protected EmitContext ec;
+               
+               public EmitContext EmitContext {
+                       get { return ec; }
+               }
+
                //
                // Whether we are Generic
                //
@@ -505,101 +563,51 @@ namespace Mono.CSharp {
                                count_type_params += parent.count_type_params;
                }
 
-               public void RecordDecl ()
-               {
-                       if ((NamespaceEntry != null) && (Parent == RootContext.Tree.Types))
-                               NamespaceEntry.DefineName (MemberName.Basename, this);
-               }
-
-               /// <summary>
-               ///   The result value from adding an declaration into
-               ///   a struct or a class
-               /// </summary>
-               public enum AdditionResult {
-                       /// <summary>
-                       /// The declaration has been successfully
-                       /// added to the declation space.
-                       /// </summary>
-                       Success,
-
-                       /// <summary>
-                       ///   The symbol has already been defined.
-                       /// </summary>
-                       NameExists,
-
-                       /// <summary>
-                       ///   Returned if the declation being added to the
-                       ///   name space clashes with its container name.
-                       ///
-                       ///   The only exceptions for this are constructors
-                       ///   and static constructors
-                       /// </summary>
-                       EnclosingClash,
-
-                       /// <summary>
-                       ///   Returned if a constructor was created (because syntactically
-                       ///   it looked like a constructor) but was not (because the name
-                       ///   of the method is not the same as the container class
-                       /// </summary>
-                       NotAConstructor,
-
-                       /// <summary>
-                       ///   This is only used by static constructors to emit the
-                       ///   error 111, but this error for other things really
-                       ///   happens at another level for other functions.
-                       /// </summary>
-                       MethodExists,
-
-                       /// <summary>
-                       ///   Some other error.
-                       /// </summary>
-                       Error
-               }
-
                /// <summary>
-               ///   Returns a status code based purely on the name
-               ///   of the member being added
+               /// Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
                /// </summary>
-               protected AdditionResult IsValid (string basename, string name)
+               protected bool AddToContainer (MemberCore symbol, bool is_method, string fullname, string basename)
                {
-                       if (basename == Basename)
-                               return AdditionResult.EnclosingClash;
+                       if (basename == Basename && !(this is Interface)) {
+                               Report.SymbolRelatedToPreviousError (this);
+                               Report.Error (542, "'{0}': member names cannot be the same as their enclosing type", symbol.Location, symbol.GetSignatureForError ());
+                               return false;
+                       }
+
+                       MemberCore mc = (MemberCore)defined_names [fullname];
+
+                       if (is_method && (mc is MethodCore || mc is IMethodData)) {
+                               symbol.caching_flags |= Flags.TestMethodDuplication;
+                               mc.caching_flags |= Flags.TestMethodDuplication;
+                               return true;
+                       }
 
-                       if (defined_names.Contains (name))
-                               return AdditionResult.NameExists;
+                       if (mc != null) {
+                               Report.SymbolRelatedToPreviousError (mc);
+                               Report.Error (102, symbol.Location, "The type '{0}' already contains a definition for '{1}'", GetSignatureForError (), basename);
+                               return false;
+                       }
 
-                       return AdditionResult.Success;
+                       defined_names.Add (fullname, symbol);
+                       return true;
                }
 
-               public static int length;
-               public static int small;
-               
-               /// <summary>
-               ///   Introduce @name into this declaration space and
-               ///   associates it with the object @o.  Note that for
-               ///   methods this will just point to the first method. o
-               /// </summary>
-               public void DefineName (string name, object o)
+               public void RecordDecl ()
                {
-                       defined_names.Add (name, o);
-
-#if DEBUGME
-                       int p = name.LastIndexOf ('.');
-                       int l = name.Length;
-                       length += l;
-                       small += l -p;
-#endif
+                       if ((NamespaceEntry != null) && (Parent == RootContext.Tree.Types))
+                               NamespaceEntry.DefineName (MemberName.Basename, this);
                }
 
                /// <summary>
-               ///   Returns the object associated with a given name in the declaration
-               ///   space.  This is the inverse operation of `DefineName'
+               ///   Returns the MemberCore associated with a given name in the declaration
+               ///   space. It doesn't return method based symbols !!
                /// </summary>
-               public object GetDefinition (string name)
+               /// 
+               public MemberCore GetDefinition (string name)
                {
-                       return defined_names [name];
+                       return (MemberCore)defined_names [name];
                }
-               
+
                bool in_transit = false;
                
                /// <summary>
@@ -703,32 +711,8 @@ namespace Mono.CSharp {
                        return type_resolve_ec;
                }
 
-               // <summary>
-               //    Looks up the type, as parsed into the expression `e' 
-               // </summary>
-               public Type ResolveType (Expression e, bool silent, Location loc)
+               public Type ResolveNestedType (Type t, Location loc)
                {
-                       TypeExpr d = ResolveTypeExpr (e, silent, loc);
-                       if (d == null)
-                               return null;
-
-                       return ResolveType (d, loc);
-               }
-
-               public Type ResolveType (TypeExpr d, Location loc)
-               {
-                       if (!d.CheckAccessLevel (this)) {
-                               Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", d.Name);
-                               return null;
-                       }
-
-                       Type t = d.ResolveType (type_resolve_ec);
-                       if (t == null)
-                               return null;
-
-                       if (d is UnboundTypeExpression)
-                               return t;
-
                        TypeContainer tc = TypeManager.LookupTypeContainer (t);
                        if ((tc != null) && tc.IsGeneric) {
                                if (!IsGeneric) {
@@ -740,10 +724,18 @@ namespace Mono.CSharp {
                                        return null;
                                }
 
-                               ConstructedType ctype = new ConstructedType (
-                                       t, TypeParameters, loc);
+                               TypeParameter[] args;
+                               if (this is GenericMethod)
+                                       args = Parent.TypeParameters;
+                               else
+                                       args = TypeParameters;
+
+                               TypeExpr ctype = new ConstructedType (t, args, loc);
+                               ctype = ctype.ResolveAsTypeTerminal (ec);
+                               if (ctype == null)
+                                       return null;
 
-                               t = ctype.ResolveType (type_resolve_ec);
+                               t = ctype.Type;
                        }
 
                        return t;
@@ -751,9 +743,9 @@ namespace Mono.CSharp {
 
                // <summary>
                //    Resolves the expression `e' for a type, and will recursively define
-               //    types. 
+               //    types.  This should only be used for resolving base types.
                // </summary>
-               public TypeExpr ResolveTypeExpr (Expression e, bool silent, Location loc)
+               public TypeExpr ResolveTypeExpr (Expression e, Location loc)
                {
                        if (type_resolve_ec == null)
                                type_resolve_ec = GetTypeResolveEmitContext (Parent, loc);
@@ -763,50 +755,13 @@ namespace Mono.CSharp {
                        else
                                type_resolve_ec.ContainerType = TypeBuilder;
 
-                       int errors = Report.Errors;
-
-                       TypeExpr d = e.ResolveAsTypeTerminal (type_resolve_ec);
-
-                       if ((d != null) && (d.eclass == ExprClass.Type))
-                               return d;
-
-                       if (silent || (Report.Errors != errors))
-                               return null;
-
-                       if (e is SimpleName){
-                               SimpleName s = new SimpleName (((SimpleName) e).Name, loc);
-                               d = s.ResolveAsTypeTerminal (type_resolve_ec);
-
-                               if ((d == null) || (d.Type == null)) {
-                                       Report.Error (246, loc, "Cannot find type `{0}'", e);
-                                       return null;
-                               }
-
-                               int num_args = TypeManager.GetNumberOfTypeArguments (d.Type);
-
-                               if (num_args == 0) {
-                                       Report.Error (308, loc,
-                                                     "The non-generic type `{0}' cannot " +
-                                                     "be used with type arguments.",
-                                                     TypeManager.CSharpName (d.Type));
-                                       return null;
-                               }
-
-                               Report.Error (305, loc,
-                                             "Using the generic type `{0}' " +
-                                             "requires {1} type arguments",
-                                             TypeManager.GetFullName (d.Type), num_args);
-                               return null;
-                       }
-
-                       Report.Error (246, loc, "Cannot find type `{0}'", e);
-                       return null;
+                       return e.ResolveAsTypeTerminal (type_resolve_ec);
                }
                
                public bool CheckAccessLevel (Type check_type) 
                {
                        TypeBuilder tb;
-                       if (this is GenericMethod)
+                       if ((this is GenericMethod) || (this is Iterator))
                                tb = Parent.TypeBuilder;
                        else
                                tb = TypeBuilder;
@@ -836,10 +791,11 @@ namespace Mono.CSharp {
 
                        case TypeAttributes.NotPublic:
 
-                               // In same cases is null.
                                if (TypeBuilder == null)
+                                       // FIXME: TypeBuilder will be null when invoked by Class.GetNormalBases().
+                                       //        However, this is invoked again later -- so safe to return true.
+                                       //        May also be null when resolving top-level attributes.
                                        return true;
-
                                //
                                // This test should probably use the declaringtype.
                                //
@@ -849,24 +805,7 @@ namespace Mono.CSharp {
                                return true;
 
                        case TypeAttributes.NestedPrivate:
-                               string check_type_name = check_type.FullName;
-                               string type_name = tb.FullName;
-
-                               int cio = check_type_name.LastIndexOf ('+');
-                               string container = check_type_name.Substring (0, cio);
-
-                               //
-                               // Check if the check_type is a nested class of the current type
-                               //
-                               if (check_type_name.StartsWith (type_name + "+")){
-                                       return true;
-                               }
-                               
-                               if (type_name.StartsWith (container)){
-                                       return true;
-                               }
-
-                               return false;
+                               return NestedAccessible (tb, check_type);
 
                        case TypeAttributes.NestedFamily:
                                //
@@ -891,24 +830,31 @@ namespace Mono.CSharp {
 
                }
 
-               protected bool FamilyAccessible (TypeBuilder tb, Type check_type)
+               protected bool NestedAccessible (Type tb, Type check_type)
                {
-                       Type declaring = check_type.DeclaringType;
-                       if (tb.IsSubclassOf (declaring))
-                               return true;
-
                        string check_type_name = check_type.FullName;
                        
+                       // At this point, we already know check_type is a nested class.
                        int cio = check_type_name.LastIndexOf ('+');
-                       string container = check_type_name.Substring (0, cio);
                        
-                       //
-                       // Check if the check_type is a nested class of the current type
-                       //
-                       if (check_type_name.StartsWith (container + "+"))
+                       // Ensure that the string 'container' has a '+' in it to avoid false matches
+                       string container = check_type_name.Substring (0, cio + 1);
+
+                       // Ensure that type_name ends with a '+' so that it can match 'container', if necessary
+                       string type_name = tb.FullName + "+";
+
+                       // If the current class is nested inside the container of check_type,
+                       // we can access check_type even if it is private or protected.
+                       return type_name.StartsWith (container);
+               }
+
+               protected bool FamilyAccessible (Type tb, Type check_type)
+               {
+                       Type declaring = check_type.DeclaringType;
+                       if (tb == declaring || TypeManager.IsFamilyAccessible (tb, declaring))
                                return true;
 
-                       return false;
+                       return NestedAccessible (tb, check_type);
                }
 
                // Access level of a type.
@@ -1146,7 +1092,7 @@ namespace Mono.CSharp {
                                                return null;
 
                                        if ((t != null) && containing_ds.CheckAccessLevel (t))
-                                               return t;
+                                               return ResolveNestedType (t, loc);
 
                                        current_type = current_type.BaseType;
                                }
@@ -1274,9 +1220,7 @@ namespace Mono.CSharp {
                        caching_flags &= ~Flags.HasCompliantAttribute_Undetected;
 
                        if (OptAttributes != null) {
-                               EmitContext ec = new EmitContext (Parent, this, Location,
-                                                                 null, null, ModFlags, false);
-                               Attribute cls_attribute = OptAttributes.GetClsCompliantAttribute (ec);
+                               Attribute cls_attribute = OptAttributes.Search (TypeManager.cls_compliant_attribute_type, ec);
                                if (cls_attribute != null) {
                                        caching_flags |= Flags.HasClsCompliantAttribute;
                                        if (cls_attribute.GetClsCompliantAttributeValue (this)) {
@@ -1374,17 +1318,16 @@ namespace Mono.CSharp {
                        return type_param_list;
                }
 
-               public AdditionResult SetParameterInfo (ArrayList constraints_list)
+               public void SetParameterInfo (ArrayList constraints_list)
                {
                        if (!is_generic) {
                                if (constraints_list != null) {
                                        Report.Error (
                                                80, Location, "Contraints are not allowed " +
                                                "on non-generic declarations");
-                                       return AdditionResult.Error;
                                }
 
-                               return AdditionResult.Success;
+                               return;
                        }
 
                        string[] names = MemberName.TypeArguments.GetDeclarations ();
@@ -1396,11 +1339,6 @@ namespace Mono.CSharp {
                        for (int i = 0; i < type_params.Length; i++) {
                                string name = names [i];
 
-                               AdditionResult res = IsValid (name, name);
-
-                               if (res != AdditionResult.Success)
-                                       return res;
-
                                Constraints constraints = null;
                                if (constraints_list != null) {
                                        foreach (Constraints constraint in constraints_list) {
@@ -1411,12 +1349,11 @@ namespace Mono.CSharp {
                                        }
                                }
 
-                               type_params [i] = new TypeParameter (name, constraints, Location);
+                               type_params [i] = new TypeParameter (Parent, name, constraints, Location);
 
-                               DefineName (name, type_params [i]);
+                               string full_name = Name + "." + name;
+                               AddToContainer (type_params [i], false, full_name, name);
                        }
-
-                       return AdditionResult.Success;
                }
 
                public TypeParameter[] TypeParameters {
@@ -1473,17 +1410,15 @@ namespace Mono.CSharp {
                        get { return Name; }
                }
 
-               TypeExpr IAlias.Type
+               TypeExpr IAlias.ResolveAsType (EmitContext ec)
                {
-                       get {
-                               if (TypeBuilder == null)
-                                       throw new InvalidOperationException ();
-
-                               if (CurrentType != null)
-                                       return CurrentType;
+                       if (TypeBuilder == null)
+                               throw new InvalidOperationException ();
 
+                       if (CurrentType != null)
+                               return new TypeExpression (CurrentType, Location);
+                       else
                                return new TypeExpression (TypeBuilder, Location);
-                       }
                }
 
                public override string[] ValidAttributeTargets {
@@ -1668,7 +1603,7 @@ namespace Mono.CSharp {
                ///   This is used when creating the member cache for a class to get all
                ///   members from the parent class.
                /// </summary>
-               IMemberContainer ParentContainer {
+               MemberCache ParentCache {
                        get;
                }
 
@@ -1719,7 +1654,7 @@ namespace Mono.CSharp {
                public readonly IMemberContainer Container;
                protected Hashtable member_hash;
                protected Hashtable method_hash;
-               
+
                /// <summary>
                ///   Create a new MemberCache for the given IMemberContainer `container'.
                /// </summary>
@@ -1730,20 +1665,10 @@ namespace Mono.CSharp {
                        Timer.IncrementCounter (CounterType.MemberCache);
                        Timer.StartTimer (TimerType.CacheInit);
 
-                       
-
                        // If we have a parent class (we have a parent class unless we're
                        // TypeManager.object_type), we deep-copy its MemberCache here.
-                       if (Container.IsInterface) {
-                               MemberCache parent;
-                               
-                               if (Container.ParentContainer != null)
-                                       parent = Container.ParentContainer.MemberCache;
-                               else
-                                       parent = TypeHandle.ObjectType.MemberCache;
-                               member_hash = SetupCacheForInterface (parent);
-                       } else if (Container.ParentContainer != null)
-                               member_hash = SetupCache (Container.ParentContainer.MemberCache);
+                       if (Container.ParentCache != null)
+                               member_hash = SetupCache (Container.ParentCache);
                        else
                                member_hash = new Hashtable ();
 
@@ -1761,6 +1686,22 @@ namespace Mono.CSharp {
                        Timer.StopTimer (TimerType.CacheInit);
                }
 
+               public MemberCache (Type[] ifaces)
+               {
+                       //
+                       // The members of this cache all belong to other caches.  
+                       // So, 'Container' will not be used.
+                       //
+                       this.Container = null;
+
+                       member_hash = new Hashtable ();
+                       if (ifaces == null)
+                               return;
+
+                       foreach (Type itype in ifaces)
+                               AddCacheContents (TypeManager.LookupMemberCache (itype));
+               }
+
                /// <summary>
                ///   Bootstrap this member cache by doing a deep-copy of our parent.
                /// </summary>
@@ -1768,28 +1709,32 @@ namespace Mono.CSharp {
                {
                        Hashtable hash = new Hashtable ();
 
+                       if (parent == null)
+                               return hash;
+
                        IDictionaryEnumerator it = parent.member_hash.GetEnumerator ();
                        while (it.MoveNext ()) {
                                hash [it.Key] = ((ArrayList) it.Value).Clone ();
-                        }
+                        }
                                 
                        return hash;
                }
 
-
                /// <summary>
-               ///   Add the contents of `new_hash' to `hash'.
+               ///   Add the contents of `cache' to the member_hash.
                /// </summary>
-               void AddHashtable (Hashtable hash, MemberCache cache)
+               void AddCacheContents (MemberCache cache)
                {
-                       Hashtable new_hash = cache.member_hash;
-                       IDictionaryEnumerator it = new_hash.GetEnumerator ();
+                       IDictionaryEnumerator it = cache.member_hash.GetEnumerator ();
                        while (it.MoveNext ()) {
-                               ArrayList list = (ArrayList) hash [it.Key];
+                               ArrayList list = (ArrayList) member_hash [it.Key];
                                if (list == null)
-                                       hash [it.Key] = list = new ArrayList ();
+                                       member_hash [it.Key] = list = new ArrayList ();
+
+                               ArrayList entries = (ArrayList) it.Value;
+                               for (int i = entries.Count-1; i >= 0; i--) {
+                                       CacheEntry entry = (CacheEntry) entries [i];
 
-                               foreach (CacheEntry entry in (ArrayList) it.Value) {
                                        if (entry.Container != cache.Container)
                                                break;
                                        list.Add (entry);
@@ -1797,28 +1742,6 @@ namespace Mono.CSharp {
                        }
                }
 
-               /// <summary>
-               ///   Bootstrap the member cache for an interface type.
-               ///   Type.GetMembers() won't return any inherited members for interface types,
-               ///   so we need to do this manually.  Interfaces also inherit from System.Object.
-               /// </summary>
-               Hashtable SetupCacheForInterface (MemberCache parent)
-               {
-                       Hashtable hash = SetupCache (parent);
-                       Type [] ifaces = TypeManager.GetInterfaces (Container.Type);
-
-                       foreach (Type itype in ifaces) {
-                               IMemberContainer iface_container =
-                                       TypeManager.LookupMemberContainer (itype);
-
-                               MemberCache iface_cache = iface_container.MemberCache;
-
-                               AddHashtable (hash, iface_cache);
-                       }
-
-                       return hash;
-               }
-
                /// <summary>
                ///   Add all members from class `container' to the cache.
                /// </summary>
@@ -1826,8 +1749,10 @@ namespace Mono.CSharp {
                {
                        // We need to call AddMembers() with a single member type at a time
                        // to get the member type part of CacheEntry.EntryType right.
+                       if (!container.IsInterface) {
                        AddMembers (MemberTypes.Constructor, container);
                        AddMembers (MemberTypes.Field, container);
+                       }
                        AddMembers (MemberTypes.Method, container);
                        AddMembers (MemberTypes.Property, container);
                        AddMembers (MemberTypes.Event, container);
@@ -2014,6 +1939,12 @@ namespace Mono.CSharp {
                                this.Member = member;
                                this.EntryType = GetEntryType (mt, bf);
                        }
+
+                       public override string ToString ()
+                       {
+                               return String.Format ("CacheEntry ({0}:{1}:{2})", Container.Name,
+                                                     EntryType, Member);
+                       }
                }
 
                /// <summary>
@@ -2241,7 +2172,7 @@ namespace Mono.CSharp {
                                        continue;
 
                                for (int j = cmpAttrs.Length - 1; j >= 0; j --) {
-                                       if (!paramTypes [j].Equals (cmpAttrs [j]))
+                                       if (!TypeManager.IsEqual (paramTypes [j], cmpAttrs [j]))
                                                goto next;
                                }
                                
@@ -2263,7 +2194,7 @@ namespace Mono.CSharp {
                                        // A private method is Ok if we are a nested subtype.
                                        // The spec actually is not very clear about this, see bug 52458.
                                        //
-                                       if (invocationType == entry.Container.Type ||
+                                       if (invocationType.Equals (entry.Container.Type) ||
                                            TypeManager.IsNestedChildOf (invocationType, entry.Container.Type))
                                                return entry.Member;
                                        
@@ -2327,7 +2258,7 @@ namespace Mono.CSharp {
                                                        // Does exist easier way how to detect indexer ?
                                                        if ((entry.EntryType & EntryType.Property) != 0) {
                                                                Type[] arg_types = TypeManager.GetArgumentTypes ((PropertyInfo)entry.Member);
-                                                               if (arg_types.Length == 1)
+                                                               if (arg_types.Length > 0)
                                                                        continue;
                                                        }
                                                }