X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmbas%2Fclass.cs;h=4f527be48eef0302170cd9fa3b590f398fdeee9d;hb=5a784c61efadcc35c32a687c7c6f9245079958f1;hp=5284f71acf8244be8392d3f7fd88425f1aeb1174;hpb=0ed717ebac0bd44923075e3a26186aed5328f9ff;p=mono.git diff --git a/mcs/mbas/class.cs b/mcs/mbas/class.cs index 5284f71acf8..4f527be48ee 100644 --- a/mcs/mbas/class.cs +++ b/mcs/mbas/class.cs @@ -1,14 +1,35 @@ + // // 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 // // (C) 2001, 2002 Ximian, Inc (http://www.ximian.com) // // - +// 2002-10-11 Miguel de Icaza +// +// * class.cs: Following the comment from 2002-09-26 to AddMethod, I +// have fixed a remaining problem: not every AddXXXX was adding a +// fully qualified name. +// +// Now everyone registers a fully qualified name in the DeclSpace as +// being defined instead of the partial name. +// +// Downsides: we are slower than we need to be due to the excess +// copies and the names being registered this way. +// +// The reason for this is that we currently depend (on the corlib +// bootstrap for instance) that types are fully qualified, because +// we dump all the types in the namespace, and we should really have +// types inserted into the proper namespace, so we can only store the +// basenames in the defined_names array. +// +// +#define CACHE using System; using System.Collections; using System.Reflection; @@ -16,12 +37,12 @@ using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Diagnostics.SymbolStore; -namespace Mono.CSharp { +namespace Mono.MonoBASIC { /// /// This is the base class for structs and classes. /// - public class TypeContainer : DeclSpace { + public class TypeContainer : DeclSpace, IMemberContainer { // Holds a list of classes and structures ArrayList types; @@ -69,7 +90,7 @@ namespace Mono.CSharp { // The emit context for toplevel objects. EmitContext ec; - + // // Pointers to the default constructor and the default static constructor // @@ -105,6 +126,10 @@ namespace Mono.CSharp { // The interfaces we implement. Type [] ifaces; + + // The parent member container and our member cache + IMemberContainer parent_container; + MemberCache member_cache; // // The indexer name for this class @@ -130,33 +155,32 @@ namespace Mono.CSharp { public AdditionResult AddConstant (Const constant) { AdditionResult res; - string name = constant.Name; + string basename = constant.Name; - if ((res = IsValid (name)) != AdditionResult.Success) + if ((res = IsValid (basename)) != AdditionResult.Success) return res; if (constants == null) constants = new ArrayList (); constants.Add (constant); - DefineName (name, constant); + DefineName (Name + "." + basename, constant); return AdditionResult.Success; } - public AdditionResult AddEnum (Mono.CSharp.Enum e) + public AdditionResult AddEnum (Mono.MonoBASIC.Enum e) { AdditionResult res; - string name = e.Name; - if ((res = IsValid (name)) != AdditionResult.Success) + if ((res = IsValid (e.Basename)) != AdditionResult.Success) return res; if (enums == null) enums = new ArrayList (); enums.Add (e); - DefineName (name, e); + DefineName (e.Name, e); return AdditionResult.Success; } @@ -164,27 +188,38 @@ namespace Mono.CSharp { public AdditionResult AddClass (Class c) { AdditionResult res; - string name = c.Name; - - - if ((res = IsValid (name)) != AdditionResult.Success) + + if ((res = IsValid (c.Basename)) != AdditionResult.Success) return res; - - DefineName (name, c); + + + + DefineName (c.Name, c); types.Add (c); - + + // FIXME: Do we really need to explicitly add an empty default static constructor? + // Apparently we don't +/* if (c.default_static_constructor == null) + { + bool isModule = c is Mono.MonoBASIC.Module; + Constructor dc = new Constructor ("New", Parameters.EmptyReadOnlyParameters, null, c.Location); + dc.ModFlags = isModule ? Modifiers.PUBLIC | Modifiers.STATIC : Modifiers.PUBLIC; + c.AddConstructor (dc); + } +*/ + //-------------------------------------------------------------- + return AdditionResult.Success; } public AdditionResult AddStruct (Struct s) { AdditionResult res; - string name = s.Name; - if ((res = IsValid (name)) != AdditionResult.Success) + if ((res = IsValid (s.Basename)) != AdditionResult.Success) return res; - DefineName (name, s); + DefineName (s.Name, s); types.Add (s); return AdditionResult.Success; @@ -193,15 +228,14 @@ namespace Mono.CSharp { public AdditionResult AddDelegate (Delegate d) { AdditionResult res; - string name = d.Name; - if ((res = IsValid (name)) != AdditionResult.Success) + if ((res = IsValid (d.Basename)) != AdditionResult.Success) return res; if (delegates == null) delegates = new ArrayList (); - DefineName (name, d); + DefineName (d.Name, d); delegates.Add (d); return AdditionResult.Success; @@ -209,12 +243,17 @@ namespace Mono.CSharp { public AdditionResult AddMethod (Method method) { - string name = method.Name; - Object value = defined_names [name]; - + string basename = method.Name; + string fullname = Name + "." + basename; + + Object value = defined_names [fullname]; + if (value != null && (!(value is Method))) return AdditionResult.NameExists; + if (basename == Basename) + return AdditionResult.EnclosingClash; + if (methods == null) methods = new ArrayList (); @@ -223,19 +262,19 @@ namespace Mono.CSharp { else methods.Add (method); - if (value != null) - DefineName (name, method); + if (value == null) + DefineName (fullname, method); return AdditionResult.Success; } public AdditionResult AddConstructor (Constructor c) { - if (c.Name != Basename) + if (c.Name != "New") return AdditionResult.NotAConstructor; bool is_static = (c.ModFlags & Modifiers.STATIC) != 0; - + if (is_static){ have_static_constructor = true; if (default_static_constructor != null){ @@ -247,8 +286,8 @@ namespace Mono.CSharp { default_static_constructor = c; } else { if (c.IsDefault ()){ - if (default_constructor != null) - return AdditionResult.MethodExists; + /*if (default_constructor != null) + return AdditionResult.MethodExists;*/ default_constructor = c; } @@ -264,15 +303,14 @@ namespace Mono.CSharp { public AdditionResult AddInterface (Interface iface) { AdditionResult res; - string name = iface.Name; - if ((res = IsValid (name)) != AdditionResult.Success) + if ((res = IsValid (iface.Basename)) != AdditionResult.Success) return res; if (interfaces == null) interfaces = new ArrayList (); interfaces.Add (iface); - DefineName (name, iface); + DefineName (iface.Name, iface); return AdditionResult.Success; } @@ -280,9 +318,9 @@ namespace Mono.CSharp { public AdditionResult AddField (Field field) { AdditionResult res; - string name = field.Name; + string basename = field.Name; - if ((res = IsValid (name)) != AdditionResult.Success) + if ((res = IsValid (basename)) != AdditionResult.Success) return res; if (fields == null) @@ -290,8 +328,8 @@ namespace Mono.CSharp { fields.Add (field); - if (field.Initializer != null){ - if ((field.ModFlags & Modifiers.STATIC) != 0){ + if (field.HasInitializer){ + if ((field.ModFlags & Modifiers.STATIC) != 0) { if (initialized_static_fields == null) initialized_static_fields = new ArrayList (); @@ -313,16 +351,16 @@ namespace Mono.CSharp { if ((field.ModFlags & Modifiers.STATIC) == 0) have_nonstatic_fields = true; - DefineName (name, field); + DefineName (Name + "." + basename, field); return AdditionResult.Success; } public AdditionResult AddProperty (Property prop) { AdditionResult res; - string name = prop.Name; + string basename = prop.Name; - if ((res = IsValid (name)) != AdditionResult.Success) + if ((res = IsValid (basename)) != AdditionResult.Success) return res; if (properties == null) @@ -332,7 +370,7 @@ namespace Mono.CSharp { properties.Insert (0, prop); else properties.Add (prop); - DefineName (name, prop); + DefineName (Name + "." + basename, prop); return AdditionResult.Success; } @@ -340,16 +378,16 @@ namespace Mono.CSharp { public AdditionResult AddEvent (Event e) { AdditionResult res; - string name = e.Name; + string basename = e.Name; - if ((res = IsValid (name)) != AdditionResult.Success) + if ((res = IsValid (basename)) != AdditionResult.Success) return res; if (events == null) events = new ArrayList (); events.Add (e); - DefineName (name, e); + DefineName (Name + "." + basename, e); return AdditionResult.Success; } @@ -514,18 +552,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); @@ -542,7 +573,7 @@ namespace Mono.CSharp { throw new Exception ("Assign.Resolve returned a non ExpressionStatement"); } } - + return true; } @@ -554,14 +585,18 @@ 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 ("New", Parameters.EmptyReadOnlyParameters, + null, + Location.Null); - if (is_static) + if (is_static) { mods = Modifiers.STATIC; - - c.ModFlags = mods; + c.ModFlags = mods; + } + else + c.Initializer = new ConstructorBaseInitializer ( + null, Parameters.EmptyReadOnlyParameters, + Location.Null); AddConstructor (c); @@ -575,7 +610,7 @@ namespace Mono.CSharp { foreach (Field f in initialized_fields){ Report.Error ( - 573, Location, + 31049, Location, "`" + n + "." + f.Name + "': can not have " + "instance field initializers in structs"); } @@ -634,14 +669,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; @@ -650,6 +687,18 @@ namespace Mono.CSharp { start = 0; } + if (parent.IsSealed ) + Report.Error (30299, Location, + "Class " + Name + " cannot inherit " + + "'NotInheritable' class " + TypeManager.MonoBASIC_Name (parent)); + + if (!AsAccessible (parent, ModFlags)) + Report.Error (30389, Location, + "Inconsistent accessibility: base class `" + + TypeManager.MonoBASIC_Name (parent) + "' is less " + + "accessible than class `" + + Name + "'"); + } else { start = 0; } @@ -657,9 +706,11 @@ 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; return null; @@ -671,24 +722,23 @@ namespace Mono.CSharp { error = true; return null; } - + if (t.IsSealed) { - string detail = ""; - - if (t.IsValueType) - detail = " (a class can not inherit from a struct/enum)"; + if (t.IsValueType) + Report.Error (30258, "class `"+ Name + + "': a class can not inherit from a struct/enum"); - Report.Error (509, "class `"+ Name + + /*Report.Error (509, "class `"+ Name + "': Cannot inherit from sealed class `"+ - bases [i]+"'"+detail); + bases [i]);*/ error = true; return null; } if (t.IsClass) { if (parent != null){ - Report.Error (527, "In Class `" + Name + "', type `"+ - name+"' is not an interface"); + Report.Error (30121, Name + ": A class cannot inherit " + + "more than one class"); error = true; return null; } @@ -701,7 +751,7 @@ namespace Mono.CSharp { return null; } } - + ifaces [j] = t; } @@ -724,14 +774,20 @@ namespace Mono.CSharp { return null; InTransit = true; - + if (this is Class) is_class = true; else is_class = false; - ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags); + ec = new EmitContext (this, Mono.MonoBASIC.Location.Null, null, null, ModFlags); + if (((ModFlags & Modifiers.ABSTRACT ) != 0) && + ((ModFlags & Modifiers.SEALED) != 0)){ + Report.Error (31408, Location, + "Class declared as 'MustInherit' cannot be declared as 'NotInheritable'"); + } + ifaces = GetClassBases (is_class, out parent, out error); if (error) @@ -744,7 +800,7 @@ namespace Mono.CSharp { parent == TypeManager.array_type){ Report.Error ( 644, Location, "`" + Name + "' cannot inherit from " + - "special class `" + TypeManager.CSharpName (parent) + "'"); + "special class `" + TypeManager.MonoBASIC_Name (parent) + "'"); return null; } } @@ -752,58 +808,60 @@ namespace Mono.CSharp { if (!is_class && TypeManager.value_type == null) throw new Exception (); + if (is_class && Parent.Parent == null) + { + if ((ModFlags & Modifiers.PRIVATE) != 0) + Report.Error (31089, Location, + "Only internal classes can be declared as 'Private'"); + + if ((ModFlags & Modifiers.PROTECTED) != 0) + Report.Error (31047, Location, + "Only internal classes can be declared as 'Protected'"); + } + + if ((Parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0)) + Report.Error (30735, Location, + "'Type' inside a 'Module' can not be " + + "declared as 'Protected'"); + + if ((Parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0)) + Report.Error (30435, Location, + "'Type' inside a 'Structure' can not be " + + "declared as 'Protected'"); + TypeAttributes type_attributes = TypeAttr; // if (parent_builder is ModuleBuilder) { if (IsTopLevel){ ModuleBuilder builder = CodeGen.ModuleBuilder; + TypeBuilder = builder.DefineType ( + Name, type_attributes, parent, ifaces); - // - // Structs with no fields need to have a ".size 1" - // appended - // - - if (!is_class && !have_nonstatic_fields) - TypeBuilder = builder.DefineType (Name, - type_attributes, - parent, - PackingSize.Unspecified, 1); - else - // - // classes or structs with fields - // - TypeBuilder = builder.DefineType (Name, - type_attributes, - parent, - ifaces); } else { TypeBuilder builder = Parent.TypeBuilder; + TypeBuilder = builder.DefineNestedType ( + Basename, type_attributes, parent, ifaces); + } - // - // Structs with no fields need to have a ".size 1" - // appended - // - if (!is_class && !have_nonstatic_fields) - TypeBuilder = builder.DefineNestedType (Basename, - type_attributes, - parent, - PackingSize.Unspecified); - else { - // - // classes or structs with fields - // - TypeBuilder = builder.DefineNestedType (Basename, - type_attributes, - parent, - ifaces); + if (!is_class) + { + // structure must contain atleast one member variable + if(!have_nonstatic_fields){ + Report.Error ( + 30281, Location, "Structure `" + Name + "' do not " + + "contain any member Variable"); + + /*TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type, + FieldAttributes.Private);*/ } - } - // 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); + // add interfaces that were not added at type creation (weird API issue) + if (!have_nonstatic_fields && (ifaces != null)) { + foreach (Type i in ifaces) + TypeBuilder.AddInterfaceImplementation (i); + } } + // // Finish the setup for the EmitContext @@ -855,7 +913,51 @@ namespace Mono.CSharp { void DefineMembers (ArrayList list, MemberInfo [] defined_names) { int idx; - + + // if one of the overloaded method is having + // Shadows or Overloads modifier all other should + // have the same modifier + Hashtable members = new Hashtable(); + int modval; + foreach (MemberCore mc in list) + { + modval = 0; + if(members[mc.Name] == null) + { + foreach (MemberCore m in list) + { + if(m.Name == mc.Name) + { + if ((m.ModFlags & Modifiers.SHADOWS) != 0) + { + modval = Modifiers.SHADOWS; + break; + } + else if((m.ModFlags & Modifiers.NEW) != 0) + { + modval = Modifiers.NEW; + } + } + } + members.Add(mc.Name, modval); + } + + modval = (int)members[mc.Name]; + if(modval != 0) + { + if(((modval & Modifiers.SHADOWS) != 0) && ((mc.ModFlags & Modifiers.SHADOWS) == 0)) + Report.Error ( + 30695, mc.Location, + "Function '" + mc.Name + "': must be declared 'Shadows' " + + "because another '" + mc.Name + "' declared 'Shadows'"); + else if(((modval & Modifiers.NEW) != 0) && ((mc.ModFlags & Modifiers.NEW) == 0)) + Report.Error ( + 31409, mc.Location, + "Function '" + mc.Name + "': must be declared 'Overloads' " + + "because another '" + mc.Name + "' declared 'Overloads'"); + } + } + members.Clear (); remove_list.Clear (); foreach (MemberCore mc in list){ @@ -872,6 +974,8 @@ namespace Mono.CSharp { if (RootContext.WarningLevel >= 4){ if ((mc.ModFlags & Modifiers.NEW) != 0) Warning_KewywordNewNotRequired (mc.Location, mc); + if ((mc.ModFlags & Modifiers.SHADOWS) != 0) + Warning_KewywordShadowsNotRequired (mc.Location, mc); } continue; } @@ -887,8 +991,9 @@ namespace Mono.CSharp { if (match is MethodBase && mc is MethodCore) continue; - if ((mc.ModFlags & Modifiers.NEW) == 0) - Warning_KeywordNewRequired (mc.Location, defined_names [idx]); + if (((mc.ModFlags & Modifiers.SHADOWS) == 0) && idx > 0) + Warning_KeywordShadowsRequired (mc.Location, defined_names [idx]); + } foreach (object o in remove_list) @@ -916,6 +1021,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; @@ -932,14 +1041,27 @@ namespace Mono.CSharp { class_indexer_name = "Item"; IndexerName = class_indexer_name; } - + + static void Error_KeywordNotAllowed (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 + Error_KeywordNotAllowed (iface.Location); + } + if (RootContext.WarningLevel > 1){ Type ptype; @@ -949,7 +1071,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); @@ -966,7 +1088,7 @@ namespace Mono.CSharp { if (this is Class){ if (instance_constructors == null){ - if (default_constructor == null) + if (default_constructor == null) DefineDefaultConstructor (false); } @@ -993,7 +1115,7 @@ namespace Mono.CSharp { // // Constructors are not in the defined_names array // - if (instance_constructors != null) + if (instance_constructors != null) DefineMembers (instance_constructors, null); if (default_static_constructor != null) @@ -1013,29 +1135,39 @@ namespace Mono.CSharp { } else IndexerName = "Item"; - if (operators != null) + if (operators != null){ DefineMembers (operators, null); + CheckPairedOperators (); + } + if (enums != null) DefineMembers (enums, defined_names); if (delegates != null) DefineMembers (delegates, defined_names); +#if CACHE + if (TypeBuilder.BaseType != null) + parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType); + + member_cache = new MemberCache (this); +#endif + 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 /// @@ -1081,11 +1213,35 @@ 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) + public override MemberList FindMembers (MemberTypes mt, BindingFlags bf, + MemberFilter filter, object criteria) { ArrayList members = new ArrayList (); - bool priv = (bf & BindingFlags.NonPublic) != 0; + + int modflags = 0; + if ((bf & BindingFlags.Public) != 0) + modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED | + Modifiers.INTERNAL; + if ((bf & BindingFlags.NonPublic) != 0) + modflags |= Modifiers.PRIVATE; + + int static_mask = 0, static_flags = 0; + switch (bf & (BindingFlags.Static | BindingFlags.Instance)) { + case BindingFlags.Static: + static_mask = static_flags = Modifiers.STATIC; + break; + + case BindingFlags.Instance: + static_mask = Modifiers.STATIC; + static_flags = 0; + break; + + default: + static_mask = static_flags = 0; + break; + } + + Timer.StartTimer (TimerType.TcFindMembers); if (filter == null) filter = accepting_filter; @@ -1093,9 +1249,10 @@ namespace Mono.CSharp { if ((mt & MemberTypes.Field) != 0) { if (fields != null) { foreach (Field f in fields) { - if ((f.ModFlags & Modifiers.PRIVATE) != 0) - if (!priv) - continue; + if ((f.ModFlags & modflags) == 0) + continue; + if ((f.ModFlags & static_mask) != static_flags) + continue; FieldBuilder fb = f.FieldBuilder; if (fb != null && filter (fb, criteria) == true) @@ -1105,10 +1262,11 @@ namespace Mono.CSharp { if (constants != null) { foreach (Const con in constants) { - if ((con.ModFlags & Modifiers.PRIVATE) != 0) - if (!priv) - continue; - + if ((con.ModFlags & modflags) == 0) + continue; + if ((con.ModFlags & static_mask) != static_flags) + continue; + FieldBuilder fb = con.FieldBuilder; if (fb != null && filter (fb, criteria) == true) members.Add (fb); @@ -1119,9 +1277,10 @@ namespace Mono.CSharp { if ((mt & MemberTypes.Method) != 0) { if (methods != null) { foreach (Method m in methods) { - if ((m.ModFlags & Modifiers.PRIVATE) != 0) - if (!priv) - continue; + if ((m.ModFlags & modflags) == 0) + continue; + if ((m.ModFlags & static_mask) != static_flags) + continue; MethodBuilder mb = m.MethodBuilder; @@ -1132,9 +1291,10 @@ namespace Mono.CSharp { if (operators != null){ foreach (Operator o in operators) { - if ((o.ModFlags & Modifiers.PRIVATE) != 0) - if (!priv) - continue; + if ((o.ModFlags & modflags) == 0) + continue; + if ((o.ModFlags & static_mask) != static_flags) + continue; MethodBuilder ob = o.OperatorMethodBuilder; if (ob != null && filter (ob, criteria) == true) @@ -1144,9 +1304,10 @@ namespace Mono.CSharp { if (properties != null){ foreach (Property p in properties){ - if ((p.ModFlags & Modifiers.PRIVATE) != 0) - if (!priv) - continue; + if ((p.ModFlags & modflags) == 0) + continue; + if ((p.ModFlags & static_mask) != static_flags) + continue; MethodBuilder b; @@ -1159,14 +1320,34 @@ namespace Mono.CSharp { members.Add (b); } } + + if (indexers != null){ + foreach (Indexer ix in indexers){ + if ((ix.ModFlags & modflags) == 0) + continue; + if ((ix.ModFlags & static_mask) != static_flags) + continue; + + MethodBuilder b; + + b = ix.GetBuilder; + if (b != null && filter (b, criteria) == true) + members.Add (b); + + b = ix.SetBuilder; + if (b != null && filter (b, criteria) == true) + members.Add (b); + } + } } if ((mt & MemberTypes.Event) != 0) { if (events != null) foreach (Event e in events) { - if ((e.ModFlags & Modifiers.PRIVATE) != 0) - if (!priv) - continue; + if ((e.ModFlags & modflags) == 0) + continue; + if ((e.ModFlags & static_mask) != static_flags) + continue; MemberInfo eb = e.EventBuilder; if (eb != null && filter (eb, criteria) == true) @@ -1177,9 +1358,10 @@ namespace Mono.CSharp { if ((mt & MemberTypes.Property) != 0){ if (properties != null) foreach (Property p in properties) { - if ((p.ModFlags & Modifiers.PRIVATE) != 0) - if (!priv) - continue; + if ((p.ModFlags & modflags) == 0) + continue; + if ((p.ModFlags & static_mask) != static_flags) + continue; MemberInfo pb = p.PropertyBuilder; if (pb != null && filter (pb, criteria) == true) { @@ -1189,9 +1371,10 @@ namespace Mono.CSharp { if (indexers != null) foreach (Indexer ix in indexers) { - if ((ix.ModFlags & Modifiers.PRIVATE) != 0) - if (!priv) - continue; + if ((ix.ModFlags & modflags) == 0) + continue; + if ((ix.ModFlags & static_mask) != static_flags) + continue; MemberInfo ib = ix.PropertyBuilder; if (ib != null && filter (ib, criteria) == true) { @@ -1201,33 +1384,66 @@ namespace Mono.CSharp { } if ((mt & MemberTypes.NestedType) != 0) { + if (types != null){ + foreach (TypeContainer t in types) { + if ((t.ModFlags & modflags) == 0) + continue; + + TypeBuilder tb = t.TypeBuilder; + if (tb != null && (filter (tb, criteria) == true)) + members.Add (tb); + } + } + + if (enums != null){ + foreach (Enum en in enums){ + if ((en.ModFlags & modflags) == 0) + continue; - if (Types != null) - foreach (TypeContainer t in Types) - if (filter (t.TypeBuilder, criteria) == true) - members.Add (t.TypeBuilder); + TypeBuilder tb = en.TypeBuilder; + if (tb != null && (filter (tb, criteria) == true)) + members.Add (tb); + } + } + + if (delegates != null){ + foreach (Delegate d in delegates){ + if ((d.ModFlags & modflags) == 0) + continue; + + TypeBuilder tb = d.TypeBuilder; + if (tb != null && (filter (tb, criteria) == true)) + members.Add (tb); + } + } + + if (interfaces != null){ + foreach (Interface iface in interfaces){ + if ((iface.ModFlags & modflags) == 0) + continue; - if (Enums != null) - foreach (Enum en in Enums) - if (filter (en.TypeBuilder, criteria) == true) - members.Add (en.TypeBuilder); + TypeBuilder tb = iface.TypeBuilder; + if (tb != null && (filter (tb, criteria) == true)) + members.Add (tb); + } + } } if ((mt & MemberTypes.Constructor) != 0){ - if (instance_constructors != null){ + if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){ foreach (Constructor c in instance_constructors){ ConstructorBuilder cb = c.ConstructorBuilder; - if (cb != null) if (filter (cb, criteria) == true) members.Add (cb); } } - if (default_static_constructor != null){ + if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){ ConstructorBuilder cb = default_static_constructor.ConstructorBuilder; + if (cb != null) if (filter (cb, criteria) == true) members.Add (cb); } @@ -1237,34 +1453,30 @@ 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; + Timer.StopTimer (TimerType.TcFindMembers); + + return new MemberList (members); } - + public override MemberCache MemberCache { + get { + return member_cache; + } + } - 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)); } // @@ -1412,7 +1624,7 @@ namespace Mono.CSharp { if (Delegates != null) foreach (Delegate d in Delegates) - d.CloseDelegate (); + d.CloseType (); } public string MakeName (string n) @@ -1420,14 +1632,21 @@ namespace Mono.CSharp { return "`" + Name + "." + n + "'"; } - public void Warning_KeywordNewRequired (Location l, MemberInfo mi) + public void Warning_KeywordShadowsRequired (Location l, MemberInfo mi) { Report.Warning ( - 108, l, "The keyword new is required on " + - MakeName (mi.Name) + " because it hides `" + + 108, l, "The keyword 'Shadows' is required on " + + MakeName (mi.Name) + " because it shadows `" + mi.ReflectedType.Name + "." + mi.Name + "'"); } + public void Warning_KewywordShadowsNotRequired (Location l, MemberCore mc) + { + Report.Warning ( + 109, l, "The member " + MakeName (mc.Name) + " does not hide an " + + "inherited member, the keyword shadows is not required"); + } + public void Warning_KewywordNewNotRequired (Location l, MemberCore mc) { Report.Warning ( @@ -1448,7 +1667,7 @@ namespace Mono.CSharp { { const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE); const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT); - const int nv = (Modifiers.NEW | Modifiers.VIRTUAL); + const int nv = (Modifiers.SHADOWS | Modifiers.VIRTUAL); bool ok = true; string name = MakeName (n); @@ -1458,8 +1677,8 @@ namespace Mono.CSharp { if ((flags & Modifiers.STATIC) != 0){ if ((flags & vao) != 0){ Report.Error ( - 112, loc, "static method " + name + "can not be marked " + - "as virtual, abstract or override"); + 30501, loc, "Shared method " + name + " can not be " + + "declared as Overridable"); ok = false; } } @@ -1471,10 +1690,18 @@ namespace Mono.CSharp { } } - if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){ + if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.VIRTUAL) != 0) + { + Report.Error ( + 30730, loc, name + + ": Methods marked as Overrides cannot be made Overridable"); + ok = false; + } + + if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.SHADOWS) != 0){ Report.Error ( - 113, loc, name + - " marked as override cannot be marked as new or virtual"); + 31408, loc, name + + ": Methods marked as Overrides cannot be marked as Shadows"); ok = false; } @@ -1495,10 +1722,18 @@ namespace Mono.CSharp { ok = false; } - if ((ModFlags & Modifiers.ABSTRACT) == 0){ + if((ModFlags & Modifiers.SEALED) != 0){ + Report.Error ( + 30607, loc, + "Class declared as 'NotInheritable' " + + "cannot have a 'MustOverride' member"); + ok = false; + } + else if ((ModFlags & Modifiers.ABSTRACT) == 0){ Report.Error ( - 513, loc, name + - " is abstract but its container class is not"); + 31411, loc, name + + " is declared as 'MustOverride', hence its container " + + "class should be declared as 'MustInherit'"); ok = false; } @@ -1507,8 +1742,8 @@ namespace Mono.CSharp { if ((flags & Modifiers.PRIVATE) != 0){ if ((flags & vao) != 0){ Report.Error ( - 621, loc, name + - " virtual or abstract members can not be private"); + 31408, loc, name + + ": Members marked as Overridable or Overrides can not be Private"); ok = false; } } @@ -1517,7 +1752,15 @@ namespace Mono.CSharp { if ((flags & Modifiers.OVERRIDE) == 0){ Report.Error ( 238, loc, name + - " cannot be sealed because it is not an override"); + ": cannot be sealed because it is not an override"); + ok = false; + } + } + if ((flags & Modifiers.NEW) != 0){ + if ((flags & Modifiers.SHADOWS) != 0){ + Report.Error ( + 31408, loc, + " 'Overloads' and 'Shadows' cannot be combined "); ok = false; } } @@ -1525,13 +1768,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; @@ -1573,60 +1906,223 @@ namespace Mono.CSharp { { Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface"); } - } - - public class Class : TypeContainer { - // - // Modifiers allowed in a class declaration - // - public const int AllowedModifiers = - Modifiers.NEW | - Modifiers.PUBLIC | - Modifiers.PROTECTED | - Modifiers.INTERNAL | - Modifiers.PRIVATE | - Modifiers.ABSTRACT | - Modifiers.SEALED | - Modifiers.UNSAFE; - public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l) - : base (parent, name, l) - { - int accmods; + // + // IMemberContainer + // - if (parent.Parent == null) - accmods = Modifiers.INTERNAL; - else - accmods = Modifiers.PRIVATE; + string IMemberContainer.Name { + get { + return Name; + } + } - this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l); - this.attributes = attrs; + Type IMemberContainer.Type { + get { + return TypeBuilder; + } } - // - // FIXME: How do we deal with the user specifying a different - // layout? - // - public override TypeAttributes TypeAttr { + IMemberContainer IMemberContainer.Parent { get { - return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class; + return parent_container; } } - } - public class Struct : TypeContainer { - // - // Modifiers allowed in a struct declaration - // - public const int AllowedModifiers = - Modifiers.NEW | - Modifiers.PUBLIC | - Modifiers.PROTECTED | - Modifiers.INTERNAL | - Modifiers.UNSAFE | - Modifiers.PRIVATE; + MemberCache IMemberContainer.MemberCache { + get { + return member_cache; + } + } - public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l) + bool IMemberContainer.IsInterface { + get { + return false; + } + } + + MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf) + { + return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null); + } + + // + // Operator pair checking + // + + class OperatorEntry { + public int flags; + public Type ret_type; + public Type type1, type2; + public Operator op; + public Operator.OpType ot; + + public OperatorEntry (int f, Operator o) + { + flags = f; + + ret_type = o.OperatorMethod.GetReturnType (); + Type [] pt = o.OperatorMethod.ParameterTypes; + type1 = pt [0]; + type2 = pt [1]; + op = o; + ot = o.OperatorType; + } + + public override int GetHashCode () + { + return ret_type.GetHashCode (); + } + + public override bool Equals (object o) + { + OperatorEntry other = (OperatorEntry) o; + + if (other.ret_type != ret_type) + return false; + if (other.type1 != type1) + return false; + if (other.type2 != type2) + return false; + return true; + } + } + + // + // Checks that some operators come in pairs: + // == and != + // > and < + // >= and <= + // + // They are matched based on the return type and the argument types + // + void CheckPairedOperators () + { + Hashtable pairs = new Hashtable (null, null); + + // Register all the operators we care about. + foreach (Operator op in operators){ + int reg = 0; + + switch (op.OperatorType){ + case Operator.OpType.Equality: + reg = 1; break; + case Operator.OpType.Inequality: + reg = 2; break; + + case Operator.OpType.GreaterThan: + reg = 1; break; + case Operator.OpType.LessThan: + reg = 2; break; + + case Operator.OpType.GreaterThanOrEqual: + reg = 1; break; + case Operator.OpType.LessThanOrEqual: + reg = 2; break; + } + if (reg == 0) + continue; + + OperatorEntry oe = new OperatorEntry (reg, op); + + object o = pairs [oe]; + if (o == null) + pairs [oe] = oe; + else { + oe = (OperatorEntry) o; + oe.flags |= reg; + } + } + + // + // Look for the mistakes. + // + foreach (DictionaryEntry de in pairs){ + OperatorEntry oe = (OperatorEntry) de.Key; + + if (oe.flags == 3) + continue; + + string s = ""; + switch (oe.ot){ + case Operator.OpType.Equality: + s = "!="; + break; + case Operator.OpType.Inequality: + s = "=="; + break; + case Operator.OpType.GreaterThan: + s = "<"; + break; + case Operator.OpType.LessThan: + s = ">"; + break; + case Operator.OpType.GreaterThanOrEqual: + s = "<="; + break; + case Operator.OpType.LessThanOrEqual: + s = ">="; + break; + } + Report.Error (216, oe.op.Location, + "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined"); + } + } + + + } + + public class Class : TypeContainer { + // + // Modifiers allowed in a class declaration + // + public const int AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.ABSTRACT | + Modifiers.SEALED ; + + public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l) + : base (parent, name, l) + { + int accmods; + + if (parent.Parent == null) + accmods = Modifiers.INTERNAL; + else + accmods = Modifiers.PUBLIC; + + this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l); + this.attributes = attrs; + } + + // + // FIXME: How do we deal with the user specifying a different + // layout? + // + public override TypeAttributes TypeAttr { + get { + return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class; + } + } + } + + public class Struct : TypeContainer { + // + // Modifiers allowed in a struct declaration + // + public const int AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.UNSAFE | + Modifiers.PRIVATE; + + public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l) : base (parent, name, l) { int accmods; @@ -1634,7 +2130,7 @@ namespace Mono.CSharp { if (parent.Parent == null) accmods = Modifiers.INTERNAL; else - accmods = Modifiers.PRIVATE; + accmods = Modifiers.PUBLIC; this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l); @@ -1658,35 +2154,30 @@ namespace Mono.CSharp { } } - public abstract class MethodCore : MemberCore { - public readonly Parameters Parameters; + 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 @@ -1694,10 +2185,6 @@ namespace Mono.CSharp { get { return parameter_info; } - - set { - parameter_info = value; - } } public Block Block { @@ -1710,6 +2197,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; @@ -1726,12 +2225,17 @@ namespace Mono.CSharp { } public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder) + { + LabelParameters (ec, parameters, builder, null); + } + + public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder, Parameters p_params) { // // Define each type attribute (in/out/ref) and // the argument names. // - Parameter [] p = Parameters.FixedParameters; + Parameter [] p = p_params == null ? Parameters.FixedParameters : p_params.FixedParameters; int i = 0; MethodBuilder mb = null; @@ -1781,11 +2285,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 @@ -1798,22 +2299,28 @@ namespace Mono.CSharp { Modifiers.PRIVATE | Modifiers.STATIC | Modifiers.VIRTUAL | - Modifiers.SEALED | + Modifiers.NONVIRTUAL | Modifiers.OVERRIDE | Modifiers.ABSTRACT | - Modifiers.UNSAFE | - Modifiers.EXTERN; + Modifiers.UNSAFE | + Modifiers.EXTERN| + Modifiers.SHADOWS; // // 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) + { + Implements = null; + } + + public Method (Expression return_type, int mod, string name, Parameters parameters, + Attributes attrs, Expression impl_what, Location l) + : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l) + { + Implements = impl_what; } // @@ -1821,24 +2328,21 @@ namespace Mono.CSharp { // function. Provides a nice cache. (used between semantic analysis // and actual code generation // - Type type_return_type; - - public Type GetReturnType (TypeContainer parent) + public Type GetReturnType () { - 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 ( - 17, location, + 30738, location, "Program `" + CodeGen.FileName + "' has more than one entry point defined: `" + - TypeManager.CSharpSignature(b) + "'"); + TypeManager.MonoBASIC_Signature(b) + "'"); } void Report28 (MethodInfo b) @@ -1848,7 +2352,7 @@ namespace Mono.CSharp { Report.Warning ( 28, Location, - "`" + TypeManager.CSharpSignature(b) + + "`" + TypeManager.MonoBASIC_Signature(b) + "' has the wrong signature to be an entry point"); } @@ -1872,49 +2376,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. @@ -1923,8 +2414,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, @@ -1937,312 +2427,142 @@ 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) - WarningNotHiding (parent); + /*if ((ModFlags & Modifiers.NEW) != 0) + WarningNotHiding (parent);*/ if ((ModFlags & Modifiers.OVERRIDE) != 0){ - Report.Error (115, Location, + Report.Error (30284, Location, parent.MakeName (Name) + - " no suitable methods found to override"); + " : No suitable methods found to override"); + } + if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0) + { + if ((ModFlags & Modifiers.NONVIRTUAL) != 0) + { + Report.Error (31088, Location, + parent.MakeName (Name) + " : Cannot " + + "be declared NotOverridable since this method is " + + "not maked as Overrides"); + } } + // if a member of module is not inherited from Object class + // can not be declared protected + if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0)) + Report.Error (31066, Location, + "'Sub' or 'Function' inside a 'Module' can not be declared as " + + "'Protected' or 'Protected Friend'"); } - } else if ((ModFlags & Modifiers.NEW) != 0) + } + /* else if ((ModFlags & Modifiers.NEW) != 0) WarningNotHiding (parent); + */ - // - // If we implement an interface, extract the interface name. - // - if (Name.IndexOf (".") != -1){ - int pos = Name.LastIndexOf ("."); - iface = Name.Substring (0, pos); - - iface_type = RootContext.LookupType (parent, iface, false, Location); - short_name = Name.Substring (pos + 1); + return true; + } - if (iface_type == null) - return false; + // + // Creates the type + // + public override bool Define (TypeContainer parent) + { + if (!DoDefine (parent)) + return false; - // Compute the full name that we need to export - Name = iface_type.FullName + "." + short_name; + if (!CheckBase (parent)) + return false; - if (!parent.VerifyImplements (iface_type, short_name, Name, Location)) - return false; - - explicit_impl = true; - } else - short_name = Name; + if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0)) + Report.Error (31067, Location, + "'Sub' or 'Function' inside a 'Structure' can not be declared as " + + "'Protected' or 'Protected Friend'"); - // - // 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); + CallingConventions cc = GetCallingConvention (parent is Class); - if (iface_type != null && implementing == null){ - TypeContainer.Error_ExplicitInterfaceNotMemberInterface (Location, short_name); - return false; - } - } + MethodData = new MethodData (this, null, MemberType, ParameterTypes, + ParameterInfo, cc, OptAttributes, + ModFlags, flags, true); - // - // 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 | Modifiers.VIRTUAL)) != 0){ - Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract"); - implementing = null; - } - } - } + MethodBuilder = MethodData.MethodBuilder; // - // If implementing is still valid, set flags + // This is used to track the Entry Point, // - if (implementing != null){ - // Console.WriteLine ("Implementing for:" + (iface_type != null ? iface_type.FullName : "") + " " + short_name); - - 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; - } - } + if (Name.ToUpper() == "MAIN" && + ((ModFlags & Modifiers.STATIC) != 0) && + (RootContext.MainClass == null || + RootContext.MainClass == parent.TypeBuilder.FullName || + (RootContext.RootNamespace != null && + RootContext.RootNamespace.Length > 0 && + (RootContext.RootNamespace + "." + RootContext.MainClass) == parent.TypeBuilder.FullName))) { + if (IsEntryPoint (MethodBuilder, ParameterInfo)) { + if (RootContext.EntryPoint == null) { + RootContext.EntryPoint = MethodBuilder; + RootContext.EntryPointLocation = Location; + } else { + DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation); + DuplicateEntryPoint (MethodBuilder, Location); + } + } else + Report28(MethodBuilder); } - // - // 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, - // - if (Name == "Main" && - ((ModFlags & Modifiers.STATIC) != 0) && - (RootContext.MainClass == null || - RootContext.MainClass == parent.TypeBuilder.FullName)){ - if (IsEntryPoint (MethodBuilder, ParameterInfo)) { - if (RootContext.EntryPoint == null) { - RootContext.EntryPoint = MethodBuilder; - RootContext.EntryPointLocation = Location; - } else { - DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation); - DuplicateEntryPoint (MethodBuilder, Location); - } - } else - Report28(MethodBuilder); - } - - return true; - } + return true; + } // // Emits the code // 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 bool implicit_initialization; - 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; + this.implicit_initialization = false; } public ArrayList Arguments { @@ -2251,74 +2571,95 @@ namespace Mono.CSharp { } } + public ConstructorInfo ParentConstructor + { + get + { + return parent_constructor; + } + } + public bool Resolve (EmitContext ec) { 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, location, + if (ec.ContainerType.IsValueType){ + Report.Error (522, loc, "structs cannot call base class constructors"); return false; } - } else + } + 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, - "Can not find a constructor for this argument list"); + Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" ); return false; } - + parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, - (MethodGroupExpr) parent_constructor_group, argument_list, location); - - if (parent_constructor == null){ - Report.Error (1501, location, - "Can not find a constructor for this argument list"); + (MethodGroupExpr) parent_constructor_group, argument_list, loc); + + if (parent_constructor == null) { + if (this.implicit_initialization) + Report.Error (30148, loc, "Must declare 'MyBase.New' in the constructor " + + "of the class '" + ec.TypeContainer.Name + "' with appropriate arguments, since the base class '" + + t.FullName + "' does not contain a definition of 'New' without any parameter"); + else + Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" ); + return false; } - + return true; } public void Emit (EmitContext ec) { - if (parent_constructor != null) - ec.ig.Emit (OpCodes.Ldarg_0); - if (argument_list != null) - Invocation.EmitArguments (ec, null, argument_list); - if (parent_constructor != null) - ec.ig.Emit (OpCodes.Call, parent_constructor); + if (parent_constructor != null){ + if (ec.IsStatic) + Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc); + else + Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc); + } } + + } 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) { } } @@ -2326,17 +2667,18 @@ 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. // - const int AllowedModifiers = + public const int AllowedModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.STATIC | Modifiers.UNSAFE | + Modifiers.EXTERN | Modifiers.PRIVATE; // @@ -2344,7 +2686,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; } @@ -2373,37 +2715,63 @@ 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) + + if ((ModFlags & Modifiers.STATIC) != 0) { ca |= MethodAttributes.Static; + + if (this.Parameters != Parameters.EmptyReadOnlyParameters) + Report.Error ( + 30479, Location, + "Shared constructor can not have parameters"); + + if ((ModFlags & Modifiers.Accessibility) != 0) + Report.Error ( + 30480, Location, + "Shared constructor can not be declared " + + "explicitly as public, private, friend or protected"); + + if (this.Initializer != null) + Report.Error ( + 30043, Location, + "Keywords like MyBase, MyClass, Me are not " + + "valid inside a Shared Constructor"); + } else { - if (parent is Struct && parameters.Length == 0){ + if (parent is Struct && ParameterTypes.Length == 0) { Report.Error ( - 568, Location, + 30629, Location, "Structs can not contain explicit parameterless " + "constructors"); return false; } - ca |= MethodAttributes.Public | MethodAttributes.HideBySig; - } + ca |= MethodAttributes.HideBySig; - foreach (Type partype in parameters) - if (!TypeContainer.AsAccessible (partype, ModFlags)) - return false; + if ((ModFlags & Modifiers.PUBLIC) != 0) + ca |= MethodAttributes.Public; + else if ((ModFlags & Modifiers.PROTECTED) != 0) { + if ((ModFlags & Modifiers.INTERNAL) != 0) + ca |= MethodAttributes.FamORAssem; + else + ca |= MethodAttributes.Family; + } + else if ((ModFlags & Modifiers.INTERNAL) != 0) + ca |= MethodAttributes.Assembly; + else if (IsDefault ()) + ca |= MethodAttributes.Public; + else + ca |= MethodAttributes.Private; + } 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 " + @@ -2424,9 +2792,11 @@ namespace Mono.CSharp { EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true); if ((ModFlags & Modifiers.STATIC) == 0){ - if (parent is Class && Initializer == null) - Initializer = new ConstructorBaseInitializer (null, parent.Location); - + if (parent is Class && Initializer == null) { + Initializer = new ConstructorBaseInitializer ( + null, Parameters.EmptyReadOnlyParameters, parent.Location); + Initializer.implicit_initialization = true; + } // // Spec mandates that Initializers will not have @@ -2438,7 +2808,7 @@ namespace Mono.CSharp { ec.IsStatic = false; } - LabelParameters (ec, ParameterTypes (parent), ConstructorBuilder); + LabelParameters (ec, ParameterTypes, ConstructorBuilder); // // Classes can have base initializers and instance field initializers. @@ -2447,236 +2817,997 @@ namespace Mono.CSharp { if ((ModFlags & Modifiers.STATIC) == 0) parent.EmitFieldInitializers (ec); } - if (Initializer != null) + + if (Initializer != null) { + if (this.ConstructorBuilder.Equals (Initializer.ParentConstructor)) + Report.Error ( + 30297, Location, + "A constructor can not call itself" ); + 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; } - } + + // + // 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; + } + + string condition = a.Conditional_GetConditionName (); + + if (condition == null) + return false; + + 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 whether this method should be ignored due to its Conditional attributes. + // + bool ShouldIgnore (Location loc) + { + // 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); + + if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0) + return true; + } + + foreach (string condition in conditionals) + if (RootContext.AllDefines [condition] == null) + return true; + + return false; + } + + // + // 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; + + 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 + "'"); + + flags |= TypeManager.MethodFlags.IsObsolete; + } + + if (ShouldIgnore (loc)) + flags |= TypeManager.MethodFlags.ShouldIgnore; + + return flags; + } + + public virtual bool Define (TypeContainer parent) + { + MethodInfo implementing = null; + string method_name, name, prefix; + + 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 (member.InterfaceType != null && implementing == null){ + TypeContainer.Error_ExplicitInterfaceNotMemberInterface ( + Location, name); + return false; + } + } + + // + // 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 (!member.IsExplicitImpl){ + // + // We already catch different accessibility settings + // so we just need to check that we are not private + // + if ((modifiers & Modifiers.PRIVATE) != 0) + implementing = null; + + // + // Static is not allowed + // + if ((modifiers & Modifiers.STATIC) != 0) + implementing = null; + } else { + if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){ + Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract"); + implementing = null; + } + } + } - public class Property : MemberCore { - public readonly string Type; - public Accessor Get, Set; - public PropertyBuilder PropertyBuilder; - public Attributes OptAttributes; - public MethodBuilder GetBuilder, SetBuilder; + // + // If implementing is still valid, set flags + // + if (implementing != null){ + // + // When implementing interface methods, set NewSlot. + // + if (implementing.DeclaringType.IsInterface) + flags |= MethodAttributes.NewSlot; + + flags |= + MethodAttributes.Virtual | + MethodAttributes.HideBySig; + + // Get the method name from the explicit interface. + if (member.InterfaceType != null) { + name = implementing.Name; + method_name = prefix + name; + } + + IsImplementing = true; + } + + // + // Create the MethodBuilder for the method + // + 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; + } + + EmitContext ec = new EmitContext ( + parent, Location, null, ReturnType, modifiers); + + 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) { + // + // clear the pending implemntation flag + // + 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 (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; + } + + // + // Emits the code + // + public virtual void Emit (TypeContainer parent, Block block, object kind) + { + ILGenerator ig; + EmitContext ec; + + if ((flags & MethodAttributes.PinvokeImpl) == 0) + ig = builder.GetILGenerator (); + else + ig = null; + + ec = new EmitContext (parent, Location, ig, ReturnType, modifiers); + + if (OptAttributes != null) + Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location); + + if (member is MethodCore) + ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder); + + // + // abstract or extern methods have no bodies + // + if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){ + if (block == null) + return; + + // + // abstract or extern methods have no bodies. + // + if ((modifiers & Modifiers.ABSTRACT) != 0) + Report.Error ( + 500, Location, "Abstract method `" + + TypeManager.MonoBASIC_Signature (builder) + + "' can not have a body"); + + if ((modifiers & Modifiers.EXTERN) != 0) + Report.Error ( + 179, Location, "External method `" + + TypeManager.MonoBASIC_Signature (builder) + + "' can not have a body"); + + return; + } + + // + // Methods must have a body unless they're extern or abstract + // + if (block == null) { + Report.Error ( + 501, Location, "Method `" + + TypeManager.MonoBASIC_Signature (builder) + + "' must declare a body since it is not marked " + + "abstract or extern"); + return; + } + + // + // 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)); + // Avoid error if we don't support debugging for the platform + try { + sw.SetMethodSourceRange (Location.SymbolDocument, + Location.Row, 0, + end.SymbolDocument, + end.Row, 0); + } catch (Exception) { + } + + ec.EmitTopBlock (block, member.Name, ParameterInfo, Location); + + sw.CloseMethod (); + } else + ec.EmitTopBlock (block, member.Name, ParameterInfo, Location); + } + } + + void EmitDestructor (EmitContext ec, Block block) + { + 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, 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); + } + } + + abstract public class MemberBase : MemberCore { + public Expression Type; + public readonly Attributes OptAttributes; + public Expression Implements; + + protected MethodAttributes flags; + + // + // The "short" name of this property / indexer / event. This is the + // name without the explicit interface. + // + public string ShortName; + + // + // The type of this property / indexer / event + // + public Type MemberType; // - // The type, once we compute it. - Type PropertyType; + // If true, this is an explicit interface implementation + // + public bool IsExplicitImpl = false; - bool explicit_impl; + // + // The name of the interface we are explicitly implementing + // + public string ExplicitInterfaceName = null; // // If true, the interface type we are explicitly implementing // - Type explicit_iface_type = null; + 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.PUBLIC, 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.MonoBASIC_Name (partype) + "' is less " + + "accessible than indexer `" + Name + "'"); + else + Report.Error (51, Location, + "Inconsistent accessibility: parameter type `" + + TypeManager.MonoBASIC_Name (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.MonoBASIC_Name (MemberType) + "' is less " + + "accessible than property `" + Name + "'"); + else if (this is Indexer) + Report.Error (54, Location, + "Inconsistent accessibility: indexer return type `" + + TypeManager.MonoBASIC_Name (MemberType) + "' is less " + + "accessible than indexer `" + Name + "'"); + else if (this is Method) + Report.Error (50, Location, + "Inconsistent accessibility: return type `" + + TypeManager.MonoBASIC_Name (MemberType) + "' is less " + + "accessible than method `" + Name + "'"); + else + Report.Error (52, Location, + "Inconsistent accessibility: field type `" + + TypeManager.MonoBASIC_Name (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.SHADOWS | Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE | Modifiers.STATIC | - Modifiers.SEALED | - Modifiers.OVERRIDE | - Modifiers.ABSTRACT | - Modifiers.UNSAFE | - Modifiers.EXTERN | - Modifiers.VIRTUAL; + // Modifiers.VOLATILE | + // Modifiers.UNSAFE | + Modifiers.READONLY; - public Property (string type, string name, int mod_flags, - Accessor get_block, Accessor set_block, - Attributes attrs, Location loc) - : base (name, loc) + 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.MonoBASIC_Name (t) + "' is less " + + "accessible than field `" + Name + "'"); + return false; + } + + if (t.IsPointer && !UnsafeOK (parent)) + return false; + + Type ptype = parent.TypeBuilder.BaseType; + + // ptype is only null for System.Object while compiling corlib. + if (ptype != null){ + MemberList list = TypeContainer.FindMembers ( + ptype, MemberTypes.Field, + BindingFlags.Public | + BindingFlags.Static | BindingFlags.Instance, + System.Type.FilterName, Name); + + if (RootContext.WarningLevel > 1){ + if ((list.Count > 0) && ((ModFlags & Modifiers.SHADOWS) == 0)) + { + Report.Warning ( + 40004, 2, Location, + "Variable '" + Name + "' should be declared " + + "Shadows since the base type '" + ptype.Name + + "' has a variable with same name"); + + ModFlags |= Modifiers.SHADOWS; + } + } + if (list.Count == 0) + // if a member of module is not inherited from Object class + // can not be declared protected + if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0)) + Report.Error (30593, Location, + "'Variable' inside a 'Module' can not be " + + "declared as 'Protected'"); + } + + if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0)) + Report.Error (30435, Location, + "'Variable' inside a 'Structure' can not be " + + "declared as 'Protected'"); + + 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.MonoBASIC_Name (t) + "'"); + return false; + } + } + } + + FieldAttributes fa = Modifiers.FieldAttr (ModFlags); + + if (parent is Struct && + ((fa & FieldAttributes.Static) == 0) && + t == parent.TypeBuilder && + !TypeManager.IsBuiltinType (t)){ + Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name + + "' causes a cycle in the structure layout"); + 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) { - Type = type; - ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc); Get = get_block; Set = set_block; - OptAttributes = attrs; + } + + 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 // - bool CheckBase (MethodAttributes flags, TypeContainer parent) + protected override bool CheckBase (TypeContainer parent) { + // Check whether arguments were correct. + if (!DoDefineParameters (parent)) + return false; + + if (IsExplicitImpl) + return true; + + string report_name; + MethodSignature ms, base_ms; + if (this is Indexer) { + string name, base_name; + + report_name = "this"; + name = TypeManager.IndexerPropertyName (parent.TypeBuilder); + ms = new MethodSignature (name, null, ParameterTypes); + base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType); + base_ms = new MethodSignature (base_name, null, ParameterTypes); + } else { + report_name = Name; + ms = base_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 `" + report_name + "' " + + "with the same parameter types"); + return false; + } + // // Find properties with the same name on the base class // - - MemberInfo [] props; - MemberInfo [] props_static = TypeManager.MemberLookup ( - parent.TypeBuilder, - parent.TypeBuilder.BaseType, - MemberTypes.Property, BindingFlags.Public | BindingFlags.Static, - Name); - - MemberInfo [] props_instance = TypeManager.MemberLookup ( - parent.TypeBuilder, - parent.TypeBuilder.BaseType, - MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance, - Name); + MemberList props; + MemberList props_static = TypeContainer.FindMembers ( + parent.TypeBuilder.BaseType, MemberTypes.Property, + BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, + MethodSignature.inheritable_property_signature_filter, base_ms); + + MemberList props_instance = TypeContainer.FindMembers ( + parent.TypeBuilder.BaseType, MemberTypes.Property, + BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, + MethodSignature.inheritable_property_signature_filter, + base_ms); // // Find if we have anything // - if (props_static != null && props_static.Length > 0) + if (props_static.Count > 0) props = props_static; - else if (props_instance != null && props_instance.Length > 0) + else if (props_instance.Count > 0) props = props_instance; else props = null; + // // If we have something on the base. - if (props != null && props.Length > 0){ - if (props.Length > 1) - throw new Exception ("Should not happen"); - + if (props != null && props.Count > 0){ PropertyInfo pi = (PropertyInfo) props [0]; MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi); @@ -2685,250 +3816,219 @@ namespace Mono.CSharp { MethodInfo reference = inherited_get == null ? inherited_set : inherited_get; - if (reference != null) - if (!CheckMethodAgainstBase (parent, flags, reference)) + if (reference != null) { + string name = reference.DeclaringType.Name + "." + report_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.NEW) != 0) + WarningNotHiding (parent);*/ if ((ModFlags & Modifiers.OVERRIDE) != 0){ - Report.Error (115, Location, - parent.MakeName (Name) + - " no suitable properties found to override"); + 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; } - bool DefineMethod (TypeContainer parent, string short_name, - MethodAttributes flags, bool is_get, ref bool is_implementing) + public virtual void Emit (TypeContainer tc) { - Type [] parameters = TypeManager.NoTypes; - MethodInfo implementing = null; - Type fn_type; - string name, prefix; - - if (explicit_impl) - prefix = explicit_iface_type.FullName + "."; - else - 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 (parent.Pending != null){ - implementing = parent.Pending.IsInterfaceMethod ( - explicit_iface_type, name, fn_type, parameters); - - if (explicit_iface_type != null && implementing == null){ - TypeContainer.Error_ExplicitInterfaceNotMemberInterface (Location, name); - return false; - } - } - - // - // 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 (explicit_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 | Modifiers.VIRTUAL)) != 0){ - Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract"); - implementing = null; - } - } - } - // - // If implementing is still valid, set flags + // 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 (implementing != null){ - // - // When implementing interface methods, set NewSlot. - // - if (implementing.DeclaringType.IsInterface) - flags |= MethodAttributes.NewSlot; - - flags |= - MethodAttributes.Virtual | - MethodAttributes.HideBySig; - - // - // clear the pending implemntation flag - // - parent.Pending.ImplementMethod ( - explicit_iface_type, name, fn_type, parameters, explicit_impl); - - is_implementing = true; - } + if (PropertyBuilder != null) + Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location); +/* + if (GetData != null) + GetData.Emit (tc, Get.Block, Get); - // - // If this is not an explicit interface implementation, - // clear implementing, as it is only used for explicit - // interface implementation - // - if (Name.IndexOf (".") == -1) - implementing = null; - - if (is_get){ - GetBuilder = parent.TypeBuilder.DefineMethod ( - prefix + name, flags, PropertyType, null); + if (SetData != null) + SetData.Emit (tc, Set.Block, Set); +*/ + } + } - 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 + "'"); - return false; - } - } else { - SetBuilder = parent.TypeBuilder.DefineMethod ( - prefix + name, flags, null, parameters); - - if (implementing != null) - parent.TypeBuilder.DefineMethodOverride ( - SetBuilder, implementing); - - SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); - - // - // 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 (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; - } - } - - return true; + 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 | + Modifiers.DEFAULT | + Modifiers.READONLY | + Modifiers.WRITEONLY | + Modifiers.SHADOWS; + + string set_parameter_name; + Parameters get_params; + Parameters set_params; + + public Property (Expression type, string name, int mod_flags, + Accessor get_block, Accessor set_block, + Attributes attrs, Location loc, string set_name, + Parameters p_get, Parameters p_set, Expression impl_what) + : base (type, name, mod_flags, AllowedModifiers, + p_set, + get_block, set_block, attrs, loc) + { + set_parameter_name = set_name; + get_params = p_get; + set_params = p_set; + Implements = impl_what; + } + + public Property (Expression type, string name, int mod_flags, + Accessor get_block, Accessor set_block, + Attributes attrs, Location loc) + : this (type, name, mod_flags, get_block, set_block, attrs, loc, + "Value", Parameters.EmptyReadOnlyParameters, Parameters.EmptyReadOnlyParameters, null) + { } public override bool Define (TypeContainer parent) { - string short_name; - - if (!parent.MethodModifiersValid (ModFlags, Name, Location)) - return false; - - MethodAttributes flags = Modifiers.MethodAttr (ModFlags); - - flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName; + Type [] g_parameters=null, s_parameters=null; + Parameter [] g_parms, s_parms; + InternalParameters g_ip=null, s_ip=null; - // Lookup Type, verify validity - PropertyType = RootContext.LookupType (parent, Type, false, Location); - if (PropertyType == null) + if (!DoDefine (parent)) return false; - // verify accessibility - if (!TypeContainer.AsAccessible (PropertyType, ModFlags)) + if (!CheckBase (parent)) return false; - if (PropertyType.IsPointer && !UnsafeOK (parent)) - return false; - - if (!CheckBase (flags, parent)) - return false; + flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName; - // - // Check for explicit interface implementation - // - if (Name.IndexOf (".") != -1){ - int pos = Name.LastIndexOf ("."); - string iface = Name.Substring (0, pos); + if (Get == null) { + if ((ModFlags & Modifiers.WRITEONLY) == 0) + Report.Error ( + 30124, Location, + "Property without 'Get' accessor must have a 'WriteOnly' modifier"); + } + else { + if (get_params == Parameters.EmptyReadOnlyParameters) + { + g_parameters = TypeManager.NoTypes; + g_ip = new InternalParameters ( + parent, Parameters.EmptyReadOnlyParameters); + } + else + { + g_parameters = new Type [get_params.FixedParameters.Length]; + for (int i = 0; i < get_params.FixedParameters.Length; i ++) + { + g_parameters[i] = get_params.FixedParameters[i].ParameterType; + } + g_parms = new Parameter [get_params.FixedParameters.Length]; + for (int i = 0; i < get_params.FixedParameters.Length; i ++) + { + Parameter tp = get_params.FixedParameters[i]; + g_parms[i] = new Parameter (tp.TypeName, tp.Name, + Parameter.Modifier.NONE, null); + } + g_ip = new InternalParameters ( + parent, new Parameters (g_parms, null, Location)); + } - explicit_iface_type = RootContext.LookupType (parent, iface, false, Location); - if (explicit_iface_type == null) + GetData = new MethodData (this, "get", MemberType, + g_parameters, g_ip, CallingConventions.Standard, + Get.OptAttributes, ModFlags, flags, false); + + if (!GetData.Define (parent)) return false; - short_name = Name.Substring (pos + 1); + GetBuilder = GetData.MethodBuilder; + } - // Compute the full name that we need to export. - Name = explicit_iface_type.FullName + "." + short_name; - - if (!parent.VerifyImplements (explicit_iface_type, short_name, Name, Location)) - return false; - - explicit_impl = true; - } else { - explicit_impl = false; - short_name = Name; + if (Set == null) { + if ((ModFlags & Modifiers.READONLY) == 0) + Report.Error ( + 30124, Location, + "Property without 'Set' accessor must have a 'ReadOnly' modifier"); + } + else + { + if (set_params == Parameters.EmptyReadOnlyParameters) + { + s_parameters = new Type [1]; + s_parameters [0] = MemberType; + + s_parms = new Parameter [1]; + s_parms [0] = new Parameter (Type, set_parameter_name, + Parameter.Modifier.NONE, null); + } + else + { + s_parameters = new Type [set_params.FixedParameters.Length]; + for (int i = 0; i < set_params.FixedParameters.Length; i ++) + { + s_parameters[i] = set_params.FixedParameters[i].ParameterType; + } - bool is_implementing = false; - if (Get != null) - if (!DefineMethod (parent, short_name, flags, true, ref is_implementing)) - return false; - - if (Set != null) - if (!DefineMethod (parent, short_name, flags, false, ref is_implementing)) + s_parms = new Parameter [set_params.FixedParameters.Length]; + for (int i = 0; i < set_params.FixedParameters.Length; i ++) + { + Parameter tp = set_params.FixedParameters[i]; + s_parms[i] = new Parameter (tp.TypeName, tp.Name, + Parameter.Modifier.NONE, null); + } + } + + s_ip = new InternalParameters ( + parent, new Parameters (s_parms, null, Location)); + + SetData = new MethodData (this, "set", TypeManager.void_type, + s_parameters, s_ip, CallingConventions.Standard, + Set.OptAttributes, ModFlags, flags, false); + + if (!SetData.Define (parent)) return false; + SetBuilder = SetData.MethodBuilder; + SetBuilder.DefineParameter (1, ParameterAttributes.None, + set_parameter_name); + } + // FIXME - PropertyAttributes.HasDefault ? PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName | PropertyAttributes.SpecialName; - if (!explicit_impl){ + if (!IsExplicitImpl){ PropertyBuilder = parent.TypeBuilder.DefineProperty ( - Name, prop_attr, PropertyType, null); - - if (Get != null) - PropertyBuilder.SetGetMethod (GetBuilder); + Name, prop_attr, MemberType, null); - if (Set != null) - PropertyBuilder.SetSetMethod (SetBuilder); + PropertyBuilder.SetGetMethod (GetBuilder); + PropertyBuilder.SetSetMethod (SetBuilder); // // HACK for the reasons exposed above @@ -2944,49 +4044,26 @@ namespace Mono.CSharp { } return true; } - - public void Emit (TypeContainer tc) - { - ILGenerator ig; - EmitContext ec; - - ec = new EmitContext (tc, Location, null, PropertyType, ModFlags); - - // - // 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 (Get != null) - Attribute.ApplyAttributes (ec, GetBuilder, Get, Get.OptAttributes, Location); - if (Set != null) - Attribute.ApplyAttributes (ec, SetBuilder, Set, Set.OptAttributes, Location); - - // - // abstract or extern properties have no bodies - // - if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0) - return; - - if (Get != null){ - ig = GetBuilder.GetILGenerator (); - ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags); - ec.EmitTopBlock (Get.Block, Location); + public override void Emit (TypeContainer tc) + { + base.Emit (tc); + + if (GetData != null) + { + Parameters = get_params; + GetData.Emit (tc, Get.Block, Get); } - if (Set != null){ - ig = SetBuilder.GetILGenerator (); - ec = new EmitContext (tc, Location, ig, null, ModFlags); - - ec.EmitTopBlock (Set.Block, Location); + if (SetData != null) + { + Parameters = set_params; + SetData.Emit (tc, Set.Block, Set); } + } } - /// /// Gigantic workaround for lameness in SRE follows : /// This class derives from EventInfo and attempts to basically @@ -3140,10 +4217,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) { @@ -3153,98 +4230,76 @@ 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)) - return false; - - if (EventType.IsPointer && !UnsafeOK (parent)) - return false; - - if (!EventType.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); - - if (Add == null && Remove == null) { - FieldBuilder = parent.TypeBuilder.DefineField ( - Name, EventType, FieldAttributes.FamANDAssem); - TypeManager.RegisterPrivateFieldOfEvent ((EventInfo) EventBuilder, FieldBuilder); - 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 + "'"); + if (!DoDefine (parent)) + return false; + + if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) { + Report.Error (66, Location, "'" + parent.Name + "." + Name + + "' : event must be of a delegate type"); return false; } - string remove_name = "remove_" + Name; - RemoveBuilder = parent.TypeBuilder.DefineMethod ( - remove_name, m_attr, null, parameters); - RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value"); - EventBuilder.SetRemoveOnMethod (RemoveBuilder); + Type [] parameter_types = new Type [1]; + parameter_types [0] = MemberType; - // - // This looks like dead code - // - //if (parent.Pending != null) - // parent.Pending.IsInterfaceMethod (null, remove_name, null, parameters, false); + Parameter [] parms = new Parameter [1]; + parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null); + InternalParameters ip = new InternalParameters ( + parent, new Parameters (parms, null, Location)); + + if (!CheckBase (parent)) + return false; // - // HACK because System.Reflection.Emit is lame + // Now define the accessors // + AddData = new MethodData (this, "add", TypeManager.void_type, + parameter_types, ip, CallingConventions.Standard, + (Add != null) ? Add.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 (!AddData.Define (parent)) return false; - } - - if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) { - Report.Error (111, Location, - "Class `" + parent.Name + - "' already contains a definition for the event `" + - Name + "'"); + + AddBuilder = AddData.MethodBuilder; + AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name); + + RemoveData = new MethodData (this, "remove", TypeManager.void_type, + parameter_types, ip, CallingConventions.Standard, + (Remove != null) ? Remove.OptAttributes : null, + ModFlags, flags, false); + + if (!RemoveData.Define (parent)) return false; + + RemoveBuilder = RemoveData.MethodBuilder; + RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ this.Name); + + if (!IsExplicitImpl){ + EventBuilder = new MyEventBuilder ( + parent.TypeBuilder, Name, e_attr, MemberType); + + if (Add == null && Remove == null) { + FieldBuilder = parent.TypeBuilder.DefineField ( + Name, MemberType, + FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0)); + TypeManager.RegisterPrivateFieldOfEvent ( + (EventInfo) EventBuilder, FieldBuilder); + TypeManager.RegisterFieldBase (FieldBuilder, this); + } + + 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; @@ -3259,43 +4314,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); - + } } } @@ -3310,7 +4369,7 @@ namespace Mono.CSharp { // // int this [ args ] - public class Indexer : MemberCore { + public class Indexer : PropertyBase { const int AllowedModifiers = Modifiers.NEW | @@ -3325,214 +4384,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 explicit_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 ( - explicit_iface_type, name, ret_type, parameters); - - if (explicit_iface_type != null && implementing == null){ - TypeContainer.Error_ExplicitInterfaceNotMemberInterface (Location, "this"); - return false; - } - } - - 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 (explicit_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 | Modifiers.VIRTUAL)) != 0){ - Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract"); - 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 ( - explicit_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; - - string prefix; - if (explicit_iface_type == null) - prefix = ""; - else - prefix = explicit_iface_type.FullName + "."; - - if (is_get){ - string meth_name = prefix + "get_" + IndexerName; - - GetBuilder = parent.TypeBuilder.DefineMethod ( - meth_name, attr, IndexerType, parameters); - - if (implementing != null) - parent.TypeBuilder.DefineMethodOverride ( - GetBuilder, implementing); - } else { - string meth_name = prefix + "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 explicit_iface_type = null; - - if (InterfaceType != null){ - explicit_iface_type = RootContext.LookupType (parent, InterfaceType, false, Location); - if (explicit_iface_type == null) - return false; - - if (!parent.VerifyImplements (explicit_iface_type, "this", "this", Location)) - 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, explicit_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"); @@ -3555,31 +4471,26 @@ namespace Mono.CSharp { fixed_parms.CopyTo (tmp, 0); tmp [fixed_parms.Length] = new Parameter ( - Type, "value", Parameter.Modifier.NONE, null); + Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null); Parameters set_formal_params = new Parameters (tmp, null, Location); - is_implementing = DefineMethod ( - parent, explicit_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; @@ -3592,73 +4503,46 @@ namespace Mono.CSharp { SetBuilder.DefineParameter ( i + 1, p [i].Attributes, p [i].Name); } + if (Set != null) SetBuilder.DefineParameter ( - i + 1, ParameterAttributes.None, "value"); + i + 1, ParameterAttributes.None, /* was "value" */ this.Name); - 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); + IndexerName, prop_attr, MemberType, ParameterTypes); - if (GetBuilder != null) + if (GetData != null) PropertyBuilder.SetGetMethod (GetBuilder); - if (SetBuilder != null) + if (SetData != null) PropertyBuilder.SetSetMethod (SetBuilder); - TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder); + TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, + ParameterTypes); } return true; } - - public void Emit (TypeContainer tc) - { - ILGenerator ig; - - // - // 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 (Get != null) - Attribute.ApplyAttributes (ec, GetBuilder, Get, Get.OptAttributes, Location); - if (Set != null) - Attribute.ApplyAttributes (ec, SetBuilder, Set, Set.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); - } - - if (Set != null){ - ig = SetBuilder.GetILGenerator (); - ec = new EmitContext (tc, Location, ig, null, ModFlags); - - ec.EmitTopBlock (Set.Block, Location); - } - } } public class Operator : MemberCore { @@ -3712,11 +4596,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; @@ -3724,8 +4606,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; @@ -3772,8 +4656,9 @@ namespace Mono.CSharp { OperatorMethod = new Method (ReturnType, ModFlags, MethodName, new Parameters (param_list, null, Location), - OptAttributes, Mono.CSharp.Location.Null); - + OptAttributes, Mono.MonoBASIC.Location.Null); + + OperatorMethod.IsOperator = true; OperatorMethod.Define (parent); if (OperatorMethod.MethodBuilder == null) @@ -3781,9 +4666,9 @@ 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 return_type = OperatorMethod.GetReturnType (); Type first_arg_type = param_types [0]; // Rules for conversion operators @@ -3893,6 +4778,84 @@ namespace Mono.CSharp { OperatorMethod.Block = Block; OperatorMethod.Emit (parent); } + + public static string GetName (OpType ot) + { + switch (ot){ + case OpType.LogicalNot: + return "!"; + case OpType.OnesComplement: + return "~"; + case OpType.Increment: + return "++"; + case OpType.Decrement: + return "--"; + case OpType.True: + return "true"; + case OpType.False: + return "false"; + case OpType.Addition: + return "+"; + case OpType.Subtraction: + return "-"; + case OpType.UnaryPlus: + return "+"; + case OpType.UnaryNegation: + return "-"; + case OpType.Multiply: + return "*"; + case OpType.Division: + return "/"; + case OpType.Modulus: + return "%"; + case OpType.BitwiseAnd: + return "&"; + case OpType.BitwiseOr: + return "|"; + case OpType.ExclusiveOr: + return "^"; + case OpType.LeftShift: + return "<<"; + case OpType.RightShift: + return ">>"; + case OpType.Equality: + return "=="; + case OpType.Inequality: + return "!="; + case OpType.GreaterThan: + return ">"; + case OpType.LessThan: + return "<"; + case OpType.GreaterThanOrEqual: + return ">="; + case OpType.LessThanOrEqual: + return "<="; + case OpType.Implicit: + return "implicit"; + case OpType.Explicit: + return "explicit"; + default: return ""; + } + } + + public override string ToString () + { + Type return_type = OperatorMethod.GetReturnType(); + Type [] param_types = OperatorMethod.ParameterTypes; + + if (SecondArgType == null) + return String.Format ( + "{0} operator {1}({2})", + TypeManager.MonoBASIC_Name (return_type), + GetName (OperatorType), + param_types [0]); + else + return String.Format ( + "{0} operator {1}({2}, {3})", + TypeManager.MonoBASIC_Name (return_type), + GetName (OperatorType), + param_types [0], param_types [1]); + } } // @@ -3909,6 +4872,12 @@ namespace Mono.CSharp { /// public static MemberFilter method_signature_filter; + /// + /// This delegate is used to extract methods which have the + /// same signature as the argument except for the name + /// + public static MemberFilter method_signature_noname_filter; + /// /// This delegate is used to extract inheritable methods which /// have the same signature as the argument. By inheritable, @@ -3916,12 +4885,23 @@ 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); + method_signature_noname_filter = new MemberFilter (MemberSignatureCompareNoName); inheritable_method_signature_filter = new MemberFilter ( InheritableMemberSignatureCompare); + inheritable_property_signature_filter = new MemberFilter ( + InheritablePropertySignatureCompare); } public MethodSignature (string name, Type ret_type, Type [] parameters) @@ -3970,29 +4950,47 @@ namespace Mono.CSharp { return true; } + static bool MemberSignatureCompareNoName (MemberInfo m, object filter_criteria) + { + return MemberSignatureCompare (m, filter_criteria, false); + } + static bool MemberSignatureCompare (MemberInfo m, object filter_criteria) { - MethodInfo mi; + return MemberSignatureCompare (m, filter_criteria, true); + } + + static bool MemberSignatureCompare (MemberInfo m, object filter_criteria, bool use_name) + { + MethodSignature sig = (MethodSignature) filter_criteria; - if (! (m is MethodInfo)) + if (use_name && (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) @@ -4040,5 +5038,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; + } + } }