This is based on a patch from Marek Safar, see bug #69082.
Fixes bugs #63705 and #67130.
* typemanager.cs (TypeManager.LookupInterfaceCache): New public
method; create a MemberCache for an interface type and cache the
result.
* decl.cs (IMemberContainer.ParentContainer): Removed.
(IMemberContainer.ParentCache): New property.
(MemberCache.SetupCacheForInterface): Removed.
(MemberCache..ctor): Added .ctor which takes a `Type[]'; use this
to create a cache for an interface's "parent".
* class.cs (TypeContainer.DoDefineMembers): Setup cache for
interfaces too.
svn path=/trunk/mcs/; revision=36157
+2004-11-16 Martin Baulig <martin@ximian.com>
+
+ This is based on a patch from Marek Safar, see bug #69082.
+ Fixes bugs #63705 and #67130.
+
+ * typemanager.cs (TypeManager.LookupInterfaceCache): New public
+ method; create a MemberCache for an interface type and cache the
+ result.
+
+ * decl.cs (IMemberContainer.ParentContainer): Removed.
+ (IMemberContainer.ParentCache): New property.
+ (MemberCache.SetupCacheForInterface): Removed.
+ (MemberCache..ctor): Added .ctor which takes a `Type[]'; use this
+ to create a cache for an interface's "parent".
+
+ * class.cs (TypeContainer.DoDefineMembers): Setup cache for
+ interfaces too.
+
2004-11-15 Martin Baulig <martin@ximian.com>
* decl.cs (MemberName.GetPartialName): Removed, use GetTypeName() instead.
// The parent member container and our member cache
IMemberContainer parent_container;
+ MemberCache parent_cache;
MemberCache member_cache;
public const string DefaultIndexerName = "Item";
//
// We need to be able to use the member cache while we are checking/defining
//
- if (TypeBuilder.BaseType != null)
+ if (TypeBuilder.BaseType != null) {
parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
+ parent_cache = parent_container.MemberCache;
+ }
- // TODO:
- //if (TypeBuilder.IsInterface) {
- // parent_container = TypeManager.LookupInterfaceContainer (base_inteface_types);
- //}
+ if (TypeBuilder.IsInterface)
+ parent_cache = TypeManager.LookupInterfaceCache (this, TypeBuilder);
if (IsTopLevel) {
if ((ModFlags & Modifiers.NEW) != 0)
public MemberInfo FindMemberWithSameName (string name, bool ignore_methods)
{
- return ParentContainer.MemberCache.FindMemberWithSameName (name, ignore_methods, null);
+ return ParentCache.FindMemberWithSameName (name, ignore_methods, null);
}
/// <summary>
type_bases = null;
OptAttributes = null;
ifaces = null;
- parent_container = null;
+ parent_cache = null;
member_cache = null;
}
/// </summary>
void VerifyClsName ()
{
- Hashtable parent_members = parent_container == null ?
+ Hashtable parent_members = parent_cache == null ?
new Hashtable () :
- parent_container.MemberCache.GetPublicMembers ();
+ parent_cache.GetPublicMembers ();
Hashtable this_members = new Hashtable ();
foreach (DictionaryEntry entry in defined_names) {
return FindMembers (mt, new_bf, null, null);
}
- public virtual IMemberContainer ParentContainer {
+ public virtual MemberCache ParentCache {
get {
- return parent_container;
+ return parent_cache;
}
}
interface_type, full, name, loc);
}
- public override IMemberContainer ParentContainer {
+ public override MemberCache ParentCache {
get {
- return PartialContainer.ParentContainer;
+ return PartialContainer.ParentCache;
}
}
}
return true;
// Is null for System.Object while compiling corlib and base interfaces
- if (Parent.ParentContainer == null) {
+ if (Parent.ParentCache == null) {
if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
}
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;
protected override MethodInfo FindOutParentMethod (TypeContainer container, ref Type parent_ret_type)
{
- MethodInfo mi = (MethodInfo) container.ParentContainer.MemberCache.FindMemberToOverride (
+ MethodInfo mi = (MethodInfo) container.ParentCache.FindMemberToOverride (
container.TypeBuilder, Name, ParameterTypes, false);
if (mi == null)
// TODO: rename to Resolve......
protected override MethodInfo FindOutParentMethod (TypeContainer container, ref Type parent_ret_type)
{
- PropertyInfo parent_property = container.ParentContainer.MemberCache.FindMemberToOverride (
+ PropertyInfo parent_property = container.ParentCache.FindMemberToOverride (
container.TypeBuilder, Name, ParameterTypes, true) as PropertyInfo;
if (parent_property == null)
/// </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;
/// 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;
}
public readonly IMemberContainer Container;
protected Hashtable member_hash;
protected Hashtable method_hash;
-
+
/// <summary>
/// Create a new MemberCache for the given IMemberContainer `container'.
/// </summary>
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 ();
Timer.StopTimer (TimerType.CacheInit);
}
+ public MemberCache (IMemberContainer container, Type[] ifaces)
+ {
+ this.Container = container;
+
+ member_hash = new Hashtable ();
+ if (ifaces == null)
+ return;
+
+ foreach (Type itype in ifaces) {
+ IMemberContainer iface_container =
+ TypeManager.LookupMemberContainer (itype);
+
+ MemberCache iface_cache = iface_container.MemberCache;
+
+ AddHashtable (member_hash, iface_cache);
+ }
+ }
+
/// <summary>
/// Bootstrap this member cache by doing a deep-copy of our parent.
/// </summary>
{
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'.
/// </summary>
}
}
- /// <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>
{
// 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);
this.Member = member;
this.EntryType = GetEntryType (mt, bf);
}
+
+ public override string ToString ()
+ {
+ return String.Format ("CacheEntry ({0}:{1}:{2})", Container.Name,
+ EntryType, Member);
+ }
}
/// <summary>
get { return Name; }
}
- IMemberContainer IMemberContainer.ParentContainer {
+ MemberCache IMemberContainer.ParentCache {
get { return null; }
}
static PtrHashtable builder_to_declspace;
+ static PtrHashtable builder_to_member_cache;
+
// <remarks>
// Tracks the interfaces implemented by typebuilders. We only
// enter those who do implement or or more interfaces
typecontainers = null;
user_types = null;
builder_to_declspace = null;
+ builder_to_member_cache = null;
builder_to_ifaces = null;
method_arguments = null;
indexer_arguments = null;
typecontainers = new Hashtable ();
builder_to_declspace = new PtrHashtable ();
+ builder_to_member_cache = new PtrHashtable ();
builder_to_method = new PtrHashtable ();
method_arguments = new PtrHashtable ();
method_internal_params = new PtrHashtable ();
return LookupTypeContainer (t);
}
-
+
public static IMemberContainer LookupMemberContainer (Type t)
{
if (t is TypeBuilder) {
return TypeHandle.GetTypeHandle (t);
}
+ public static MemberCache LookupInterfaceCache (IMemberContainer container, Type t)
+ {
+ MemberCache cache = builder_to_member_cache [t] as MemberCache;
+ if (cache != null)
+ return cache;
+
+ cache = new MemberCache (container, GetInterfaces (t));
+ builder_to_member_cache.Add (t, cache);
+ return cache;
+ }
+
public static TypeContainer LookupInterface (Type t)
{
TypeContainer tc = (TypeContainer) builder_to_declspace [t];
// 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)
private string full_name;
private bool is_interface;
private MemberCache member_cache;
+ private MemberCache parent_cache;
private TypeHandle (Type type)
{
this.type = type;
full_name = type.FullName != null ? type.FullName : type.Name;
- if (type.BaseType != null)
+ if (type.BaseType != null) {
BaseType = GetTypeHandle (type.BaseType);
+ parent_cache = BaseType.MemberCache;
+ } else if (type.IsInterface)
+ parent_cache = TypeManager.LookupInterfaceCache (this, type);
this.is_interface = type.IsInterface || type.IsGenericParameter;
this.member_cache = new MemberCache (this);
}
}
}
- public IMemberContainer ParentContainer {
+ public MemberCache ParentCache {
get {
- return BaseType;
+ return parent_cache;
}
}