X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mcs%2Fmcs%2Fclass.cs;h=11d1b9be24a0a75746342c0c201dfe0186bebf01;hb=d43ab974ad944444ec9137536f8d1c8f8b497c14;hp=3cf54210d277311052daa30f8baf8349f0cb4ade;hpb=cfa2f984ce0c71bd17de82e1355e586823c09c1a;p=mono.git diff --git a/mcs/mcs/class.cs b/mcs/mcs/class.cs index 3cf54210d27..11d1b9be24a 100755 --- a/mcs/mcs/class.cs +++ b/mcs/mcs/class.cs @@ -1,7 +1,9 @@ + // // class.cs: Class and Struct handlers // -// Author: Miguel de Icaza (miguel@gnu.org) +// Authors: Miguel de Icaza (miguel@gnu.org) +// Martin Baulig (martin@gnome.org) // // Licensed under the terms of the GNU GPL // @@ -103,6 +105,9 @@ namespace Mono.CSharp { public bool AllowMultiple = false; public bool Inherited; + // The interfaces we implement. + Type [] ifaces; + // // The indexer name for this class // @@ -212,10 +217,17 @@ namespace Mono.CSharp { if (value != null && (!(value is Method))) return AdditionResult.NameExists; + if (name == Basename) + return AdditionResult.EnclosingClash; + if (methods == null) methods = new ArrayList (); - methods.Add (method); + if (method.Name.IndexOf (".") != -1) + methods.Insert (0, method); + else + methods.Add (method); + if (value != null) DefineName (name, method); @@ -274,16 +286,16 @@ namespace Mono.CSharp { { AdditionResult res; string name = field.Name; - + if ((res = IsValid (name)) != AdditionResult.Success) return res; - + if (fields == null) fields = new ArrayList (); - + fields.Add (field); - if (field.Initializer != null){ + if (field.HasInitializer){ if ((field.ModFlags & Modifiers.STATIC) != 0){ if (initialized_static_fields == null) initialized_static_fields = new ArrayList (); @@ -305,7 +317,7 @@ namespace Mono.CSharp { if ((field.ModFlags & Modifiers.STATIC) == 0) have_nonstatic_fields = true; - + DefineName (name, field); return AdditionResult.Success; } @@ -321,7 +333,10 @@ namespace Mono.CSharp { if (properties == null) properties = new ArrayList (); - properties.Add (prop); + if (prop.Name.IndexOf (".") != -1) + properties.Insert (0, prop); + else + properties.Add (prop); DefineName (name, prop); return AdditionResult.Success; @@ -349,7 +364,10 @@ namespace Mono.CSharp { if (indexers == null) indexers = new ArrayList (); - indexers.Add (i); + if (i.InterfaceType != null) + indexers.Insert (0, i); + else + indexers.Add (i); return AdditionResult.Success; } @@ -416,6 +434,10 @@ namespace Mono.CSharp { get { return fields; } + + set { + fields = value; + } } public ArrayList InstanceConstructors { @@ -497,18 +519,11 @@ namespace Mono.CSharp { if (fields == null) return true; - - foreach (Field f in fields){ - Object init = f.Initializer; - Expression e; - if (init is Expression) - e = (Expression) init; - else { - string base_type = f.Type.Substring (0, f.Type.IndexOf ("[")); - string rank = f.Type.Substring (f.Type.IndexOf ("[")); - e = new ArrayCreation (base_type, rank, (ArrayList)init, f.Location); - } + foreach (Field f in fields){ + Expression e = f.GetInitializerExpression (ec); + if (e == null) + return false; Location l = f.Location; FieldExpr fe = new FieldExpr (f.FieldBuilder, l); @@ -525,7 +540,7 @@ namespace Mono.CSharp { throw new Exception ("Assign.Resolve returned a non ExpressionStatement"); } } - + return true; } @@ -537,9 +552,11 @@ namespace Mono.CSharp { Constructor c; int mods = 0; - c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (), - new ConstructorBaseInitializer (null, new Location (-1)), - new Location (-1)); + c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters, + new ConstructorBaseInitializer ( + null, Parameters.EmptyReadOnlyParameters, + Location.Null), + Location.Null); if (is_static) mods = Modifiers.STATIC; @@ -617,14 +634,16 @@ namespace Mono.CSharp { count = bases.Count; if (is_class){ - string name = (string) bases [0]; - Type first = FindType (name); + Expression name = (Expression) bases [0]; + name = ResolveTypeExpr (name, false, Location); - if (first == null){ + if (name == null){ error = true; return null; } + Type first = name.Type; + if (first.IsClass){ parent = first; start = 1; @@ -633,6 +652,13 @@ namespace Mono.CSharp { start = 0; } + if (!AsAccessible (parent, ModFlags)) + Report.Error (60, Location, + "Inconsistent accessibility: base class `" + + TypeManager.CSharpName (parent) + "' is less " + + "accessible than class `" + + Name + "'"); + } else { start = 0; } @@ -640,8 +666,10 @@ namespace Mono.CSharp { Type [] ifaces = new Type [count-start]; for (i = start, j = 0; i < count; i++, j++){ - string name = (string) bases [i]; - Type t = FindType (name); + Expression name = (Expression) bases [i]; + Expression resolved = ResolveTypeExpr (name, false, Location); + bases [i] = resolved; + Type t = resolved.Type; if (t == null){ error = true; @@ -684,7 +712,7 @@ namespace Mono.CSharp { return null; } } - + ifaces [j] = t; } @@ -697,7 +725,6 @@ namespace Mono.CSharp { public override TypeBuilder DefineType () { Type parent; - Type [] ifaces; bool error; bool is_class; @@ -708,7 +735,7 @@ namespace Mono.CSharp { return null; InTransit = true; - + if (this is Class) is_class = true; else @@ -783,6 +810,12 @@ namespace Mono.CSharp { } } + // add interfaces that were not added at type creation (weird API issue) + if (!is_class && !have_nonstatic_fields && (ifaces != null)) { + foreach (Type i in ifaces) + TypeBuilder.AddInterfaceImplementation (i); + } + // // Finish the setup for the EmitContext // @@ -790,8 +823,9 @@ namespace Mono.CSharp { TypeManager.AddUserType (Name, TypeBuilder, this, ifaces); - if (parent == TypeManager.attribute_type || - parent.IsSubclassOf (TypeManager.attribute_type)) { + if ((parent != null) && + (parent == TypeManager.attribute_type || + parent.IsSubclassOf (TypeManager.attribute_type))) { RootContext.RegisterAttribute (this); TypeManager.RegisterAttrType (TypeBuilder, this); } else @@ -893,6 +927,10 @@ namespace Mono.CSharp { i.Define (this); name = i.IndexerName; + + if (i.InterfaceType != null) + continue; + if (class_indexer_name == null){ class_indexer_name = name; continue; @@ -909,14 +947,27 @@ namespace Mono.CSharp { class_indexer_name = "Item"; IndexerName = class_indexer_name; } - + + static void Report1530 (Location loc) + { + Report.Error (1530, loc, "Keyword new not allowed for namespace elements"); + } + /// /// Populates our TypeBuilder with fields and methods /// - public override bool Define (TypeContainer parent) + public override bool DefineMembers (TypeContainer parent) { MemberInfo [] defined_names = null; + if (interface_order != null){ + foreach (Interface iface in interface_order) + if ((iface.ModFlags & Modifiers.NEW) == 0) + iface.DefineMembers (this); + else + Report1530 (iface.Location); + } + if (RootContext.WarningLevel > 1){ Type ptype; @@ -926,7 +977,7 @@ namespace Mono.CSharp { // ptype = TypeBuilder.BaseType; if (ptype != null){ - defined_names = FindMembers ( + defined_names = (MemberInfo []) FindMembers ( ptype, MemberTypes.All & ~MemberTypes.Constructor, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, null, null); @@ -1002,17 +1053,17 @@ namespace Mono.CSharp { return true; } - /// - /// Looks up the alias for the name - /// - public string LookupAlias (string name) + public override bool Define (TypeContainer parent) { - if (Namespace != null) - return Namespace.LookupAlias (name); - else - return null; + if (interface_order != null){ + foreach (Interface iface in interface_order) + if ((iface.ModFlags & Modifiers.NEW) == 0) + iface.Define (this); + } + + return true; } - + /// /// This function is based by a delegate to the FindMembers routine /// @@ -1058,15 +1109,15 @@ namespace Mono.CSharp { // // Since the whole process is a no-op, it is fine to check for null here. // - public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, - MemberFilter filter, object criteria) + internal override MemberList FindMembers (MemberTypes mt, BindingFlags bf, + MemberFilter filter, object criteria) { ArrayList members = new ArrayList (); bool priv = (bf & BindingFlags.NonPublic) != 0; if (filter == null) filter = accepting_filter; - + if ((mt & MemberTypes.Field) != 0) { if (fields != null) { foreach (Field f in fields) { @@ -1178,17 +1229,32 @@ namespace Mono.CSharp { } if ((mt & MemberTypes.NestedType) != 0) { + if (types != null){ + foreach (TypeContainer t in types) { + TypeBuilder tb = t.TypeBuilder; + + if (tb != null && (filter (tb, criteria) == true)) + members.Add (tb); + } + } - if (Types != null) - foreach (TypeContainer t in Types) - if (filter (t.TypeBuilder, criteria) == true) - members.Add (t.TypeBuilder); + if (enums != null){ + foreach (Enum en in enums){ + TypeBuilder tb = en.TypeBuilder; - if (Enums != null) - foreach (Enum en in Enums) - if (filter (en.TypeBuilder, criteria) == true) - members.Add (en.TypeBuilder); + if (tb != null && (filter (tb, criteria) == true)) + members.Add (tb); + } + } + if (delegates != null){ + foreach (Delegate d in delegates){ + TypeBuilder tb = d.TypeBuilder; + + if (tb != null && (filter (tb, criteria) == true)) + members.Add (tb); + } + } } if ((mt & MemberTypes.Constructor) != 0){ @@ -1206,6 +1272,7 @@ namespace Mono.CSharp { ConstructorBuilder cb = default_static_constructor.ConstructorBuilder; + if (cb != null) if (filter (cb, criteria) == true) members.Add (cb); } @@ -1215,51 +1282,24 @@ namespace Mono.CSharp { // Lookup members in parent if requested. // if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) { - MemberInfo [] mi; - - mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria); - if (mi != null) - members.AddRange (mi); - } - - int count = members.Count; - if (count > 0){ - MemberInfo [] mi = new MemberInfo [count]; - members.CopyTo (mi); - return mi; + MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria); + members.AddRange (list); } - return null; + return new MemberList (members); } - public MemberInfo GetFieldFromEvent (EventExpr event_expr) - { - if (events == null) - return null; - - EventInfo ei = event_expr.EventInfo; - - foreach (Event e in events) { - - if (e.FieldBuilder == null) - continue; - - if (Type.FilterName (e.FieldBuilder, ei.Name)) - return e.FieldBuilder; - } - - return null; - } + - public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf, - MemberFilter filter, object criteria) + public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf, + MemberFilter filter, object criteria) { TypeContainer tc = TypeManager.LookupTypeContainer (t); if (tc != null) return tc.FindMembers (mt, bf, filter, criteria); else - return t.FindMembers (mt, bf, filter, criteria); + return new MemberList (t.FindMembers (mt, bf, filter, criteria)); } // @@ -1442,6 +1482,7 @@ namespace Mono.CSharp { public bool MethodModifiersValid (int flags, string n, Location loc) { const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE); + const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT); const int nv = (Modifiers.NEW | Modifiers.VIRTUAL); bool ok = true; string name = MakeName (n); @@ -1458,6 +1499,13 @@ namespace Mono.CSharp { } } + if (this is Struct){ + if ((flags & va) != 0){ + Modifiers.Error_InvalidModifier (loc, "virtual or abstract"); + ok = false; + } + } + if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){ Report.Error ( 113, loc, name + @@ -1512,13 +1560,103 @@ namespace Mono.CSharp { return ok; } + // Access level of a type. + enum AccessLevel { + Public = 0, + ProtectedInternal = 1, + Internal = 2, + Protected = 3, + Private = 4 + } + + // Check whether `flags' denotes a more restricted access than `level' + // and return the new level. + static AccessLevel CheckAccessLevel (AccessLevel level, int flags) + { + AccessLevel old_level = level; + + if ((flags & Modifiers.INTERNAL) != 0) { + if ((flags & Modifiers.PROTECTED) != 0) { + if ((int) level < (int) AccessLevel.ProtectedInternal) + level = AccessLevel.ProtectedInternal; + } else { + if ((int) level < (int) AccessLevel.Internal) + level = AccessLevel.Internal; + } + } else if ((flags & Modifiers.PROTECTED) != 0) { + if ((int) level < (int) AccessLevel.Protected) + level = AccessLevel.Protected; + } else if ((flags & Modifiers.PRIVATE) != 0) + level = AccessLevel.Private; + + return level; + } + + // Return the access level for a new member which is defined in the current + // TypeContainer with access modifiers `flags'. + AccessLevel GetAccessLevel (int flags) + { + if ((flags & Modifiers.PRIVATE) != 0) + return AccessLevel.Private; + + AccessLevel level; + if (!IsTopLevel && (Parent != null)) + level = Parent.GetAccessLevel (flags); + else + level = AccessLevel.Public; + + return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags); + } + + // Return the access level for type `t', but don't give more access than `flags'. + static AccessLevel GetAccessLevel (Type t, int flags) + { + if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate) + return AccessLevel.Private; + + AccessLevel level; + if (TypeManager.IsBuiltinType (t)) + return AccessLevel.Public; + else if ((t.DeclaringType != null) && (t != t.DeclaringType)) + level = GetAccessLevel (t.DeclaringType, flags); + else { + level = CheckAccessLevel (AccessLevel.Public, flags); + } + + if (t.IsNestedPublic) + return level; + + if (t.IsNestedAssembly || t.IsNotPublic) { + if ((int) level < (int) AccessLevel.Internal) + level = AccessLevel.Internal; + } + + if (t.IsNestedFamily) { + if ((int) level < (int) AccessLevel.Protected) + level = AccessLevel.Protected; + } + + if (t.IsNestedFamORAssem) { + if ((int) level < (int) AccessLevel.ProtectedInternal) + level = AccessLevel.ProtectedInternal; + } + + return level; + } + // - // Returns true if `type' is as accessible as the flags `flags' - // given for this member + // Returns true if `parent' is as accessible as the flags `flags' + // given for this member. // - static public bool AsAccessible (Type type, int flags) + public bool AsAccessible (Type parent, int flags) { - return true; + while (parent.IsArray || parent.IsPointer || parent.IsByRef) + parent = parent.GetElementType (); + + AccessLevel level = GetAccessLevel (flags); + AccessLevel level2 = GetAccessLevel (parent, flags); + + return (int) level >= (int) level2; } Hashtable builder_and_args; @@ -1529,6 +1667,43 @@ namespace Mono.CSharp { builder_and_args = new Hashtable (); return true; } + + /// + /// Performs checks for an explicit interface implementation. First it + /// checks whether the `interface_type' is a base inteface implementation. + /// Then it checks whether `name' exists in the interface type. + /// + public bool VerifyImplements (Type interface_type, string full, string name, Location loc) + { + bool found = false; + + if (ifaces != null){ + foreach (Type t in ifaces){ + if (t == interface_type){ + found = true; + break; + } + } + } + + if (!found){ + Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'"); + return false; + } + + return true; + } + + public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name) + { + Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface"); + } + + public override MemberCache MemberCache { + get { + return null; + } + } } public class Class : TypeContainer { @@ -1614,35 +1789,30 @@ namespace Mono.CSharp { } } - public abstract class MethodCore : MemberCore { + public abstract class MethodCore : MemberBase { public readonly Parameters Parameters; Block block; // // Parameters, cached for semantic analysis. // - InternalParameters parameter_info; - - public MethodCore (string name, Parameters parameters, Location l) - : base (name, l) + protected InternalParameters parameter_info; + protected Type [] parameter_types; + + public MethodCore (Expression type, int mod, int allowed_mod, string name, + Attributes attrs, Parameters parameters, Location loc) + : base (type, mod, allowed_mod, name, attrs, loc) { - Name = name; Parameters = parameters; } // // Returns the System.Type array for the parameters of this method // - Type [] parameter_types; - public Type [] ParameterTypes (TypeContainer parent) - { - if (Parameters == null) - return TypeManager.NoTypes; - - if (parameter_types == null) - parameter_types = Parameters.GetParameterInfo (parent); - - return parameter_types; + public Type [] ParameterTypes { + get { + return parameter_types; + } } public InternalParameters ParameterInfo @@ -1650,10 +1820,6 @@ namespace Mono.CSharp { get { return parameter_info; } - - set { - parameter_info = value; - } } public Block Block { @@ -1666,6 +1832,18 @@ namespace Mono.CSharp { } } + protected virtual bool DoDefineParameters (TypeContainer parent) + { + // Check if arguments were correct + parameter_types = Parameters.GetParameterInfo (parent); + if ((parameter_types == null) || !CheckParameters (parent, parameter_types)) + return false; + + parameter_info = new InternalParameters (parent, Parameters); + + return true; + } + public CallingConventions GetCallingConvention (bool is_class) { CallingConventions cc = 0; @@ -1737,11 +1915,8 @@ namespace Mono.CSharp { } public class Method : MethodCore { - public readonly string ReturnType; public MethodBuilder MethodBuilder; - public readonly Attributes OptAttributes; - - MethodAttributes flags; + public MethodData MethodData; /// /// Modifiers allowed in a class declaration @@ -1763,31 +1938,24 @@ namespace Mono.CSharp { // // return_type can be "null" for VOID values. // - public Method (string return_type, int mod, string name, Parameters parameters, + public Method (Expression return_type, int mod, string name, Parameters parameters, Attributes attrs, Location l) - : base (name, parameters, l) - { - ReturnType = return_type; - ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l); - OptAttributes = attrs; - } + : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l) + { } // // Returns the `System.Type' for the ReturnType of this // function. Provides a nice cache. (used between semantic analysis // and actual code generation // - Type type_return_type; - public Type GetReturnType (TypeContainer parent) { - if (type_return_type == null) - type_return_type = RootContext.LookupType ( - parent, ReturnType, false, Location); - - return type_return_type; + return MemberType; } + // Whether this is an operator method. + public bool IsOperator; + void DuplicateEntryPoint (MethodInfo b, Location location) { Report.Error ( @@ -1828,49 +1996,36 @@ namespace Mono.CSharp { return true; else return false; - } + } // - // Creates the type + // Checks our base implementation if any // - public override bool Define (TypeContainer parent) + protected override bool CheckBase (TypeContainer parent) { - Type ret_type = GetReturnType (parent); - Type [] parameters = ParameterTypes (parent); - bool error = false; - MethodInfo implementing = null; - Type iface_type = null; - string iface = "", short_name; - bool explicit_impl = false; - - // Check if the return type and arguments were correct - if (ret_type == null || parameters == null) - return false; - - if (!parent.MethodModifiersValid (ModFlags, Name, Location)) - return false; - - flags = Modifiers.MethodAttr (ModFlags); - - // - // verify accessibility - // - if (!TypeContainer.AsAccessible (ret_type, ModFlags)) + // Check whether arguments were correct. + if (!DoDefineParameters (parent)) return false; - if (ret_type.IsPointer && !UnsafeOK (parent)) - return false; - - foreach (Type partype in parameters){ - if (!TypeContainer.AsAccessible (partype, ModFlags)) - error = true; - if (partype.IsPointer && !UnsafeOK (parent)) - error = true; + MethodSignature ms = new MethodSignature (Name, null, ParameterTypes); + if (!IsOperator) { + MemberList mi_this; + + mi_this = TypeContainer.FindMembers ( + parent.TypeBuilder, MemberTypes.Method, + BindingFlags.NonPublic | BindingFlags.Public | + BindingFlags.Static | BindingFlags.Instance | + BindingFlags.DeclaredOnly, + MethodSignature.method_signature_filter, ms); + + if (mi_this.Count > 0) { + Report.Error (111, Location, "Class `" + parent.Name + "' " + + "already defines a member called `" + Name + "' " + + "with the same parameter types"); + return false; + } } - if (error) - return false; - // // Verify if the parent has a type with the same name, and then // check whether we have to create a new slot for it or not. @@ -1879,8 +2034,7 @@ namespace Mono.CSharp { // ptype is only null for System.Object while compiling corlib. if (ptype != null){ - MethodSignature ms = new MethodSignature (Name, null, parameters); - MemberInfo [] mi, mi_static, mi_instance; + MemberList mi, mi_static, mi_instance; mi_static = TypeContainer.FindMembers ( ptype, MemberTypes.Method, @@ -1893,16 +2047,32 @@ namespace Mono.CSharp { MethodSignature.inheritable_method_signature_filter, ms); - if (mi_instance != null && mi_instance.Length > 0){ + if (mi_instance.Count > 0){ mi = mi_instance; - } else if (mi_static != null && mi_static.Length > 0) + } else if (mi_static.Count > 0) mi = mi_static; else mi = null; - if (mi != null && mi.Length > 0){ - if (!CheckMethodAgainstBase (parent, flags, (MethodInfo) mi [0])){ + if (mi != null && mi.Count > 0){ + parent_method = (MethodInfo) mi [0]; + string name = parent_method.DeclaringType.Name + "." + + parent_method.Name; + + if (!CheckMethodAgainstBase (parent, flags, parent_method, name)) return false; + + if ((ModFlags & Modifiers.NEW) == 0) { + Type parent_ret = TypeManager.TypeToCoreType ( + parent_method.ReturnType); + + if (parent_ret != MemberType) { + Report.Error ( + 508, parent.MakeName (Name) + ": cannot " + + "change return type when overriding " + + "inherited member " + name); + return false; + } } } else { if ((ModFlags & Modifiers.NEW) != 0) @@ -1917,151 +2087,33 @@ namespace Mono.CSharp { } else if ((ModFlags & Modifiers.NEW) != 0) WarningNotHiding (parent); - // - // If we implement an interface, extract the interface name. - // + return true; + } - if (Name.IndexOf (".") != -1){ - int pos = Name.LastIndexOf ("."); - iface = Name.Substring (0, pos); + // + // Creates the type + // + public override bool Define (TypeContainer parent) + { + if (!DoDefine (parent)) + return false; - iface_type = RootContext.LookupType (parent, iface, false, Location); - short_name = Name.Substring (pos + 1); + if (!CheckBase (parent)) + return false; - if (iface_type == null) - return false; + CallingConventions cc = GetCallingConvention (parent is Class); - // Compute the full name that we need to export - Name = iface_type.FullName + "." + short_name; - explicit_impl = true; - } else - short_name = Name; + MethodData = new MethodData (this, null, MemberType, ParameterTypes, + ParameterInfo, cc, OptAttributes, + ModFlags, flags, true); - // - // Check if we are an implementation of an interface method or - // a method - // - if (parent.Pending != null) - implementing = parent.Pending.IsInterfaceMethod ( - iface_type, short_name, ret_type, parameters); - - // - // For implicit implementations, make sure we are public, for - // explicit implementations, make sure we are private. - // - if (implementing != null){ - // - // Setting null inside this block will trigger a more - // verbose error reporting for missing interface implementations - // - // The "candidate" function has been flagged already - // but it wont get cleared - // - if (iface_type == null){ - // - // We already catch different accessibility settings - // so we just need to check that we are not private - // - if ((ModFlags & Modifiers.PRIVATE) != 0) - implementing = null; + if (!MethodData.Define (parent)) + return false; - // - // Static is not allowed - // - if ((ModFlags & Modifiers.STATIC) != 0) - implementing = null; - } else { - if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){ - Report.Error ( - 106, Location, "`public' or `abstract' modifiers "+ - "are not allowed in explicit interface declarations" - ); - implementing = null; - } - } - } + MethodBuilder = MethodData.MethodBuilder; // - // If implementing is still valid, set flags - // - if (implementing != null){ - if (implementing.DeclaringType.IsInterface) - flags |= MethodAttributes.NewSlot; - - flags |= - MethodAttributes.Virtual | - MethodAttributes.HideBySig; - - // - // clear the pending implementation flag - // - parent.Pending.ImplementMethod ( - iface_type, short_name, ret_type, parameters, explicit_impl); - } - - Attribute dllimport_attr = null; - if (OptAttributes != null && OptAttributes.AttributeSections != null) { - foreach (AttributeSection asec in OptAttributes.AttributeSections) { - if (asec.Attributes == null) - continue; - - foreach (Attribute a in asec.Attributes) - if (a.Name.IndexOf ("DllImport") != -1) { - flags |= MethodAttributes.PinvokeImpl; - dllimport_attr = a; - } - } - } - - // - // Finally, define the method - // - - if ((flags & MethodAttributes.PinvokeImpl) != 0) { - - if ((ModFlags & Modifiers.STATIC) == 0) { - Report.Error (601, Location, "The DllImport attribute must be specified on " + - "a method marked 'static' and 'extern'."); - return false; - } - - EmitContext ec = new EmitContext ( - parent, Location, null, GetReturnType (parent), ModFlags); - - MethodBuilder = dllimport_attr.DefinePInvokeMethod ( - ec, parent.TypeBuilder, - Name, flags, ret_type, parameters); - } else { - MethodBuilder = parent.TypeBuilder.DefineMethod ( - Name, flags, - GetCallingConvention (parent is Class), - ret_type, parameters); - - if (implementing != null && explicit_impl) - parent.TypeBuilder.DefineMethodOverride ( - MethodBuilder, implementing); - } - - if (MethodBuilder == null) - return false; - - // - // HACK because System.Reflection.Emit is lame - // - ParameterInfo = new InternalParameters (parent, Parameters); - - if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo, - parameters)) { - Report.Error ( - 111, Location, - "Class `" + parent.Name + "' already contains a definition with " + - " the same return value and parameter types for method `" + - Name + "'"); - return false; - } - - // - // This is used to track the Entry Point, + // This is used to track the Entry Point, // if (Name == "Main" && ((ModFlags & Modifiers.STATIC) != 0) && @@ -2087,110 +2139,22 @@ namespace Mono.CSharp { // public void Emit (TypeContainer parent) { - ILGenerator ig; - EmitContext ec; - - if ((flags & MethodAttributes.PinvokeImpl) == 0) - ig = MethodBuilder.GetILGenerator (); - else - ig = null; - - ec = new EmitContext (parent, Location, ig, GetReturnType (parent), ModFlags); - - if (OptAttributes != null) - Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location); - - - LabelParameters (ec, ParameterTypes (parent), MethodBuilder); - - // - // abstract or extern methods have no bodies - // - if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){ - if (Block != null){ - if ((ModFlags & Modifiers.ABSTRACT) != 0){ - Report.Error ( - 500, "Abstract method `" + - TypeManager.CSharpSignature (MethodBuilder) + - "' can not have a body"); - } - } - return; - } - - // - // Handle destructors specially - // - // FIXME: This code generates buggy code - // - if (Name == "Finalize" && type_return_type == TypeManager.void_type) - EmitDestructor (ec); - else { - ISymbolWriter sw = CodeGen.SymbolWriter; - - if ((sw != null) && (!Location.IsNull (Location))) { - MethodToken token = MethodBuilder.GetToken (); - sw.OpenMethod (new SymbolToken (token.Token)); - sw.SetMethodSourceRange (Location.SymbolDocument, - Location.Row, 0, - Block.EndLocation.SymbolDocument, - Block.EndLocation.Row, 0); - - ec.EmitTopBlock (Block, Location); - - sw.CloseMethod (); - } else - ec.EmitTopBlock (Block, Location); - } - } - - void EmitDestructor (EmitContext ec) - { - ILGenerator ig = ec.ig; - - Label finish = ig.DefineLabel (); - bool old_in_try = ec.InTry; - - ig.BeginExceptionBlock (); - ec.InTry = true; - ec.ReturnLabel = finish; - ec.EmitTopBlock (Block, Location); - ec.InTry = old_in_try; - - ig.MarkLabel (finish); - bool old_in_finally = ec.InFinally; - ec.InFinally = true; - ig.BeginFinallyBlock (); - - if (ec.ContainerType.BaseType != null) { - Expression member_lookup = Expression.MemberLookup ( - ec, ec.ContainerType.BaseType, "Finalize", - MemberTypes.Method, Expression.AllBindingFlags, Location); - - if (member_lookup != null){ - MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup); - - ig.Emit (OpCodes.Ldarg_0); - ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]); - } - } - ec.InFinally = old_in_finally; - - ig.EndExceptionBlock (); - //ig.MarkLabel (ec.ReturnLabel); - ig.Emit (OpCodes.Ret); + MethodData.Emit (parent, Block, this); } } public abstract class ConstructorInitializer { ArrayList argument_list; ConstructorInfo parent_constructor; - Location location; + Parameters parameters; + Location loc; - public ConstructorInitializer (ArrayList argument_list, Location location) + public ConstructorInitializer (ArrayList argument_list, Parameters parameters, + Location loc) { this.argument_list = argument_list; - this.location = location; + this.parameters = parameters; + this.loc = loc; } public ArrayList Arguments { @@ -2203,39 +2167,48 @@ namespace Mono.CSharp { { Expression parent_constructor_group; Type t; - + + ec.CurrentBlock = new Block (null, true, parameters); + if (argument_list != null){ foreach (Argument a in argument_list){ - if (!a.Resolve (ec, location)) + if (!a.Resolve (ec, loc)) return false; } } + ec.CurrentBlock = null; + if (this is ConstructorBaseInitializer) { if (ec.ContainerType.BaseType == null) return true; t = ec.ContainerType.BaseType; + if (ec.ContainerType.IsValueType) { + Report.Error (522, loc, + "structs cannot call base class constructors"); + return false; + } } else t = ec.ContainerType; - + parent_constructor_group = Expression.MemberLookup ( - ec, t, ".ctor", + ec, t, t, ".ctor", MemberTypes.Constructor, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, - location); + loc); if (parent_constructor_group == null){ - Report.Error (1501, location, + Report.Error (1501, loc, "Can not find a constructor for this argument list"); return false; } parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, - (MethodGroupExpr) parent_constructor_group, argument_list, location); + (MethodGroupExpr) parent_constructor_group, argument_list, loc); if (parent_constructor == null){ - Report.Error (1501, location, + Report.Error (1501, loc, "Can not find a constructor for this argument list"); return false; } @@ -2245,7 +2218,8 @@ namespace Mono.CSharp { public void Emit (EmitContext ec) { - ec.ig.Emit (OpCodes.Ldarg_0); + if (parent_constructor != null) + ec.ig.Emit (OpCodes.Ldarg_0); if (argument_list != null) Invocation.EmitArguments (ec, null, argument_list); if (parent_constructor != null) @@ -2254,13 +2228,15 @@ namespace Mono.CSharp { } public class ConstructorBaseInitializer : ConstructorInitializer { - public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l) + public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) : + base (argument_list, pars, l) { } } public class ConstructorThisInitializer : ConstructorInitializer { - public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l) + public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) : + base (argument_list, pars, l) { } } @@ -2268,7 +2244,7 @@ namespace Mono.CSharp { public class Constructor : MethodCore { public ConstructorBuilder ConstructorBuilder; public ConstructorInitializer Initializer; - public Attributes OptAttributes; + new public Attributes OptAttributes; // // Modifiers allowed for a constructor. @@ -2286,7 +2262,7 @@ namespace Mono.CSharp { // my very own code has static constructors. // public Constructor (string name, Parameters args, ConstructorInitializer init, Location l) - : base (name, args, l) + : base (null, 0, AllowedModifiers, name, null, args, l) { Initializer = init; } @@ -2315,15 +2291,14 @@ namespace Mono.CSharp { MethodAttributes ca = (MethodAttributes.RTSpecialName | MethodAttributes.SpecialName); - Type [] parameters = ParameterTypes (parent); - - if (parameters == null) + // Check if arguments were correct. + if (!DoDefineParameters (parent)) return false; - + if ((ModFlags & Modifiers.STATIC) != 0) ca |= MethodAttributes.Static; else { - if (parent is Struct && parameters.Length == 0){ + if (parent is Struct && ParameterTypes.Length == 0){ Report.Error ( 568, Location, "Structs can not contain explicit parameterless " + @@ -2333,19 +2308,13 @@ namespace Mono.CSharp { ca |= MethodAttributes.Public | MethodAttributes.HideBySig; } - foreach (Type partype in parameters) - if (!TypeContainer.AsAccessible (partype, ModFlags)) - return false; - ConstructorBuilder = parent.TypeBuilder.DefineConstructor ( - ca, GetCallingConvention (parent is Class), parameters); + ca, GetCallingConvention (parent is Class), ParameterTypes); // // HACK because System.Reflection.Emit is lame // - ParameterInfo = new InternalParameters (parent, Parameters); - - if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) { + if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) { Report.Error ( 111, Location, "Class `" +parent.Name+ "' already contains a definition with the " + @@ -2365,9 +2334,10 @@ namespace Mono.CSharp { ILGenerator ig = ConstructorBuilder.GetILGenerator (); EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true); - if (parent is Class && ((ModFlags & Modifiers.STATIC) == 0)){ - if (Initializer == null) - Initializer = new ConstructorBaseInitializer (null, parent.Location); + if ((ModFlags & Modifiers.STATIC) == 0){ + if (parent is Class && Initializer == null) + Initializer = new ConstructorBaseInitializer ( + null, Parameters.EmptyReadOnlyParameters, parent.Location); // @@ -2375,293 +2345,292 @@ namespace Mono.CSharp { // `this' access // ec.IsStatic = true; - if (!Initializer.Resolve (ec)) + if (Initializer != null && !Initializer.Resolve (ec)) return; ec.IsStatic = false; } - LabelParameters (ec, ParameterTypes (parent), ConstructorBuilder); + LabelParameters (ec, ParameterTypes, ConstructorBuilder); // // Classes can have base initializers and instance field initializers. // if (parent is Class){ - if ((ModFlags & Modifiers.STATIC) == 0){ + if ((ModFlags & Modifiers.STATIC) == 0) parent.EmitFieldInitializers (ec); - - Initializer.Emit (ec); - } } + if (Initializer != null) + Initializer.Emit (ec); if ((ModFlags & Modifiers.STATIC) != 0) parent.EmitFieldInitializers (ec); Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location); - ec.EmitTopBlock (Block, Location); + // If this is a non-static `struct' constructor and doesn't have any + // initializer, it must initialize all of the struct's fields. + if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && + (Initializer == null)) + Block.AddThisVariable (parent, Location); + + ec.EmitTopBlock (Block, ParameterInfo, Location); } } - // - // Fields and Events both generate FieldBuilders, we use this to share - // their common bits. This is also used to flag usage of the field - // - abstract public class FieldBase : MemberCore { - public readonly string Type; - public readonly Object Initializer; + public class MethodData { + // + // The return type of this method + // + public readonly Type ReturnType; + public readonly Type[] ParameterTypes; + public readonly InternalParameters ParameterInfo; + public readonly CallingConventions CallingConventions; public readonly Attributes OptAttributes; - public FieldBuilder FieldBuilder; - public Status status; + public readonly Location Location; - [Flags] - public enum Status : byte { ASSIGNED = 1, USED = 2 } + // + // Are we implementing an interface ? + // + public bool IsImplementing = false; // - // The constructor is only exposed to our children + // Protected data. // - protected FieldBase (string type, int mod, int allowed_mod, string name, - object init, Attributes attrs, Location loc) - : base (name, loc) - { - Type = type; - ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc); - Initializer = init; - OptAttributes = attrs; + protected MemberBase member; + protected int modifiers; + protected MethodAttributes flags; + protected bool is_method; + protected string accessor_name; + ArrayList conditionals; + + MethodBuilder builder = null; + public MethodBuilder MethodBuilder { + get { + return builder; + } } - } - - // - // The Field class is used to represents class/struct fields during parsing. - // - public class Field : FieldBase { - // - // Modifiers allowed in a class declaration - // - const int AllowedModifiers = - Modifiers.NEW | - Modifiers.PUBLIC | - Modifiers.PROTECTED | - Modifiers.INTERNAL | - Modifiers.PRIVATE | - Modifiers.STATIC | - Modifiers.VOLATILE | - Modifiers.UNSAFE | - Modifiers.READONLY; - public Field (string type, int mod, string name, Object expr_or_array_init, - Attributes attrs, Location loc) - : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc) + public MethodData (MemberBase member, string name, Type return_type, + Type [] parameter_types, InternalParameters parameters, + CallingConventions cc, Attributes opt_attrs, + int modifiers, MethodAttributes flags, bool is_method) { + this.member = member; + this.accessor_name = name; + this.ReturnType = return_type; + this.ParameterTypes = parameter_types; + this.ParameterInfo = parameters; + this.CallingConventions = cc; + this.OptAttributes = opt_attrs; + this.modifiers = modifiers; + this.flags = flags; + this.is_method = is_method; + this.Location = member.Location; + this.conditionals = new ArrayList (); } - public override bool Define (TypeContainer parent) - { - Type t = RootContext.LookupType (parent, Type, false, Location); - - if (t == null) - return false; - - if (!TypeContainer.AsAccessible (t, ModFlags)) - return false; + // + // Attributes. + // + Attribute dllimport_attribute = null; + string obsolete = null; + bool obsolete_error = false; - if (t.IsPointer && !UnsafeOK (parent)) - return false; - - if (RootContext.WarningLevel > 1){ - Type ptype = parent.TypeBuilder.BaseType; + public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method) + { + if ((opt_attrs == null) || (opt_attrs.AttributeSections == null)) + return true; - // ptype is only null for System.Object while compiling corlib. - if (ptype != null){ - MemberInfo [] mi; + foreach (AttributeSection asec in opt_attrs.AttributeSections) { + if (asec.Attributes == null) + continue; - mi = TypeContainer.FindMembers ( - ptype, MemberTypes.Method, - BindingFlags.Public | - BindingFlags.Static | BindingFlags.Instance, - System.Type.FilterName, Name); - } - } - - if ((ModFlags & Modifiers.VOLATILE) != 0){ - if (!t.IsClass){ - if (TypeManager.IsEnumType (t)) - t = TypeManager.EnumToUnderlying (t); - - if (!((t == TypeManager.bool_type) || - (t == TypeManager.sbyte_type) || - (t == TypeManager.byte_type) || - (t == TypeManager.short_type) || - (t == TypeManager.ushort_type) || - (t == TypeManager.int32_type) || - (t == TypeManager.uint32_type) || - (t == TypeManager.char_type) || - (t == TypeManager.float_type))){ - Report.Error ( - 677, Location, parent.MakeName (Name) + - " A volatile field can not be of type `" + - TypeManager.CSharpName (t) + "'"); - return false; + foreach (Attribute a in asec.Attributes) { + if (a.Name == "Conditional") { + if (!ApplyConditionalAttribute (a)) + return false; + } else if (a.Name == "Obsolete") { + if (!ApplyObsoleteAttribute (a)) + return false; + } else if (a.Name.IndexOf ("DllImport") != -1) { + if (!is_method) { + a.Type = TypeManager.dllimport_type; + Attribute.Error_AttributeNotValidForElement (a, Location); + return false; + } + if (!ApplyDllImportAttribute (a)) + return false; } } } - - FieldBuilder = parent.TypeBuilder.DefineField ( - Name, t, Modifiers.FieldAttr (ModFlags)); - TypeManager.RegisterFieldBase (FieldBuilder, this); return true; } - public void Emit (TypeContainer tc) + // + // Applies the `DllImport' attribute to the method. + // + protected virtual bool ApplyDllImportAttribute (Attribute a) { - EmitContext ec = new EmitContext (tc, Location, null, - FieldBuilder.FieldType, ModFlags); + const int extern_static = Modifiers.EXTERN | Modifiers.STATIC; + if ((modifiers & extern_static) != extern_static) { + Report.Error (601, Location, + "The DllImport attribute must be specified on a method " + + "marked `static' and `extern'."); + return false; + } - Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location); + flags |= MethodAttributes.PinvokeImpl; + dllimport_attribute = a; + return true; } - } - // - // `set' and `get' accessors are represented with an Accessor. - // - public class Accessor { // - // Null if the accessor is empty, or a Block if not + // Applies the `Obsolete' attribute to the method. // - public Block Block; - public Attributes OptAttributes; - - public Accessor (Block b, Attributes attrs) + protected virtual bool ApplyObsoleteAttribute (Attribute a) { - Block = b; - OptAttributes = attrs; + if (obsolete != null) { + Report.Error (579, Location, "Duplicate `Obsolete' attribute"); + return false; + } + + obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error); + return obsolete != null; } - } - - public class Property : MemberCore { - public readonly string Type; - public Accessor Get, Set; - public PropertyBuilder PropertyBuilder; - public Attributes OptAttributes; - public MethodBuilder GetBuilder, SetBuilder; // - // The type, once we compute it. - Type PropertyType; + // Applies the `Conditional' attribute to the method. + // + protected virtual bool ApplyConditionalAttribute (Attribute a) + { + // The Conditional attribute is only valid on methods. + if (!is_method) { + Attribute.Error_AttributeNotValidForElement (a, Location); + return false; + } - bool explicit_impl; + string condition = a.Conditional_GetConditionName (); - const int AllowedModifiers = - Modifiers.NEW | - Modifiers.PUBLIC | - Modifiers.PROTECTED | - Modifiers.INTERNAL | - Modifiers.PRIVATE | - Modifiers.STATIC | - Modifiers.SEALED | - Modifiers.OVERRIDE | - Modifiers.ABSTRACT | - Modifiers.UNSAFE | - Modifiers.EXTERN | - Modifiers.VIRTUAL; + if (condition == null) + return false; - public Property (string type, string name, int mod_flags, - Accessor get_block, Accessor set_block, - Attributes attrs, Location loc) - : base (name, loc) - { - Type = type; - ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc); - Get = get_block; - Set = set_block; - OptAttributes = attrs; + if (ReturnType != TypeManager.void_type) { + Report.Error (578, Location, + "Conditional not valid on `" + member.Name + "' " + + "because its return type is not void"); + return false; + } + + if ((modifiers & Modifiers.OVERRIDE) != 0) { + Report.Error (243, Location, + "Conditional not valid on `" + member.Name + "' " + + "because it is an override method"); + return false; + } + + if (member.IsExplicitImpl) { + Report.Error (577, Location, + "Conditional not valid on `" + member.Name + "' " + + "because it is an explicit interface implementation"); + return false; + } + + if (IsImplementing) { + Report.Error (623, Location, + "Conditional not valid on `" + member.Name + "' " + + "because it is an interface method"); + return false; + } + + conditionals.Add (condition); + + return true; } // - // Checks our base implementation if any + // Checks whether this method should be ignored due to its Conditional attributes. // - bool CheckBase (MethodAttributes flags, TypeContainer parent) + bool ShouldIgnore (Location loc) { - // - // Find properties with the same name on the base class - // + // When we're overriding a virtual method, we implicitly inherit the + // Conditional attributes from our parent. + if (member.ParentMethod != null) { + TypeManager.MethodFlags flags = TypeManager.GetMethodFlags ( + member.ParentMethod, loc); - MemberInfo [] props; - MemberInfo [] props_static = TypeManager.MemberLookup ( - parent.TypeBuilder, - parent.TypeBuilder.BaseType, - MemberTypes.Property, BindingFlags.Public | BindingFlags.Static, - Name); + if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0) + return true; + } - MemberInfo [] props_instance = TypeManager.MemberLookup ( - parent.TypeBuilder, - parent.TypeBuilder.BaseType, - MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance, - Name); + foreach (string condition in conditionals) + if (RootContext.AllDefines [condition] == null) + return true; - // - // Find if we have anything - // - if (props_static != null && props_static.Length > 0) - props = props_static; - else if (props_instance != null && props_instance.Length > 0) - props = props_instance; - else - props = null; + return false; + } - // - // If we have something on the base. - if (props != null && props.Length > 0){ - if (props.Length > 1) - throw new Exception ("Should not happen"); - - PropertyInfo pi = (PropertyInfo) props [0]; + // + // Returns the TypeManager.MethodFlags for this method. + // This emits an error 619 / warning 618 if the method is obsolete. + // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned. + // + public virtual TypeManager.MethodFlags GetMethodFlags (Location loc) + { + TypeManager.MethodFlags flags = 0; - MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi); - MethodInfo inherited_set = TypeManager.GetPropertySetter (pi); + if (obsolete != null) { + if (obsolete_error) { + Report.Error (619, loc, "Method `" + member.Name + + "' is obsolete: `" + obsolete + "'"); + return TypeManager.MethodFlags.IsObsoleteError; + } else + Report.Warning (618, loc, "Method `" + member.Name + + "' is obsolete: `" + obsolete + "'"); - MethodInfo reference = inherited_get == null ? - inherited_set : inherited_get; - - if (reference != null) - if (!CheckMethodAgainstBase (parent, flags, reference)) - return false; - - } else { - if ((ModFlags & Modifiers.NEW) != 0) - WarningNotHiding (parent); - - if ((ModFlags & Modifiers.OVERRIDE) != 0){ - Report.Error (115, Location, - parent.MakeName (Name) + - " no suitable properties found to override"); - return false; - } + flags |= TypeManager.MethodFlags.IsObsolete; } - return true; + + if (ShouldIgnore (loc)) + flags |= TypeManager.MethodFlags.ShouldIgnore; + + return flags; } - bool DefineMethod (TypeContainer parent, Type iface_type, string short_name, - MethodAttributes flags, bool is_get) + public virtual bool Define (TypeContainer parent) { - Type [] parameters = TypeManager.NoTypes; MethodInfo implementing = null; - Type fn_type; - string name; + string method_name, name, prefix; - if (is_get){ - fn_type = PropertyType; - name = "get_" + short_name; - } else { - name = "set_" + short_name; - parameters = new Type [1]; - parameters [0] = PropertyType; - fn_type = TypeManager.void_type; - } + if (OptAttributes != null) + if (!ApplyAttributes (OptAttributes, is_method)) + return false; + + if (member.IsExplicitImpl) + prefix = member.InterfaceType.FullName + "."; + else + prefix = ""; + + if (accessor_name != null) + name = accessor_name + "_" + member.ShortName; + else + name = member.ShortName; + method_name = prefix + name; + + if (parent.Pending != null){ + if (member is Indexer) + implementing = parent.Pending.IsInterfaceIndexer ( + member.InterfaceType, ReturnType, ParameterTypes); + else + implementing = parent.Pending.IsInterfaceMethod ( + member.InterfaceType, name, ReturnType, ParameterTypes); - if (parent.Pending != null) - implementing = parent.Pending.IsInterfaceMethod ( - iface_type, name, fn_type, parameters); + if (member.InterfaceType != null && implementing == null){ + TypeContainer.Error_ExplicitInterfaceNotMemberInterface ( + Location, name); + return false; + } + } // // For implicit implementations, make sure we are public, for @@ -2675,25 +2644,22 @@ namespace Mono.CSharp { // The "candidate" function has been flagged already // but it wont get cleared // - if (iface_type == null){ + if (!member.IsExplicitImpl){ // // We already catch different accessibility settings // so we just need to check that we are not private // - if ((ModFlags & Modifiers.PRIVATE) != 0) + if ((modifiers & Modifiers.PRIVATE) != 0) implementing = null; // // Static is not allowed // - if ((ModFlags & Modifiers.STATIC) != 0) + if ((modifiers & Modifiers.STATIC) != 0) implementing = null; } else { - if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){ - Report.Error ( - 106, Location, "`public' or `abstract' modifiers "+ - "are not allowed in explicit interface declarations" - ); + if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){ + Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract"); implementing = null; } } @@ -2713,190 +2679,773 @@ namespace Mono.CSharp { MethodAttributes.Virtual | MethodAttributes.HideBySig; - // - // clear the pending implemntation flag - // - parent.Pending.ImplementMethod ( - iface_type, name, fn_type, parameters, explicit_impl); + // Get the method name from the explicit interface. + if (member.InterfaceType != null) { + name = implementing.Name; + method_name = prefix + name; + } + + IsImplementing = true; } // - // If this is not an explicit interface implementation, - // clear implementing, as it is only used for explicit - // interface implementation + // Create the MethodBuilder for the method // - if (Name.IndexOf (".") == -1) - implementing = null; - - if (is_get){ - GetBuilder = parent.TypeBuilder.DefineMethod ( - name, flags, PropertyType, null); - PropertyBuilder.SetGetMethod (GetBuilder); - - if (implementing != null) - parent.TypeBuilder.DefineMethodOverride ( - GetBuilder, implementing); - - // - // HACK because System.Reflection.Emit is lame - // - InternalParameters ip = new InternalParameters ( - parent, Parameters.GetEmptyReadOnlyParameters ()); - - if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) { - Report.Error (111, Location, - "Class `" + parent.Name + - "' already contains a definition with the " + - "same return value and parameter types as the " + - "'get' method of property `" + Name + "'"); + if ((flags & MethodAttributes.PinvokeImpl) != 0) { + if ((modifiers & Modifiers.STATIC) == 0) { + Report.Error (601, Location, + "The DllImport attribute must be specified on " + + "a method marked 'static' and 'extern'."); return false; } - } else { - SetBuilder = parent.TypeBuilder.DefineMethod ( - name, flags, null, parameters); - if (implementing != null) - parent.TypeBuilder.DefineMethodOverride ( - SetBuilder, implementing); + EmitContext ec = new EmitContext ( + parent, Location, null, ReturnType, modifiers); - SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); - PropertyBuilder.SetSetMethod (SetBuilder); + builder = dllimport_attribute.DefinePInvokeMethod ( + ec, parent.TypeBuilder, method_name, flags, + ReturnType, ParameterTypes); + } else + builder = parent.TypeBuilder.DefineMethod ( + method_name, flags, CallingConventions, + ReturnType, ParameterTypes); + + if (builder == null) + return false; + if (IsImplementing) { // - // HACK because System.Reflection.Emit is lame + // clear the pending implemntation flag // - Parameter [] parms = new Parameter [1]; - parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null); - InternalParameters ip = new InternalParameters ( - parent, new Parameters (parms, null, Location)); + if (member is Indexer) { + parent.Pending.ImplementIndexer ( + member.InterfaceType, builder, ReturnType, + ParameterTypes, true); + } else + parent.Pending.ImplementMethod ( + member.InterfaceType, name, ReturnType, + ParameterTypes, member.IsExplicitImpl); - if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) { - Report.Error ( - 111, Location, - "Class `" + parent.Name + - "' already contains a definition with the " + - "same return value and parameter types as the " + - "'set' method of property `" + Name + "'"); - return false; - } + if (member.IsExplicitImpl) + parent.TypeBuilder.DefineMethodOverride ( + builder, implementing); + } + + if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) { + Report.Error (111, Location, + "Class `" + parent.Name + + "' already contains a definition with the " + + "same return value and parameter types as the " + + "'get' method of property `" + member.Name + "'"); + return false; } + TypeManager.AddMethod (builder, this); + return true; } - public override bool Define (TypeContainer parent) + // + // Emits the code + // + public virtual void Emit (TypeContainer parent, Block block, object kind) { - Type iface_type = null; - string short_name; - - if (!parent.MethodModifiersValid (ModFlags, Name, Location)) - return false; + ILGenerator ig; + EmitContext ec; - MethodAttributes flags = Modifiers.MethodAttr (ModFlags); - - flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName; + if ((flags & MethodAttributes.PinvokeImpl) == 0) + ig = builder.GetILGenerator (); + else + ig = null; - // Lookup Type, verify validity - PropertyType = RootContext.LookupType (parent, Type, false, Location); - if (PropertyType == null) - return false; + ec = new EmitContext (parent, Location, ig, ReturnType, modifiers); - // verify accessibility - if (!TypeContainer.AsAccessible (PropertyType, ModFlags)) - return false; + if (OptAttributes != null) + Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location); - if (PropertyType.IsPointer && !UnsafeOK (parent)) - return false; - - if (!CheckBase (flags, parent)) - return false; + if (member is MethodCore) + ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder); // - // Check for explicit interface implementation + // abstract or extern methods have no bodies // - if (Name.IndexOf (".") != -1){ - int pos = Name.LastIndexOf ("."); - string iface = Name.Substring (0, pos); + if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){ + if (block == null) + return; - iface_type = RootContext.LookupType (parent, iface, false, Location); - if (iface_type == null) - return false; + // + // abstract or extern methods have no bodies. + // + if ((modifiers & Modifiers.ABSTRACT) != 0) + Report.Error ( + 500, Location, "Abstract method `" + + TypeManager.CSharpSignature (builder) + + "' can not have a body"); - short_name = Name.Substring (pos + 1); + if ((modifiers & Modifiers.EXTERN) != 0) + Report.Error ( + 179, Location, "External method `" + + TypeManager.CSharpSignature (builder) + + "' can not have a body"); - // Compute the full name that we need to export. - Name = iface_type.FullName + "." + short_name; - explicit_impl = true; - } else { - explicit_impl = false; - short_name = Name; + return; } - // FIXME - PropertyAttributes.HasDefault ? - - PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName | - PropertyAttributes.SpecialName; - - PropertyBuilder = parent.TypeBuilder.DefineProperty ( - Name, prop_attr, PropertyType, null); - - if (Get != null) - if (!DefineMethod (parent, iface_type, short_name, flags, true)) - return false; - - if (Set != null) - if (!DefineMethod (parent, iface_type, short_name, flags, false)) - return false; - // - // HACK for the reasons exposed above + // Methods must have a body unless they're extern or abstract // - if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) { + if (block == null) { Report.Error ( - 111, Location, - "Class `" + parent.Name + - "' already contains a definition for the property `" + - Name + "'"); - return false; + 501, Location, "Method `" + + TypeManager.CSharpSignature (builder) + + "' must declare a body since it is not marked " + + "abstract or extern"); + return; } - return true; + // + // Handle destructors specially + // + // FIXME: This code generates buggy code + // + if (member.Name == "Finalize" && ReturnType == TypeManager.void_type) + EmitDestructor (ec, block); + else { + ISymbolWriter sw = CodeGen.SymbolWriter; + + if ((sw != null) && !Location.IsNull (Location) && + !Location.IsNull (block.EndLocation)) { + Location end = block.EndLocation; + MethodToken token = MethodBuilder.GetToken (); + sw.OpenMethod (new SymbolToken (token.Token)); + sw.SetMethodSourceRange (Location.SymbolDocument, + Location.Row, 0, + end.SymbolDocument, + end.Row, 0); + + ec.EmitTopBlock (block, ParameterInfo, Location); + + sw.CloseMethod (); + } else + ec.EmitTopBlock (block, ParameterInfo, Location); + } } - - public void Emit (TypeContainer tc) + + void EmitDestructor (EmitContext ec, Block block) { - ILGenerator ig; - EmitContext ec; + ILGenerator ig = ec.ig; + + Label finish = ig.DefineLabel (); + bool old_in_try = ec.InTry; + + ig.BeginExceptionBlock (); + ec.InTry = true; + ec.ReturnLabel = finish; + ec.HasReturnLabel = true; + ec.EmitTopBlock (block, null, Location); + ec.InTry = old_in_try; + + // ig.MarkLabel (finish); + bool old_in_finally = ec.InFinally; + ec.InFinally = true; + ig.BeginFinallyBlock (); + + if (ec.ContainerType.BaseType != null) { + Expression member_lookup = Expression.MemberLookup ( + ec, ec.ContainerType.BaseType, "Finalize", + MemberTypes.Method, Expression.AllBindingFlags, Location); - ec = new EmitContext (tc, Location, null, PropertyType, ModFlags); - Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location); + if (member_lookup != null){ + MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup); + + ig.Emit (OpCodes.Ldarg_0); + ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]); + } + } + ec.InFinally = old_in_finally; + ig.EndExceptionBlock (); + //ig.MarkLabel (ec.ReturnLabel); + ig.Emit (OpCodes.Ret); + } + } - // - // abstract or extern properties have no bodies - // - if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0) - return; + abstract public class MemberBase : MemberCore { + public Expression Type; + public readonly Attributes OptAttributes; - if (Get != null){ - ig = GetBuilder.GetILGenerator (); - ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags); + protected MethodAttributes flags; - Attribute.ApplyAttributes (ec, GetBuilder, Get, Get.OptAttributes, Location); - ec.EmitTopBlock (Get.Block, Location); - } + // + // The "short" name of this property / indexer / event. This is the + // name without the explicit interface. + // + public string ShortName; - if (Set != null){ - ig = SetBuilder.GetILGenerator (); - ec = new EmitContext (tc, Location, ig, null, ModFlags); + // + // The type of this property / indexer / event + // + public Type MemberType; + + // + // If true, this is an explicit interface implementation + // + public bool IsExplicitImpl = false; + + // + // The name of the interface we are explicitly implementing + // + public string ExplicitInterfaceName = null; + + // + // If true, the interface type we are explicitly implementing + // + public Type InterfaceType = null; + + // + // The method we're overriding if this is an override method. + // + protected MethodInfo parent_method = null; + public MethodInfo ParentMethod { + get { + return parent_method; + } + } + + // + // The constructor is only exposed to our children + // + protected MemberBase (Expression type, int mod, int allowed_mod, string name, + Attributes attrs, Location loc) + : base (name, loc) + { + Type = type; + ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc); + OptAttributes = attrs; + } + + protected virtual bool CheckBase (TypeContainer parent) + { + return true; + } + + protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters) + { + bool error = false; + + foreach (Type partype in parameters){ + if (partype.IsPointer && !UnsafeOK (parent)) + error = true; + + if (parent.AsAccessible (partype, ModFlags)) + continue; + + if (this is Indexer) + Report.Error (55, Location, + "Inconsistent accessibility: parameter type `" + + TypeManager.CSharpName (partype) + "' is less " + + "accessible than indexer `" + Name + "'"); + else + Report.Error (51, Location, + "Inconsistent accessibility: parameter type `" + + TypeManager.CSharpName (partype) + "' is less " + + "accessible than method `" + Name + "'"); + error = true; + } + + return !error; + } + + protected virtual bool DoDefine (TypeContainer parent) + { + if (Name == null) + Name = "this"; + + if (!parent.MethodModifiersValid (ModFlags, Name, Location)) + return false; + + flags = Modifiers.MethodAttr (ModFlags); + + // Lookup Type, verify validity + MemberType = parent.ResolveType (Type, false, Location); + if (MemberType == null) + return false; + + // verify accessibility + if (!parent.AsAccessible (MemberType, ModFlags)) { + if (this is Property) + Report.Error (53, Location, + "Inconsistent accessibility: property type `" + + TypeManager.CSharpName (MemberType) + "' is less " + + "accessible than property `" + Name + "'"); + else if (this is Indexer) + Report.Error (54, Location, + "Inconsistent accessibility: indexer return type `" + + TypeManager.CSharpName (MemberType) + "' is less " + + "accessible than indexer `" + Name + "'"); + else if (this is Method) + Report.Error (50, Location, + "Inconsistent accessibility: return type `" + + TypeManager.CSharpName (MemberType) + "' is less " + + "accessible than method `" + Name + "'"); + else + Report.Error (52, Location, + "Inconsistent accessibility: field type `" + + TypeManager.CSharpName (MemberType) + "' is less " + + "accessible than field `" + Name + "'"); + return false; + } + + if (MemberType.IsPointer && !UnsafeOK (parent)) + return false; + + // + // Check for explicit interface implementation + // + if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){ + int pos = Name.LastIndexOf ("."); + + ExplicitInterfaceName = Name.Substring (0, pos); + ShortName = Name.Substring (pos + 1); + } else + ShortName = Name; + + if (ExplicitInterfaceName != null) { + InterfaceType = RootContext.LookupType ( + parent, ExplicitInterfaceName, false, Location); + if (InterfaceType == null) + return false; + + // Compute the full name that we need to export. + Name = InterfaceType.FullName + "." + ShortName; + + if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location)) + return false; + + IsExplicitImpl = true; + } else + IsExplicitImpl = false; + + return true; + } + } + + // + // Fields and Events both generate FieldBuilders, we use this to share + // their common bits. This is also used to flag usage of the field + // + abstract public class FieldBase : MemberBase { + public FieldBuilder FieldBuilder; + public Status status; + + [Flags] + public enum Status : byte { ASSIGNED = 1, USED = 2 } + + // + // The constructor is only exposed to our children + // + protected FieldBase (Expression type, int mod, int allowed_mod, string name, + object init, Attributes attrs, Location loc) + : base (type, mod, allowed_mod, name, attrs, loc) + { + this.init = init; + } + + // + // Whether this field has an initializer. + // + public bool HasInitializer { + get { + return init != null; + } + } + + // Private. + readonly Object init; + Expression init_expr; + bool init_expr_initialized = false; + + // + // Resolves and returns the field initializer. + // + public Expression GetInitializerExpression (EmitContext ec) + { + if (init_expr_initialized) + return init_expr; + + Expression e; + if (init is Expression) + e = (Expression) init; + else + e = new ArrayCreation (Type, "", (ArrayList)init, Location); + + ec.IsFieldInitializer = true; + e = e.DoResolve (ec); + ec.IsFieldInitializer = false; + + init_expr = e; + init_expr_initialized = true; + + return init_expr; + } + } + + // + // The Field class is used to represents class/struct fields during parsing. + // + public class Field : FieldBase { + // + // Modifiers allowed in a class declaration + // + const int AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.STATIC | + Modifiers.VOLATILE | + Modifiers.UNSAFE | + Modifiers.READONLY; + + public Field (Expression type, int mod, string name, Object expr_or_array_init, + Attributes attrs, Location loc) + : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc) + { + } + + public override bool Define (TypeContainer parent) + { + Type t = parent.ResolveType (Type, false, Location); + + if (t == null) + return false; + + if (!parent.AsAccessible (t, ModFlags)) { + Report.Error (52, Location, + "Inconsistent accessibility: field type `" + + TypeManager.CSharpName (t) + "' is less " + + "accessible than field `" + Name + "'"); + return false; + } + + if (t.IsPointer && !UnsafeOK (parent)) + return false; + + if (RootContext.WarningLevel > 1){ + Type ptype = parent.TypeBuilder.BaseType; + + // ptype is only null for System.Object while compiling corlib. + if (ptype != null){ + TypeContainer.FindMembers ( + ptype, MemberTypes.Method, + BindingFlags.Public | + BindingFlags.Static | BindingFlags.Instance, + System.Type.FilterName, Name); + } + } + + if ((ModFlags & Modifiers.VOLATILE) != 0){ + if (!t.IsClass){ + if (TypeManager.IsEnumType (t)) + t = TypeManager.EnumToUnderlying (t); + + if (!((t == TypeManager.bool_type) || + (t == TypeManager.sbyte_type) || + (t == TypeManager.byte_type) || + (t == TypeManager.short_type) || + (t == TypeManager.ushort_type) || + (t == TypeManager.int32_type) || + (t == TypeManager.uint32_type) || + (t == TypeManager.char_type) || + (t == TypeManager.float_type))){ + Report.Error ( + 677, Location, parent.MakeName (Name) + + " A volatile field can not be of type `" + + TypeManager.CSharpName (t) + "'"); + return false; + } + } + } + + FieldBuilder = parent.TypeBuilder.DefineField ( + Name, t, Modifiers.FieldAttr (ModFlags)); + + TypeManager.RegisterFieldBase (FieldBuilder, this); + return true; + } + + public void Emit (TypeContainer tc) + { + EmitContext ec = new EmitContext (tc, Location, null, + FieldBuilder.FieldType, ModFlags); + + Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location); + } + } + + // + // `set' and `get' accessors are represented with an Accessor. + // + public class Accessor { + // + // Null if the accessor is empty, or a Block if not + // + public Block Block; + public Attributes OptAttributes; + + public Accessor (Block b, Attributes attrs) + { + Block = b; + OptAttributes = attrs; + } + } + + // + // Properties and Indexers both generate PropertyBuilders, we use this to share + // their common bits. + // + abstract public class PropertyBase : MethodCore { + public Accessor Get, Set; + public PropertyBuilder PropertyBuilder; + public MethodBuilder GetBuilder, SetBuilder; + public MethodData GetData, SetData; + + protected EmitContext ec; + + public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod, + Parameters parameters, Accessor get_block, Accessor set_block, + Attributes attrs, Location loc) + : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc) + { + Get = get_block; + Set = set_block; + } + + protected override bool DoDefine (TypeContainer parent) + { + if (!base.DoDefine (parent)) + return false; + + ec = new EmitContext (parent, Location, null, MemberType, ModFlags); + + return true; + } + + // + // Checks our base implementation if any + // + protected override bool CheckBase (TypeContainer parent) + { + // Check whether arguments were correct. + if (!DoDefineParameters (parent)) + return false; + + MethodSignature ms = new MethodSignature (Name, null, ParameterTypes); + MemberList props_this; + + props_this = TypeContainer.FindMembers ( + parent.TypeBuilder, MemberTypes.Property, + BindingFlags.NonPublic | BindingFlags.Public | + BindingFlags.Static | BindingFlags.Instance | + BindingFlags.DeclaredOnly, + MethodSignature.method_signature_filter, ms); + + if (props_this.Count > 0) { + Report.Error (111, Location, "Class `" + parent.Name + "' " + + "already defines a member called `" + Name + "' " + + "with the same parameter types"); + return false; + } + + // + // Find properties with the same name on the base class + // + MemberList props; + MemberList props_static = TypeContainer.FindMembers ( + parent.TypeBuilder.BaseType, MemberTypes.Property, + BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, + MethodSignature.inheritable_property_signature_filter, ms); + + MemberList props_instance = TypeContainer.FindMembers ( + parent.TypeBuilder.BaseType, MemberTypes.Property, + BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, + MethodSignature.inheritable_property_signature_filter, + ms); + + // + // Find if we have anything + // + if (props_static.Count > 0) + props = props_static; + else if (props_instance.Count > 0) + props = props_instance; + else + props = null; + + // + // If we have something on the base. + if (props != null && props.Count > 0){ + PropertyInfo pi = (PropertyInfo) props [0]; + + MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi); + MethodInfo inherited_set = TypeManager.GetPropertySetter (pi); + + MethodInfo reference = inherited_get == null ? + inherited_set : inherited_get; + + if (reference != null) { + string name = reference.DeclaringType.Name + "." + Name; + + if (!CheckMethodAgainstBase (parent, flags, reference, name)) + return false; + } + + if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) { + Report.Error (508, parent.MakeName (Name) + ": cannot " + + "change return type when overriding inherited " + + "member `" + pi.DeclaringType + "." + pi.Name + "'"); + return false; + } + } else { + if ((ModFlags & Modifiers.NEW) != 0) + WarningNotHiding (parent); + + if ((ModFlags & Modifiers.OVERRIDE) != 0){ + if (this is Indexer) + Report.Error (115, Location, + parent.MakeName (Name) + + " no suitable indexers found to override"); + else + Report.Error (115, Location, + parent.MakeName (Name) + + " no suitable properties found to override"); + return false; + } + } + return true; + } + + public void Emit (TypeContainer tc) + { + // + // The PropertyBuilder can be null for explicit implementations, in that + // case, we do not actually emit the ".property", so there is nowhere to + // put the attribute + // + if (PropertyBuilder != null) + Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location); + + if (GetData != null) + GetData.Emit (tc, Get.Block, Get); + + if (SetData != null) + SetData.Emit (tc, Set.Block, Set); + } + } + + public class Property : PropertyBase { + const int AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.STATIC | + Modifiers.SEALED | + Modifiers.OVERRIDE | + Modifiers.ABSTRACT | + Modifiers.UNSAFE | + Modifiers.EXTERN | + Modifiers.VIRTUAL; + + public Property (Expression type, string name, int mod_flags, + Accessor get_block, Accessor set_block, + Attributes attrs, Location loc) + : base (type, name, mod_flags, AllowedModifiers, + Parameters.EmptyReadOnlyParameters, + get_block, set_block, attrs, loc) + { + } + + public override bool Define (TypeContainer parent) + { + if (!DoDefine (parent)) + return false; + + if (!CheckBase (parent)) + return false; + + flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName; + + if (Get != null) { + Type [] parameters = TypeManager.NoTypes; + + InternalParameters ip = new InternalParameters ( + parent, Parameters.EmptyReadOnlyParameters); + + GetData = new MethodData (this, "get", MemberType, + parameters, ip, CallingConventions.Standard, + Get.OptAttributes, ModFlags, flags, false); + + if (!GetData.Define (parent)) + return false; + + GetBuilder = GetData.MethodBuilder; + } + + if (Set != null) { + Type [] parameters = new Type [1]; + parameters [0] = MemberType; + + Parameter [] parms = new Parameter [1]; + parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null); + InternalParameters ip = new InternalParameters ( + parent, new Parameters (parms, null, Location)); + + SetData = new MethodData (this, "set", TypeManager.void_type, + parameters, ip, CallingConventions.Standard, + Set.OptAttributes, ModFlags, flags, false); + + if (!SetData.Define (parent)) + return false; + + SetBuilder = SetData.MethodBuilder; + SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); + } + + // FIXME - PropertyAttributes.HasDefault ? + + PropertyAttributes prop_attr = + PropertyAttributes.RTSpecialName | + PropertyAttributes.SpecialName; + + if (!IsExplicitImpl){ + PropertyBuilder = parent.TypeBuilder.DefineProperty ( + Name, prop_attr, MemberType, null); + + if (Get != null) + PropertyBuilder.SetGetMethod (GetBuilder); + + if (Set != null) + PropertyBuilder.SetSetMethod (SetBuilder); - Attribute.ApplyAttributes (ec, SetBuilder, Set, Set.OptAttributes, Location); - ec.EmitTopBlock (Set.Block, Location); + // + // HACK for the reasons exposed above + // + if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) { + Report.Error ( + 111, Location, + "Class `" + parent.Name + + "' already contains a definition for the property `" + + Name + "'"); + return false; + } } + return true; } } - /// /// Gigantic workaround for lameness in SRE follows : /// This class derives from EventInfo and attempts to basically @@ -3050,10 +3599,10 @@ namespace Mono.CSharp { public readonly Accessor Remove; public MyEventBuilder EventBuilder; - Type EventType; MethodBuilder AddBuilder, RemoveBuilder; + MethodData AddData, RemoveData; - public Event (string type, string name, Object init, int mod, Accessor add, + public Event (Expression type, string name, Object init, int mod, Accessor add, Accessor remove, Attributes attrs, Location loc) : base (type, mod, AllowedModifiers, name, init, attrs, loc) { @@ -3063,97 +3612,75 @@ namespace Mono.CSharp { public override bool Define (TypeContainer parent) { - if (!parent.MethodModifiersValid (ModFlags, Name, Location)) - return false; - - MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags); EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName; - EventType = RootContext.LookupType (parent, Type, false, Location); - if (EventType == null) - return false; - - if (!TypeContainer.AsAccessible (EventType, ModFlags)) + if (!DoDefine (parent)) return false; - if (EventType.IsPointer && !UnsafeOK (parent)) - return false; - - if (!EventType.IsSubclassOf (TypeManager.delegate_type)) { + if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) { Report.Error (66, Location, "'" + parent.Name + "." + Name + "' : event must be of a delegate type"); return false; } - - Type [] parameters = new Type [1]; - parameters [0] = EventType; - EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType); + Type [] parameter_types = new Type [1]; + parameter_types [0] = MemberType; - if (Add == null && Remove == null){ - FieldBuilder = parent.TypeBuilder.DefineField ( - Name, EventType, FieldAttributes.Private); - TypeManager.RegisterFieldBase (FieldBuilder, this); - } - - // - // Now define the accessors - // - string add_name = "add_" + Name; - - AddBuilder = parent.TypeBuilder.DefineMethod ( - add_name, m_attr, null, parameters); - AddBuilder.DefineParameter (1, ParameterAttributes.None, "value"); - EventBuilder.SetAddOnMethod (AddBuilder); - if (parent.Pending != null) - parent.Pending.ImplementMethod (null, add_name, null, parameters, false); - - // - // HACK because System.Reflection.Emit is lame - // Parameter [] parms = new Parameter [1]; parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null); InternalParameters ip = new InternalParameters ( - parent, new Parameters (parms, null, Location)); - - if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) { - Report.Error (111, Location, - "Class `" + parent.Name + "' already contains a definition with the " + - "same return value and parameter types for the " + - "'add' method of event `" + Name + "'"); - return false; - } + parent, new Parameters (parms, null, Location)); - string remove_name = "remove_" + Name; - RemoveBuilder = parent.TypeBuilder.DefineMethod ( - remove_name, m_attr, null, parameters); - RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value"); - EventBuilder.SetRemoveOnMethod (RemoveBuilder); + if (!CheckBase (parent)) + return false; // - // This looks like dead code + // Now define the accessors // - //if (parent.Pending != null) - // parent.Pending.IsInterfaceMethod (null, remove_name, null, parameters, false); + AddData = new MethodData (this, "add", TypeManager.void_type, + parameter_types, ip, CallingConventions.Standard, + (Add != null) ? Add.OptAttributes : null, + ModFlags, flags, false); - // - // HACK because System.Reflection.Emit is lame - // + if (!AddData.Define (parent)) + return false; + + AddBuilder = AddData.MethodBuilder; + AddBuilder.DefineParameter (1, ParameterAttributes.None, "value"); + + RemoveData = new MethodData (this, "remove", TypeManager.void_type, + parameter_types, ip, CallingConventions.Standard, + (Remove != null) ? Remove.OptAttributes : null, + ModFlags, flags, false); - if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) { - Report.Error (111, Location, - "Class `" + parent.Name + "' already contains a definition with the " + - "same return value and parameter types for the " + - "'remove' method of event `" + Name + "'"); + if (!RemoveData.Define (parent)) return false; - } + + RemoveBuilder = RemoveData.MethodBuilder; + RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value"); + + if (!IsExplicitImpl){ + EventBuilder = new MyEventBuilder ( + parent.TypeBuilder, Name, e_attr, MemberType); + + if (Add == null && Remove == null) { + FieldBuilder = parent.TypeBuilder.DefineField ( + Name, MemberType, FieldAttributes.FamANDAssem); + TypeManager.RegisterPrivateFieldOfEvent ( + (EventInfo) EventBuilder, FieldBuilder); + TypeManager.RegisterFieldBase (FieldBuilder, this); + } - if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) { - Report.Error (111, Location, - "Class `" + parent.Name + - "' already contains a definition for the event `" + - Name + "'"); - return false; + EventBuilder.SetAddOnMethod (AddBuilder); + EventBuilder.SetRemoveOnMethod (RemoveBuilder); + + if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) { + Report.Error (111, Location, + "Class `" + parent.Name + + "' already contains a definition for the event `" + + Name + "'"); + return false; + } } return true; @@ -3168,43 +3695,47 @@ namespace Mono.CSharp { method = TypeManager.delegate_combine_delegate_delegate; else method = TypeManager.delegate_remove_delegate_delegate; - - ig.Emit (OpCodes.Ldarg_0); - ig.Emit (OpCodes.Ldarg_0); - ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder); - ig.Emit (OpCodes.Ldarg_1); - ig.Emit (OpCodes.Call, method); - ig.Emit (OpCodes.Castclass, EventType); - ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder); + + if ((ModFlags & Modifiers.STATIC) != 0) { + ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder); + ig.Emit (OpCodes.Ldarg_0); + ig.Emit (OpCodes.Call, method); + ig.Emit (OpCodes.Castclass, MemberType); + ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder); + } else { + ig.Emit (OpCodes.Ldarg_0); + ig.Emit (OpCodes.Ldarg_0); + ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder); + ig.Emit (OpCodes.Ldarg_1); + ig.Emit (OpCodes.Call, method); + ig.Emit (OpCodes.Castclass, MemberType); + ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder); + } ig.Emit (OpCodes.Ret); } public void Emit (TypeContainer tc) { EmitContext ec; - ILGenerator ig; - ig = AddBuilder.GetILGenerator (); - ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags); + ec = new EmitContext (tc, Location, null, MemberType, ModFlags); + Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location); - if (Add != null) { - Attribute.ApplyAttributes (ec, AddBuilder, Add, Add.OptAttributes, Location); - ec.EmitTopBlock (Add.Block, Location); - } else + if (Add != null) + AddData.Emit (tc, Add.Block, Add); + else { + ILGenerator ig = AddData.MethodBuilder.GetILGenerator (); + ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags); EmitDefaultMethod (ec, true); + } - ig = RemoveBuilder.GetILGenerator (); - ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags); - - if (Remove != null) { - Attribute.ApplyAttributes (ec, RemoveBuilder, Remove, Remove.OptAttributes, Location); - ec.EmitTopBlock (Remove.Block, Location); - } else + if (Remove != null) + RemoveData.Emit (tc, Remove.Block, Remove); + else { + ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator (); + ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags); EmitDefaultMethod (ec, false); - - ec = new EmitContext (tc, Location, null, EventType, ModFlags); - Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location); - + } } } @@ -3219,7 +3750,7 @@ namespace Mono.CSharp { // // int this [ args ] - public class Indexer : MemberCore { + public class Indexer : PropertyBase { const int AllowedModifiers = Modifiers.NEW | @@ -3234,208 +3765,71 @@ namespace Mono.CSharp { Modifiers.EXTERN | Modifiers.ABSTRACT; - public readonly string Type; - public readonly string InterfaceType; - public readonly Parameters FormalParameters; - public readonly Accessor Get, Set; - public Attributes OptAttributes; - public MethodBuilder GetBuilder; - public MethodBuilder SetBuilder; - public PropertyBuilder PropertyBuilder; - public Type IndexerType; public string IndexerName; + public string InterfaceIndexerName; + + // + // Are we implementing an interface ? + // + bool IsImplementing = false; - EmitContext ec; - - public Indexer (string type, string int_type, int flags, Parameters parms, + public Indexer (Expression type, string int_type, int flags, Parameters parameters, Accessor get_block, Accessor set_block, Attributes attrs, Location loc) - : base ("", loc) + : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block, + attrs, loc) { - - Type = type; - InterfaceType = int_type; - ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc); - FormalParameters = parms; - Get = get_block; - Set = set_block; - OptAttributes = attrs; + ExplicitInterfaceName = int_type; } - bool DefineMethod (TypeContainer parent, Type iface_type, - Type ret_type, string name, - Type [] parameters, MethodAttributes attr, bool is_get) - { - MethodInfo implementing = null; - bool is_implementation; - - if (parent.Pending != null) - implementing = parent.Pending.IsInterfaceMethod ( - iface_type, name, ret_type, parameters); - - is_implementation = implementing != null; - - // - // Setting null inside this block will trigger a more - // verbose error reporting for missing interface implementations - // - // The "candidate" function has been flagged already - // but it wont get cleared - // - if (implementing != null){ - if (iface_type == null){ - // - // We already catch different accessibility settings - // so we just need to check that we are not private - // - if ((ModFlags & Modifiers.PRIVATE) != 0) - implementing = null; - - // - // Static is not allowed - // - if ((ModFlags & Modifiers.STATIC) != 0) - implementing = null; - } else { - if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){ - Report.Error ( - 106, Location, - "`public' or `abstract' modifiers are not "+ - "allowed in explicit interface declarations" - ); - implementing = null; - } - } - } - if (implementing != null){ - // - // When implementing interface methods, set NewSlot. - // - if (implementing.DeclaringType.IsInterface) - attr |= MethodAttributes.NewSlot; - - attr |= - MethodAttributes.Virtual | - MethodAttributes.HideBySig; - - // - // clear the pending implementing flag - // - parent.Pending.ImplementMethod ( - iface_type, name, ret_type, parameters, true); - } - - // - // If this is not an explicit interface implementation, - // clear implementing, as it is only used for explicit - // interface implementation - // - if (InterfaceType == null) - implementing = null; - - if (is_get){ - string meth_name = "get_" + IndexerName; - if (iface_type != null) - meth_name = iface_type + ".get_" + IndexerName; - - GetBuilder = parent.TypeBuilder.DefineMethod ( - meth_name, attr, IndexerType, parameters); - - if (implementing != null) - parent.TypeBuilder.DefineMethodOverride ( - GetBuilder, implementing); - } else { - string meth_name = "set_" + IndexerName; - - if (iface_type != null) - meth_name = iface_type + ".set_" + IndexerName; - - SetBuilder = parent.TypeBuilder.DefineMethod ( - meth_name, attr, null, parameters); - if (implementing != null) - parent.TypeBuilder.DefineMethodOverride ( - SetBuilder, implementing); - } - - return is_implementation; - } - public override bool Define (TypeContainer parent) { PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName | PropertyAttributes.SpecialName; - bool error = false; - IndexerType = RootContext.LookupType (parent, Type, false, Location); - Type [] parameters = FormalParameters.GetParameterInfo (parent); - - // Check if the return type and arguments were correct - if (IndexerType == null || parameters == null) - return false; - - if (!parent.MethodModifiersValid (ModFlags, InterfaceType == null ? - "this" : InterfaceType, Location)) - return false; - - // - // verify accessibility and unsafe pointers - // - if (!TypeContainer.AsAccessible (IndexerType, ModFlags)) - return false; - - if (IndexerType.IsPointer && !UnsafeOK (parent)) + if (!DoDefine (parent)) return false; - foreach (Type partype in parameters){ - if (!TypeContainer.AsAccessible (partype, ModFlags)) - error = true; - if (partype.IsPointer && !UnsafeOK (parent)) - error = true; + IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes); + if (IndexerName == null) + IndexerName = "Item"; + else if (IsExplicitImpl) + Report.Error (592, Location, + "Attribute 'IndexerName' is not valid on this declaration " + + "type. It is valid on `property' declarations only."); + + ShortName = IndexerName; + if (IsExplicitImpl) { + InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType); + Name = InterfaceType.FullName + "." + IndexerName; + } else { + InterfaceIndexerName = IndexerName; + Name = ShortName; } - if (error) + if (!CheckBase (parent)) return false; - - Type iface_type = null; - - if (InterfaceType != null){ - iface_type = RootContext.LookupType (parent, InterfaceType, false, Location); - if (iface_type == null) - return false; - } - ec = new EmitContext (parent, Location, null, IndexerType, ModFlags); + if (Get != null){ + InternalParameters ip = new InternalParameters (parent, Parameters); - IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes); - if (IndexerName == null) - IndexerName = "Item"; - - MethodAttributes attr = Modifiers.MethodAttr (ModFlags); + GetData = new MethodData (this, "get", MemberType, + ParameterTypes, ip, CallingConventions.Standard, + Get.OptAttributes, ModFlags, flags, false); - bool is_implementing = false; - - if (Get != null){ - is_implementing = DefineMethod ( - parent, iface_type, IndexerType, "get_" + IndexerName, - parameters, attr, true); - InternalParameters pi = new InternalParameters (parent, FormalParameters); - if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) { - Report.Error (111, Location, - "Class `" + parent.Name + - "' already contains a definition with the " + - "same return value and parameter types for the " + - "'get' indexer"); + if (!GetData.Define (parent)) return false; - } + + GetBuilder = GetData.MethodBuilder; } if (Set != null){ - int top = parameters.Length; + int top = ParameterTypes.Length; Type [] set_pars = new Type [top + 1]; - parameters.CopyTo (set_pars, 0); - set_pars [top] = IndexerType; + ParameterTypes.CopyTo (set_pars, 0); + set_pars [top] = MemberType; - Parameter [] fixed_parms = FormalParameters.FixedParameters; + Parameter [] fixed_parms = Parameters.FixedParameters; if (fixed_parms == null){ throw new Exception ("We currently do not support only array arguments in an indexer"); @@ -3462,27 +3856,22 @@ namespace Mono.CSharp { Parameters set_formal_params = new Parameters (tmp, null, Location); - is_implementing = DefineMethod ( - parent, iface_type, TypeManager.void_type, - "set_" + IndexerName, set_pars, attr, false); - InternalParameters ip = new InternalParameters (parent, set_formal_params); - - if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) { - Report.Error ( - 111, Location, - "Class `" + parent.Name + "' already contains a " + - "definition with the " + - "same return value and parameter types for the " + - "'set' indexer"); + + SetData = new MethodData (this, "set", TypeManager.void_type, + set_pars, ip, CallingConventions.Standard, + Set.OptAttributes, ModFlags, flags, false); + + if (!SetData.Define (parent)) return false; - } + + SetBuilder = SetData.MethodBuilder; } // // Now name the parameters // - Parameter [] p = FormalParameters.FixedParameters; + Parameter [] p = Parameters.FixedParameters; if (p != null) { int i; @@ -3500,56 +3889,39 @@ namespace Mono.CSharp { SetBuilder.DefineParameter ( i + 1, ParameterAttributes.None, "value"); - if (i != parameters.Length) { - Parameter array_param = FormalParameters.ArrayParameter; - SetBuilder.DefineParameter (i + 1, array_param.Attributes, - array_param.Name); + if (i != ParameterTypes.Length) { + Parameter array_param = Parameters.ArrayParameter; + SetBuilder.DefineParameter ( + i + 1, array_param.Attributes, array_param.Name); } } + if (GetData != null) + IsImplementing = GetData.IsImplementing; + else if (SetData != null) + IsImplementing = SetData.IsImplementing; // - // Only define the PropertyBuilder if we are not implementing - // an interface property. + // Define the PropertyBuilder if one of the following conditions are met: + // a) we're not implementing an interface indexer. + // b) the indexer has a different IndexerName and this is no + // explicit interface implementation. // - if (!is_implementing){ + if (!IsExplicitImpl) { PropertyBuilder = parent.TypeBuilder.DefineProperty ( - IndexerName, prop_attr, IndexerType, parameters); - TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder); + IndexerName, prop_attr, MemberType, ParameterTypes); - if (GetBuilder != null) + if (GetData != null) PropertyBuilder.SetGetMethod (GetBuilder); - if (SetBuilder != null) + if (SetData != null) PropertyBuilder.SetSetMethod (SetBuilder); - } - - return true; - } - - public void Emit (TypeContainer tc) - { - ILGenerator ig; - - Attribute.ApplyAttributes ( - ec, PropertyBuilder, this, OptAttributes, Location); - - if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0) - return; - - if (Get != null){ - ig = GetBuilder.GetILGenerator (); - ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags); - ec.EmitTopBlock (Get.Block, Location); + TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, + ParameterTypes); } - if (Set != null){ - ig = SetBuilder.GetILGenerator (); - ec = new EmitContext (tc, Location, ig, null, ModFlags); - - ec.EmitTopBlock (Set.Block, Location); - } + return true; } } @@ -3604,11 +3976,9 @@ namespace Mono.CSharp { }; public readonly OpType OperatorType; - public readonly string ReturnType; - public readonly string FirstArgType; - public readonly string FirstArgName; - public readonly string SecondArgType; - public readonly string SecondArgName; + public readonly Expression ReturnType; + public readonly Expression FirstArgType, SecondArgType; + public readonly string FirstArgName, SecondArgName; public readonly Block Block; public Attributes OptAttributes; public MethodBuilder OperatorMethodBuilder; @@ -3616,8 +3986,10 @@ namespace Mono.CSharp { public string MethodName; public Method OperatorMethod; - public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name, - string arg2type, string arg2name, Block block, Attributes attrs, Location loc) + public Operator (OpType type, Expression ret_type, int flags, + Expression arg1type, string arg1name, + Expression arg2type, string arg2name, + Block block, Attributes attrs, Location loc) : base ("", loc) { OperatorType = type; @@ -3665,7 +4037,8 @@ namespace Mono.CSharp { OperatorMethod = new Method (ReturnType, ModFlags, MethodName, new Parameters (param_list, null, Location), OptAttributes, Mono.CSharp.Location.Null); - + + OperatorMethod.IsOperator = true; OperatorMethod.Define (parent); if (OperatorMethod.MethodBuilder == null) @@ -3673,7 +4046,7 @@ namespace Mono.CSharp { OperatorMethodBuilder = OperatorMethod.MethodBuilder; - Type [] param_types = OperatorMethod.ParameterTypes (parent); + Type [] param_types = OperatorMethod.ParameterTypes; Type declaring_type = OperatorMethodBuilder.DeclaringType; Type return_type = OperatorMethod.GetReturnType (parent); Type first_arg_type = param_types [0]; @@ -3808,12 +4181,22 @@ namespace Mono.CSharp { /// from the current assembly and class /// public static MemberFilter inheritable_method_signature_filter; + + /// + /// This delegate is used to extract inheritable methods which + /// have the same signature as the argument. By inheritable, + /// this means that we have permissions to override the method + /// from the current assembly and class + /// + public static MemberFilter inheritable_property_signature_filter; static MethodSignature () { method_signature_filter = new MemberFilter (MemberSignatureCompare); inheritable_method_signature_filter = new MemberFilter ( InheritableMemberSignatureCompare); + inheritable_property_signature_filter = new MemberFilter ( + InheritablePropertySignatureCompare); } public MethodSignature (string name, Type ret_type, Type [] parameters) @@ -3864,27 +4247,35 @@ namespace Mono.CSharp { static bool MemberSignatureCompare (MemberInfo m, object filter_criteria) { - MethodInfo mi; + MethodSignature sig = (MethodSignature) filter_criteria; - if (! (m is MethodInfo)) + if (m.Name != sig.Name) return false; - MethodSignature sig = (MethodSignature) filter_criteria; + Type ReturnType; + MethodInfo mi = m as MethodInfo; + PropertyInfo pi = m as PropertyInfo; - if (m.Name != sig.Name) + if (mi != null) + ReturnType = mi.ReturnType; + else if (pi != null) + ReturnType = pi.PropertyType; + else return false; - mi = (MethodInfo) m; - // // we use sig.RetType == null to mean `do not check the // method return value. // if (sig.RetType != null) - if (mi.ReturnType != sig.RetType) + if (ReturnType != sig.RetType) return false; - Type [] args = TypeManager.GetArgumentTypes (mi); + Type [] args; + if (mi != null) + args = TypeManager.GetArgumentTypes (mi); + else + args = TypeManager.GetArgumentTypes (pi); Type [] sigp = sig.Parameters; if (args.Length != sigp.Length) @@ -3932,5 +4323,46 @@ namespace Mono.CSharp { } return false; } - } + + // + // This filter should be used when we are requesting properties that + // we want to override. + // + // This makes a number of assumptions, for example + // that the methods being extracted are of a parent + // class (this means we know implicitly that we are + // being called to find out about members by a derived + // class). + // + static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria) + { + if (MemberSignatureCompare (m, filter_criteria)){ + PropertyInfo pi = (PropertyInfo) m; + + MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi); + MethodInfo inherited_set = TypeManager.GetPropertySetter (pi); + + MethodInfo mi = inherited_get == null ? inherited_set : inherited_get; + + MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask; + + // If only accessible to the current class. + if (prot == MethodAttributes.Private) + return false; + + // If only accessible to the defining assembly or + if (prot == MethodAttributes.FamANDAssem || + prot == MethodAttributes.Assembly){ + if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder) + return true; + else + return false; + } + + // Anything else (FamOrAssembly and Public) is fine + return true; + } + return false; + } + } }