+2004-10-24 Marek Safar <marek.safar@seznam.cz>
+
+ Fixed bugs #63705, #67130
+ * decl.cs (MemberCache.MemberCache): Add parameter to distinguish
+ imported and defined interfaces.
+ (CacheEntry, EntryType): Changed to protected internal.
+
+ * class.cs (TypeContainer.DoDefineMembers): Setup cache for
+ interfaces too.
+
+ * typemanager.cs (LookupInterfaceContainer): New method.
+ Fills member container from base interfaces.
+
2004-10-20 Marek Safar <marek.safar@seznam.cz>
* class.cs (MethodCore.CheckBase): Add errors 505, 533, 544,
if (TypeBuilder.BaseType != null)
parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
- // TODO:
- //if (TypeBuilder.IsInterface) {
- // parent_container = TypeManager.LookupInterfaceContainer (base_inteface_types);
- //}
+ if (TypeBuilder.IsInterface)
+ parent_container = TypeManager.LookupInterfaceContainer (base_inteface_types);
if (IsTopLevel) {
if ((ModFlags & Modifiers.NEW) != 0)
#if CACHE
if (!(this is ClassPart))
- member_cache = new MemberCache (this);
+ member_cache = new MemberCache (this, false);
#endif
if (parts != null) {
return false;
}
} else {
- if (parent_method.IsAbstract) {
+ if (parent_method.IsAbstract && !IsInterface) {
Report.SymbolRelatedToPreviousError (parent_method);
Report.Error (533, Location, "'{0}' hides inherited abstract member", GetSignatureForError (Parent));
return false;
/// </summary>
protected bool AddToContainer (MemberCore symbol, bool is_method, string fullname, string basename)
{
- if (basename == Basename) {
+ 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;
/// <summary>
/// Create a new MemberCache for the given IMemberContainer `container'.
/// </summary>
- public MemberCache (IMemberContainer container)
+ public MemberCache (IMemberContainer container, bool setup_inherited_interfaces)
{
this.Container = container;
if (Container.ParentContainer != null)
parent = Container.ParentContainer.MemberCache;
else
- parent = TypeHandle.ObjectType.MemberCache;
- member_hash = SetupCacheForInterface (parent);
+ parent = null;
+ member_hash = SetupCacheForInterface (parent, setup_inherited_interfaces);
} else if (Container.ParentContainer != null)
member_hash = SetupCache (Container.ParentContainer.MemberCache);
else
Hashtable SetupCache (MemberCache parent)
{
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;
}
/// 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 SetupCacheForInterface (MemberCache parent, bool deep_setup)
{
Hashtable hash = SetupCache (parent);
+
+ if (!deep_setup)
+ return hash;
+
TypeExpr [] ifaces = TypeManager.GetInterfaces (Container.Type);
foreach (TypeExpr iface in ifaces) {
{
// We need to call AddMembers() with a single member type at a time
// to get the member type part of CacheEntry.EntryType right.
- AddMembers (MemberTypes.Constructor, container);
- AddMembers (MemberTypes.Field, container);
+ if (!container.IsInterface) {
+ AddMembers (MemberTypes.Constructor, container);
+ AddMembers (MemberTypes.Field, container);
+ }
AddMembers (MemberTypes.Method, container);
AddMembers (MemberTypes.Property, container);
AddMembers (MemberTypes.Event, container);
/// number to speed up the searching process.
/// </summary>
[Flags]
- protected enum EntryType {
+ protected internal enum EntryType {
None = 0x000,
Instance = 0x001,
MaskType = Constructor|Event|Field|Method|Property|NestedType
}
- protected struct CacheEntry {
+ protected internal struct CacheEntry {
public readonly IMemberContainer Container;
public readonly EntryType EntryType;
public readonly MemberInfo Member;
return builder_to_declspace [t] as TypeContainer;
}
+ /// <summary>
+ /// Fills member container from base interfaces
+ /// </summary>
+ public static IMemberContainer LookupInterfaceContainer (Type[] types)
+ {
+ if (types == null)
+ return null;
+
+ IMemberContainer complete = null;
+ foreach (Type t in types) {
+ IMemberContainer one_type_cont = null;
+ if (t is TypeBuilder) {
+ one_type_cont = builder_to_declspace [t] as IMemberContainer;
+ } else
+ one_type_cont = TypeHandle.GetTypeHandle (t);
+
+ if (complete == null) {
+ complete = one_type_cont;
+ continue;
+ }
+
+ // We need to avoid including same member more than once
+ foreach (DictionaryEntry de in one_type_cont.MemberCache.Members) {
+ object o = complete.MemberCache.Members [de.Key];
+ if (o == null) {
+ complete.MemberCache.Members.Add (de.Key, de.Value);
+ continue;
+ }
+
+ ArrayList al_old = (ArrayList)o;
+ ArrayList al_new = (ArrayList)de.Value;
+
+ foreach (MemberCache.CacheEntry ce in al_new) {
+ bool exist = false;
+ foreach (MemberCache.CacheEntry ce_old in al_old) {
+ if (ce.Member == ce_old.Member) {
+ exist = true;
+ break;
+ }
+ }
+ if (!exist)
+ al_old.Add (ce);
+ }
+ }
+ }
+ return complete;
+ }
+
public static IMemberContainer LookupMemberContainer (Type t)
{
if (t is TypeBuilder) {
// This happens with interfaces, they have a null
// basetype. Look members up in the Object class.
//
- if (current_type == null)
+ if (current_type == null) {
current_type = TypeManager.object_type;
+ searching = true;
+ }
}
if (list.Length == 0)
if (type.BaseType != null)
BaseType = GetTypeHandle (type.BaseType);
this.is_interface = type.IsInterface;
- this.member_cache = new MemberCache (this);
+ this.member_cache = new MemberCache (this, true);
}
// IMemberContainer methods