X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fdecl.cs;h=7ec2b071653b160d5d7f980d829d26c8e76866f5;hb=f682f95e0b2e1423140faa87aa0ee3021eb3e39b;hp=f13f5bcbed50dd22c775b69e2584fe5cdf414236;hpb=f73e0d5c67f0d26e85b92fc4b75fc48783f20d64;p=mono.git diff --git a/mcs/gmcs/decl.cs b/mcs/gmcs/decl.cs index f13f5bcbed5..7ec2b071653 100644 --- a/mcs/gmcs/decl.cs +++ b/mcs/gmcs/decl.cs @@ -29,53 +29,58 @@ namespace Mono.CSharp { public readonly MemberName Left; public readonly Location Location; - public static readonly MemberName Null = new MemberName ("", Location.Null); + public static readonly MemberName Null = new MemberName (""); bool is_double_colon; private MemberName (MemberName left, string name, bool is_double_colon, - TypeArguments args, Location loc) + Location loc) { this.Name = name; this.Location = loc; this.is_double_colon = is_double_colon; - this.TypeArguments = args; this.Left = left; } - public MemberName (string name, TypeArguments args, Location loc) - : this (name, loc) + private MemberName (MemberName left, string name, bool is_double_colon, + TypeArguments args, Location loc) + : this (left, name, is_double_colon, loc) { this.TypeArguments = args; } + public MemberName (string name) + : this (name, Location.Null) + { } + public MemberName (string name, Location loc) - { - this.Name = name; - this.Location = loc; - } + : this (null, name, false, loc) + { } + + public MemberName (string name, TypeArguments args, Location loc) + : this (null, name, false, args, loc) + { } + + public MemberName (MemberName left, string name) + : this (left, name, left != null ? left.Location : Location.Null) + { } public MemberName (MemberName left, string name, Location loc) - : this (name, loc) - { - this.Left = left; - } + : this (left, name, false, loc) + { } public MemberName (MemberName left, string name, TypeArguments args, Location loc) - : this (name, args, loc) - { - this.Left = left; - } + : this (left, name, false, args, loc) + { } + public MemberName (string alias, string name, Location loc) - : this (new MemberName (alias, loc), name, true, null, loc) - { - } + : this (new MemberName (alias, loc), name, true, loc) + { } public MemberName (MemberName left, MemberName right) : this (left, right, right.Location) - { - } + { } public MemberName (MemberName left, MemberName right, Location loc) : this (null, right.Name, false, right.TypeArguments, loc) @@ -85,26 +90,9 @@ namespace Mono.CSharp { this.Left = (right.Left == null) ? left : new MemberName (left, right.Left); } - static readonly char [] dot_array = { '.' }; - - public static MemberName FromDotted (string name, Location loc) - { - string [] elements = name.Split (dot_array); - int count = elements.Length; - int i = 0; - MemberName n = new MemberName (elements [i++], loc); - while (i < count) - n = new MemberName (n, elements [i++], loc); - return n; - } - public string GetName () { - string connect = is_double_colon ? "::" : "."; - if (Left != null) - return Left.GetName () + connect + Name; - else - return Name; + return GetName (false); } public bool IsGeneric { @@ -128,71 +116,15 @@ namespace Mono.CSharp { return name; } - public int CountTypeArguments { - get { - if (TypeArguments == null) - return 0; - else - return TypeArguments.Count; - } - } - - public string MethodName { - get { - string connect = is_double_colon ? "::" : "."; - if (Left != null) - return Left.FullName + connect + Name; - else - return Name; - } - } - - public static string MakeName (string name, TypeArguments args) - { - if (args == null) - return name; - else - return name + "`" + args.Count; - } - - public static string MakeName (string name, int count) - { - return name + "`" + count; - } - public string GetTypeName () { string connect = is_double_colon ? "::" : "."; if (Left != null) - return Left.GetTypeName () + connect + - MakeName (Name, TypeArguments); + return Left.GetTypeName () + connect + MakeName (Name, TypeArguments); else return MakeName (Name, TypeArguments); } - protected bool IsUnbound { - get { - if ((Left != null) && Left.IsUnbound) - return true; - else if (TypeArguments == null) - return false; - else - return TypeArguments.IsUnbound; - } - } - - protected bool CheckUnbound (Location loc) - { - if ((Left != null) && !Left.CheckUnbound (loc)) - return false; - if ((TypeArguments != null) && !TypeArguments.IsUnbound) { - Report.Error (1031, loc, "Type expected"); - return false; - } - - return true; - } - public Expression GetTypeExpression () { if (IsUnbound) { @@ -243,6 +175,16 @@ namespace Mono.CSharp { } } + public string MethodName { + get { + string connect = is_double_colon ? "::" : "."; + if (Left != null) + return Left.FullName + connect + Name; + else + return Name; + } + } + public override string ToString () { string connect = is_double_colon ? "::" : "."; @@ -292,13 +234,58 @@ namespace Mono.CSharp { return hash & 0x7FFFFFFF; } + + public int CountTypeArguments { + get { + if (TypeArguments == null) + return 0; + else + return TypeArguments.Count; + } + } + + public static string MakeName (string name, TypeArguments args) + { + if (args == null) + return name; + else + return name + "`" + args.Count; + } + + public static string MakeName (string name, int count) + { + return name + "`" + count; + } + + protected bool IsUnbound { + get { + if ((Left != null) && Left.IsUnbound) + return true; + else if (TypeArguments == null) + return false; + else + return TypeArguments.IsUnbound; + } + } + + protected bool CheckUnbound (Location loc) + { + if ((Left != null) && !Left.CheckUnbound (loc)) + return false; + if ((TypeArguments != null) && !TypeArguments.IsUnbound) { + Report.Error (1031, loc, "Type expected"); + return false; + } + + return true; + } } /// /// Base representation for members. This is used to keep track /// of Name, Location and Modifier flags, and handling Attributes. /// - public abstract class MemberCore : Attributable { + public abstract class MemberCore : Attributable, IResolveContext { /// /// Public name /// @@ -323,7 +310,7 @@ namespace Mono.CSharp { /// public int ModFlags; - public /*readonly*/ DeclSpace Parent; + public readonly DeclSpace Parent; /// /// Location where this declaration happens @@ -335,7 +322,7 @@ namespace Mono.CSharp { /// /// XML documentation comment /// - public string DocComment; + protected string comment; /// /// Represents header string for documentation comment @@ -357,21 +344,19 @@ namespace Mono.CSharp { Excluded = 1 << 9, // Method is conditional TestMethodDuplication = 1 << 10, // Test for duplication must be performed IsUsed = 1 << 11, - IsAssigned = 1 << 12 // Field is assigned + IsAssigned = 1 << 12, // Field is assigned + HasExplicitLayout = 1 << 13 } - + /// /// MemberCore flags at first detected then cached - /// + /// internal Flags caching_flags; public MemberCore (DeclSpace parent, MemberName name, Attributes attrs) : base (attrs) { - if (parent is PartialContainer && !(this is PartialContainer)) - throw new InternalErrorException ("A PartialContainer cannot be the direct parent of a member"); - - Parent = parent; + this.Parent = parent; member_name = name; caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected; } @@ -384,15 +369,24 @@ namespace Mono.CSharp { public abstract bool Define (); + public virtual string DocComment { + get { + return comment; + } + set { + comment = value; + } + } + // // Returns full member name for error message // public virtual string GetSignatureForError () { if (Parent == null || Parent.Parent == null) - return Name; + return member_name.ToString (); - return String.Concat (Parent.GetSignatureForError (), '.', Name); + return String.Concat (Parent.GetSignatureForError (), '.', member_name.ToString ()); } /// @@ -403,15 +397,7 @@ namespace Mono.CSharp { if (!RootContext.VerifyClsCompliance) return; - VerifyClsCompliance (Parent); - } - - public virtual EmitContext EmitContext { - get { return Parent.EmitContext; } - } - - public bool InUnsafe { - get { return ((ModFlags & Modifiers.UNSAFE) != 0) || Parent.UnsafeContext; } + VerifyClsCompliance (); } public virtual bool IsUsed { @@ -423,24 +409,6 @@ namespace Mono.CSharp { caching_flags |= Flags.IsUsed; } - // - // Whehter is it ok to use an unsafe pointer in this type container - // - public bool UnsafeOK (DeclSpace parent) - { - // - // First check if this MemberCore modifier flags has unsafe set - // - if ((ModFlags & Modifiers.UNSAFE) != 0) - return true; - - if (parent.UnsafeContext) - return true; - - Expression.UnsafeError (Location); - return false; - } - /// /// Returns instance of ObsoleteAttribute for this MemberCore /// @@ -457,11 +425,11 @@ namespace Mono.CSharp { return null; Attribute obsolete_attr = OptAttributes.Search ( - TypeManager.obsolete_attribute_type, EmitContext); + TypeManager.obsolete_attribute_type); if (obsolete_attr == null) return null; - ObsoleteAttribute obsolete = obsolete_attr.GetObsoleteAttribute (EmitContext); + ObsoleteAttribute obsolete = obsolete_attr.GetObsoleteAttribute (); if (obsolete == null) return null; @@ -485,27 +453,15 @@ namespace Mono.CSharp { AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc); } - protected void CheckObsoleteType (Expression type) - { - ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (type.Type); - if (obsolete_attr == null) - return; - - if (GetObsoleteAttribute () != null || Parent.GetObsoleteAttribute () != null) - return; - - AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (type.Type), type.Location); - } - /// /// Analyze whether CLS-Compliant verification must be execute for this MemberCore. /// - public override bool IsClsComplianceRequired (DeclSpace container) + public override bool IsClsComplianceRequired () { if ((caching_flags & Flags.ClsCompliance_Undetected) == 0) return (caching_flags & Flags.ClsCompliant) != 0; - if (GetClsCompliantAttributeValue (container) && IsExposedFromAssembly (container)) { + if (GetClsCompliantAttributeValue () && IsExposedFromAssembly ()) { caching_flags &= ~Flags.ClsCompliance_Undetected; caching_flags |= Flags.ClsCompliant; return true; @@ -518,12 +474,12 @@ namespace Mono.CSharp { /// /// Returns true when MemberCore is exposed from assembly. /// - public bool IsExposedFromAssembly (DeclSpace ds) + public bool IsExposedFromAssembly () { if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0) return false; - DeclSpace parentContainer = ds; + DeclSpace parentContainer = Parent; while (parentContainer != null && parentContainer.ModFlags != 0) { if ((parentContainer.ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0) return false; @@ -533,19 +489,33 @@ namespace Mono.CSharp { } /// - /// Resolve CLSCompliantAttribute value or gets cached value. + /// Goes through class hierarchy and gets value of first found CLSCompliantAttribute. + /// If no is attribute exists then assembly CLSCompliantAttribute is returned. /// - bool GetClsCompliantAttributeValue (DeclSpace ds) + public virtual bool GetClsCompliantAttributeValue () { + if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0) + return (caching_flags & Flags.ClsCompliantAttributeTrue) != 0; + + caching_flags &= ~Flags.HasCompliantAttribute_Undetected; + if (OptAttributes != null) { Attribute cls_attribute = OptAttributes.Search ( - TypeManager.cls_compliant_attribute_type, ds.EmitContext); + TypeManager.cls_compliant_attribute_type); if (cls_attribute != null) { caching_flags |= Flags.HasClsCompliantAttribute; - return cls_attribute.GetClsCompliantAttributeValue (ds.EmitContext); + bool value = cls_attribute.GetClsCompliantAttributeValue (); + if (value) + caching_flags |= Flags.ClsCompliantAttributeTrue; + return value; } } - return ds.GetClsCompliantAttributeValue (); + + if (Parent.GetClsCompliantAttributeValue ()) { + caching_flags |= Flags.ClsCompliantAttributeTrue; + return true; + } + return false; } /// @@ -571,11 +541,11 @@ namespace Mono.CSharp { /// CLS-Compliant which means that CLS-Compliant tests are not necessary. A descendants override it /// and add their extra verifications. /// - protected virtual bool VerifyClsCompliance (DeclSpace ds) + protected virtual bool VerifyClsCompliance () { - if (!IsClsComplianceRequired (ds)) { + if (!IsClsComplianceRequired ()) { if (HasClsCompliantAttribute && RootContext.WarningLevel >= 2) { - if (!IsExposedFromAssembly (ds)) + if (!IsExposedFromAssembly ()) Report.Warning (3019, 2, Location, "CLS compliance checking will not be performed on `{0}' because it is not visible from outside this assembly", GetSignatureForError ()); if (!CodeGen.Assembly.IsClsCompliant) Report.Warning (3021, 2, Location, "`{0}' does not need a CLSCompliant attribute because the assembly is not marked as CLS-compliant", GetSignatureForError ()); @@ -602,7 +572,7 @@ namespace Mono.CSharp { // Raised (and passed an XmlElement that contains the comment) // when GenerateDocComment is writing documentation expectedly. // - internal virtual void OnGenerateDocComment (DeclSpace ds, XmlElement intermediateNode) + internal virtual void OnGenerateDocComment (XmlElement intermediateNode) { } @@ -626,6 +596,40 @@ namespace Mono.CSharp { { DocUtil.GenerateDocComment (this, ds); } + + public override IResolveContext ResolveContext { + get { return this; } + } + + #region IResolveContext Members + + public DeclSpace DeclContainer { + get { return Parent; } + } + + public virtual DeclSpace GenericDeclContainer { + get { return DeclContainer; } + } + + public bool IsInObsoleteScope { + get { + if (GetObsoleteAttribute () != null) + return true; + + return Parent == null ? false : Parent.IsInObsoleteScope; + } + } + + public bool IsInUnsafeScope { + get { + if ((ModFlags & Modifiers.UNSAFE) != 0) + return true; + + return Parent == null ? false : Parent.IsInUnsafeScope; + } + } + + #endregion } /// @@ -662,17 +666,12 @@ namespace Mono.CSharp { protected Hashtable defined_names; + public TypeContainer PartialContainer; + readonly bool is_generic; readonly int count_type_params; readonly int count_current_type_params; - // The emit context for toplevel objects. - protected EmitContext ec; - - public override EmitContext EmitContext { - get { return ec; } - } - // // Whether we are Generic // @@ -696,6 +695,7 @@ namespace Mono.CSharp { NamespaceEntry = ns; Basename = name.Basename; defined_names = new Hashtable (); + PartialContainer = null; if (name.TypeArguments != null) { is_generic = true; count_type_params = count_current_type_params = name.TypeArguments.Count; @@ -704,26 +704,15 @@ namespace Mono.CSharp { count_type_params += parent.count_type_params; } + public override DeclSpace GenericDeclContainer { + get { return this; } + } + /// /// Adds the member to defined_names table. It tests for duplications and enclosing name conflicts /// - protected bool AddToContainer (MemberCore symbol, string name) - { - if (name == MemberName.Name && !(this is Interface) && !(this is Enum)) { - if (symbol is TypeParameter) - Report.Error (694, symbol.Location, - "Type parameter `{0}' has same name as " + - "containing type, or method", name); - else { - Report.SymbolRelatedToPreviousError (this); - Report.Error (542, symbol.Location, - "`{0}': member names cannot be the same " + - "as their enclosing type", - symbol.GetSignatureForError ()); - return false; - } - } - + protected virtual bool AddToContainer (MemberCore symbol, string name) + { MemberCore mc = (MemberCore) defined_names [name]; if (mc == null) { @@ -735,10 +724,8 @@ namespace Mono.CSharp { return true; Report.SymbolRelatedToPreviousError (mc); - if (symbol is PartialContainer || mc is PartialContainer) { - Report.Error (260, symbol.Location, - "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists", - name); + if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) { + Error_MissingPartialModifier (symbol); return false; } @@ -820,6 +807,13 @@ namespace Mono.CSharp { return true; } + protected void Error_MissingPartialModifier (MemberCore type) + { + Report.Error (260, type.Location, + "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists", + type.GetSignatureForError ()); + } + public override string GetSignatureForError () { if (IsGeneric) { @@ -828,49 +822,6 @@ namespace Mono.CSharp { // Parent.GetSignatureForError return Name; } - - // - // Whether this is an `unsafe context' - // - public bool UnsafeContext { - get { - if ((ModFlags & Modifiers.UNSAFE) != 0) - return true; - if (Parent != null) - return Parent.UnsafeContext; - return false; - } - } - - EmitContext type_resolve_ec; - protected EmitContext TypeResolveEmitContext { - get { - if (type_resolve_ec == null) { - // FIXME: I think this should really be one of: - // - // a. type_resolve_ec = Parent.EmitContext; - // b. type_resolve_ec = new EmitContext (Parent, Parent, loc, null, null, ModFlags, false); - // - // However, if Parent == RootContext.Tree.Types, its NamespaceEntry will be null. - // - type_resolve_ec = new EmitContext (Parent, this, Location.Null, null, null, ModFlags, false); - } - return type_resolve_ec; - } - } - - // - // Resolves the expression `e' for a type, and will recursively define - // types. This should only be used for resolving base types. - // - protected TypeExpr ResolveBaseTypeExpr (Expression e, bool silent, Location loc) - { - TypeResolveEmitContext.loc = loc; - TypeResolveEmitContext.ResolvingTypeTree = true; - if (this is GenericMethod) - TypeResolveEmitContext.ContainerType = Parent.TypeBuilder; - return e.ResolveAsTypeTerminal (TypeResolveEmitContext); - } public bool CheckAccessLevel (Type check_type) { @@ -1066,15 +1017,6 @@ namespace Mono.CSharp { return ~ (~ mAccess | pAccess) == 0; } - // - // Return the nested type with name @name. Ensures that the nested type - // is defined if necessary. Do _not_ use this when you have a MemberCache handy. - // - public virtual Type FindNestedType (string name) - { - return null; - } - private Type LookupNestedTypeInHierarchy (string name) { // if the member cache has been created, lets use it. @@ -1089,10 +1031,11 @@ namespace Mono.CSharp { current_type = current_type.BaseType) { current_type = TypeManager.DropGenericTypeArguments (current_type); if (current_type is TypeBuilder) { - DeclSpace decl = this; - if (current_type != TypeBuilder) - decl = TypeManager.LookupDeclSpace (current_type); - t = decl.FindNestedType (name); + TypeContainer tc = current_type == TypeBuilder + ? PartialContainer + : TypeManager.LookupTypeContainer (current_type); + if (tc != null) + t = tc.FindNestedType (name); } else { t = TypeManager.GetNestedType (current_type, name); } @@ -1113,9 +1056,6 @@ namespace Mono.CSharp { // public FullNamedExpression LookupType (string name, Location loc, bool ignore_cs0104) { - if (this is PartialContainer) - throw new InternalErrorException ("Should not get here"); - if (Cache.Contains (name)) return (FullNamedExpression) Cache [name]; @@ -1123,7 +1063,7 @@ namespace Mono.CSharp { Type t = LookupNestedTypeInHierarchy (name); if (t != null) e = new TypeExpression (t, Location.Null); - else if (Parent != null && Parent != RootContext.Tree.Types) + else if (Parent != null) e = Parent.LookupType (name, loc, ignore_cs0104); else e = NamespaceEntry.LookupNamespaceOrType (this, name, loc, ignore_cs0104); @@ -1157,44 +1097,6 @@ namespace Mono.CSharp { TypeBuilder.SetCustomAttribute (cb); } - /// - /// Goes through class hierarchy and get value of first CLSCompliantAttribute that found. - /// If no is attribute exists then return assembly CLSCompliantAttribute. - /// - public bool GetClsCompliantAttributeValue () - { - if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0) - return (caching_flags & Flags.ClsCompliantAttributeTrue) != 0; - - caching_flags &= ~Flags.HasCompliantAttribute_Undetected; - - if (OptAttributes != null) { - Attribute cls_attribute = OptAttributes.Search (TypeManager.cls_compliant_attribute_type, ec); - if (cls_attribute != null) { - caching_flags |= Flags.HasClsCompliantAttribute; - if (cls_attribute.GetClsCompliantAttributeValue (ec)) { - caching_flags |= Flags.ClsCompliantAttributeTrue; - return true; - } - return false; - } - } - - if (Parent == null) { - if (CodeGen.Assembly.IsClsCompliant) { - caching_flags |= Flags.ClsCompliantAttributeTrue; - return true; - } - return false; - } - - if (Parent.GetClsCompliantAttributeValue ()) { - caching_flags |= Flags.ClsCompliantAttributeTrue; - return true; - } - return false; - } - // // Extensions for generics // @@ -1222,9 +1124,11 @@ namespace Mono.CSharp { if (param.Name != name) continue; + Report.SymbolRelatedToPreviousError (Parent); + // TODO: Location is wrong (parent instead of child) Report.Warning (693, 3, Location, - "Type parameter `{0}' has same name as type parameter from outer type `{1}'", - name, Parent.GetInstantiationName ()); + "Type parameter `{0}' has the same name as the type parameter from outer type `{1}'", + name, Parent.GetSignatureForError ()); return false; } @@ -1287,11 +1191,18 @@ namespace Mono.CSharp { Constraints constraints = null; if (constraints_list != null) { - foreach (Constraints constraint in constraints_list) { - if (constraint == null) + int total = constraints_list.Count; + for (int ii = 0; ii < total; ++ii) { + Constraints constraints_at = (Constraints)constraints_list[ii]; + // TODO: it is used by iterators only + if (constraints_at == null) { + constraints_list.RemoveAt (ii); + --total; continue; - if (constraint.TypeParameter == name.Name) { - constraints = constraint; + } + if (constraints_at.TypeParameter == name.Name) { + constraints = constraints_at; + constraints_list.RemoveAt(ii); break; } } @@ -1303,6 +1214,13 @@ namespace Mono.CSharp { AddToContainer (type_params [i], name.Name); } + + if (constraints_list != null && constraints_list.Count > 0) { + foreach (Constraints constraint in constraints_list) { + Report.Error(699, constraint.Location, "`{0}': A constraint references nonexistent type parameter `{1}'", + GetSignatureForError (), constraint.TypeParameter); + } + } } public TypeParameter[] TypeParameters { @@ -1344,11 +1262,15 @@ namespace Mono.CSharp { if (!IsGeneric) return null; - foreach (TypeParameter type_param in CurrentTypeParameters) { - if (type_param.Name != name) - continue; + TypeParameter [] current_params; + if (this is TypeContainer) + current_params = PartialContainer.CurrentTypeParameters; + else + current_params = CurrentTypeParameters; - return new TypeParameterExpr (type_param, loc); + foreach (TypeParameter type_param in current_params) { + if (type_param.Name == name) + return new TypeParameterExpr (type_param, loc); } if (Parent != null) @@ -1361,9 +1283,9 @@ namespace Mono.CSharp { get { return attribute_targets; } } - protected override bool VerifyClsCompliance (DeclSpace ds) + protected override bool VerifyClsCompliance () { - if (!base.VerifyClsCompliance (ds)) { + if (!base.VerifyClsCompliance ()) { return false; } @@ -1382,9 +1304,6 @@ namespace Mono.CSharp { Report.SymbolRelatedToPreviousError (t); } else { - if (val is PartialContainer) - return true; - Report.SymbolRelatedToPreviousError ((DeclSpace)val); } Report.Warning (3005, 1, Location, "Identifier `{0}' differing only in case is not CLS-compliant", GetSignatureForError ()); @@ -1640,8 +1559,8 @@ namespace Mono.CSharp { // method cache with all declared and inherited methods. Type type = container.Type; if (!(type is TypeBuilder) && !type.IsInterface && - // !(type.IsGenericInstance && (type.GetGenericTypeDefinition () is TypeBuilder)) && - !type.IsGenericInstance && + // !(type.IsGenericType && (type.GetGenericTypeDefinition () is TypeBuilder)) && + !type.IsGenericType && (Container.BaseCache == null || Container.BaseCache.method_hash != null)) { method_hash = new Hashtable (); AddMethods (type); @@ -1672,7 +1591,7 @@ namespace Mono.CSharp { /// /// Bootstrap this member cache by doing a deep-copy of our base. /// - Hashtable SetupCache (MemberCache base_class) + static Hashtable SetupCache (MemberCache base_class) { Hashtable hash = new Hashtable (); @@ -1717,8 +1636,8 @@ 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.Constructor, container); + AddMembers (MemberTypes.Field, container); } AddMembers (MemberTypes.Method, container); AddMembers (MemberTypes.Property, container); @@ -1917,8 +1836,8 @@ namespace Mono.CSharp { protected class CacheEntry { public readonly IMemberContainer Container; - public EntryType EntryType; - public MemberInfo Member; + public readonly EntryType EntryType; + public readonly MemberInfo Member; public CacheEntry (IMemberContainer container, MemberInfo member, MemberTypes mt, BindingFlags bf) @@ -1983,7 +1902,7 @@ namespace Mono.CSharp { static MemberInfo [] emptyMemberInfo = new MemberInfo [0]; public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, string name, - MemberFilter filter, object criteria) + MemberFilter filter, object criteria) { if (using_global) throw new Exception (); @@ -2024,6 +1943,7 @@ namespace Mono.CSharp { IMemberContainer current = Container; + bool do_interface_search = current.IsInterface; // `applicable' is a list of all members with the given member name `name' // in the current class and all its base classes. The list is sorted in @@ -2039,7 +1959,10 @@ namespace Mono.CSharp { // iteration of this loop if there are no members with the name we're // looking for in the current class). if (entry.Container != current) { - if (declared_only || DoneSearching (global)) + if (declared_only) + break; + + if (!do_interface_search && DoneSearching (global)) break; current = entry.Container; @@ -2055,8 +1978,28 @@ namespace Mono.CSharp { // Apply the filter to it. if (filter (entry.Member, criteria)) { - if ((entry.EntryType & EntryType.MaskType) != EntryType.Method) + if ((entry.EntryType & EntryType.MaskType) != EntryType.Method) { do_method_search = false; + } + + // Because interfaces support multiple inheritance we have to be sure that + // base member is from same interface, so only top level member will be returned + if (do_interface_search && global.Count > 0) { + bool member_already_exists = false; + + foreach (MemberInfo mi in global) { + if (mi is MethodBase) + continue; + + if (IsInterfaceBaseInterface (TypeManager.GetInterfaces (mi.DeclaringType), entry.Member.DeclaringType)) { + member_already_exists = true; + break; + } + } + if (member_already_exists) + continue; + } + global.Add (entry.Member); } } @@ -2078,6 +2021,22 @@ namespace Mono.CSharp { global.CopyTo (copy); return copy; } + + /// + /// Returns true if iterface exists in any base interfaces (ifaces) + /// + static bool IsInterfaceBaseInterface (Type[] ifaces, Type ifaceToFind) + { + foreach (Type iface in ifaces) { + if (iface == ifaceToFind) + return true; + + Type[] base_ifaces = TypeManager.GetInterfaces (iface); + if (base_ifaces.Length > 0 && IsInterfaceBaseInterface (base_ifaces, ifaceToFind)) + return true; + } + return false; + } // find the nested type @name in @this. public Type FindNestedType (string name) @@ -2350,7 +2309,9 @@ namespace Mono.CSharp { /// /// Cls compliance check whether methods or constructors parameters differing only in ref or out, or in array rank /// - public void VerifyClsParameterConflict (ArrayList al, MethodCore method, MemberInfo this_builder) + /// + // TODO: refactor as method is always 'this' + public static void VerifyClsParameterConflict (ArrayList al, MethodCore method, MemberInfo this_builder) { EntryType tested_type = (method is Constructor ? EntryType.Constructor : EntryType.Method) | EntryType.Public; @@ -2375,7 +2336,7 @@ namespace Mono.CSharp { // TODO: now we are ignoring CLSCompliance(false) on method from other assembly which is buggy. // However it is exactly what csc does. - if (md != null && !md.IsClsComplianceRequired (method.Parent)) + if (md != null && !md.IsClsComplianceRequired ()) continue; Report.SymbolRelatedToPreviousError (entry.Member);