3 // class.cs: Class and Struct handlers
5 // Authors: Miguel de Icaza (miguel@gnu.org)
6 // Martin Baulig (martin@gnome.org)
7 // Anirban Bhattacharjee (banirban@novell.com)
9 // Licensed under the terms of the GNU GPL
11 // (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
14 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
16 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
17 // have fixed a remaining problem: not every AddXXXX was adding a
18 // fully qualified name.
20 // Now everyone registers a fully qualified name in the DeclSpace as
21 // being defined instead of the partial name.
23 // Downsides: we are slower than we need to be due to the excess
24 // copies and the names being registered this way.
26 // The reason for this is that we currently depend (on the corlib
27 // bootstrap for instance) that types are fully qualified, because
28 // we dump all the types in the namespace, and we should really have
29 // types inserted into the proper namespace, so we can only store the
30 // basenames in the defined_names array.
35 using System.Collections;
36 using System.Reflection;
37 using System.Reflection.Emit;
38 using System.Runtime.CompilerServices;
39 using System.Diagnostics.SymbolStore;
41 namespace Mono.MonoBASIC {
44 /// This is the base class for structs and classes.
46 public class TypeContainer : DeclSpace, IMemberContainer {
47 // Holds a list of classes and structures
50 // Holds the list of properties
53 // Holds the list of enumerations
56 // Holds the list of delegates
59 // Holds the list of constructors
60 ArrayList instance_constructors;
62 // Holds the list of fields
65 // Holds a list of fields that have initializers
66 ArrayList initialized_fields;
68 // Holds a list of static fields that have initializers
69 ArrayList initialized_static_fields;
71 // Holds the list of constants
77 // Holds order in which interfaces must be closed
78 ArrayList interface_order;
86 // Holds AddHandlers stements for events
89 // The emit context for toplevel objects.
93 // Pointers to the default constructor and the default static constructor
95 Constructor default_constructor;
96 Constructor default_static_constructor;
99 // Whether we have seen a static constructor for this class or not
101 bool have_static_constructor = false;
104 // Whether we have at least one non-static field
106 bool have_nonstatic_fields = false;
109 // This one is computed after we can distinguish interfaces
110 // from classes from the arraylist `type_bases'
112 string base_class_name;
113 public Type base_class_type;
115 ArrayList type_bases;
117 // Information in the case we are an attribute type
119 AttributeUsageAttribute attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
121 public AttributeUsageAttribute AttributeUsage {
123 return attribute_usage;
127 attribute_usage = value;
131 // The interfaces we implement.
134 // The parent member container and our member cache
135 IMemberContainer parent_container;
136 MemberCache member_cache;
139 // The indexer name for this class
141 public string DefaultPropName;
143 public TypeContainer (TypeContainer parent, string name, Attributes attrs, Location l)
144 : base (parent, name, attrs, l)
147 types = new ArrayList ();
154 base_class_name = null;
156 //Console.WriteLine ("New class " + name + " inside " + n);
159 public AdditionResult AddConstant (Const constant)
162 string basename = constant.Name;
164 if ((res = IsValid (basename)) != AdditionResult.Success)
167 if (constants == null)
168 constants = new ArrayList ();
170 constants.Add (constant);
171 DefineName (Name + "." + basename, constant);
173 return AdditionResult.Success;
176 public AdditionResult AddEnum (Mono.MonoBASIC.Enum e)
180 if ((res = IsValid (e.Basename)) != AdditionResult.Success)
184 enums = new ArrayList ();
187 DefineName (e.Name, e);
189 return AdditionResult.Success;
192 public AdditionResult AddClass (Class c)
196 if ((res = IsValid (c.Basename)) != AdditionResult.Success)
201 DefineName (c.Name, c);
204 // FIXME: Do we really need to explicitly add an empty default static constructor?
205 // Apparently we don't
206 /* if (c.default_static_constructor == null)
208 bool isModule = c is Mono.MonoBASIC.Module;
209 Constructor dc = new Constructor ("New", Parameters.EmptyReadOnlyParameters, null, c.Location);
210 dc.ModFlags = isModule ? Modifiers.PUBLIC | Modifiers.STATIC : Modifiers.PUBLIC;
211 c.AddConstructor (dc);
214 //--------------------------------------------------------------
216 return AdditionResult.Success;
219 public AdditionResult AddStruct (Struct s)
223 if ((res = IsValid (s.Basename)) != AdditionResult.Success)
226 DefineName (s.Name, s);
229 return AdditionResult.Success;
232 public AdditionResult AddDelegate (Delegate d)
236 if ((res = IsValid (d.Basename)) != AdditionResult.Success)
239 if (delegates == null)
240 delegates = new ArrayList ();
242 DefineName (d.Name, d);
245 return AdditionResult.Success;
248 public AdditionResult AddMethod (Method method)
250 string basename = method.Name;
251 string fullname = Name + "." + basename;
253 Object value = defined_names [fullname];
255 if (value != null && (!(value is Method)))
256 return AdditionResult.NameExists;
258 if (basename == Basename)
259 return AdditionResult.EnclosingClash;
262 methods = new ArrayList ();
264 if (method.Name.IndexOf (".") != -1)
265 methods.Insert (0, method);
267 methods.Add (method);
270 DefineName (fullname, method);
272 return AdditionResult.Success;
275 public AdditionResult AddConstructor (Constructor c)
278 return AdditionResult.NotAConstructor;
280 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
283 have_static_constructor = true;
284 if (default_static_constructor != null){
285 Console.WriteLine ("I have a static constructor already");
286 Console.WriteLine (" " + default_static_constructor);
287 return AdditionResult.MethodExists;
290 default_static_constructor = c;
293 /*if (default_constructor != null)
294 return AdditionResult.MethodExists;*/
295 default_constructor = c;
298 if (instance_constructors == null)
299 instance_constructors = new ArrayList ();
301 instance_constructors.Add (c);
304 return AdditionResult.Success;
307 public AdditionResult AddInterface (Interface iface)
311 if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
314 if (interfaces == null)
315 interfaces = new ArrayList ();
316 interfaces.Add (iface);
317 DefineName (iface.Name, iface);
319 return AdditionResult.Success;
322 public AdditionResult AddField (Field field)
325 string basename = field.Name;
327 if ((res = IsValid (basename)) != AdditionResult.Success)
331 fields = new ArrayList ();
335 if (field.HasInitializer){
336 if ((field.ModFlags & Modifiers.STATIC) != 0) {
337 if (initialized_static_fields == null)
338 initialized_static_fields = new ArrayList ();
340 initialized_static_fields.Add (field);
343 // We have not seen a static constructor,
344 // but we will provide static initialization of fields
346 have_static_constructor = true;
348 if (initialized_fields == null)
349 initialized_fields = new ArrayList ();
351 initialized_fields.Add (field);
355 if ((field.ModFlags & Modifiers.STATIC) == 0)
356 have_nonstatic_fields = true;
358 DefineName (Name + "." + basename, field);
359 return AdditionResult.Success;
362 public AdditionResult AddProperty (Property prop)
365 string basename = prop.Name;
367 string fullname = Name + "." + basename;
369 Object value = defined_names [fullname];
371 if (value != null && (!(value is Property)))
372 return AdditionResult.NameExists;
374 if ((res = IsValid (basename)) != AdditionResult.Success)
377 if (properties == null)
378 properties = new ArrayList ();
380 if (prop.Name.IndexOf (".") != -1)
381 properties.Insert (0, prop);
383 properties.Add (prop);
386 DefineName (Name + "." + basename, prop);
388 return AdditionResult.Success;
391 public AdditionResult AddEvent (Event e)
394 string basename = e.Name;
396 if ((res = IsValid (basename)) != AdditionResult.Success)
400 events = new ArrayList ();
403 DefineName (Name + "." + basename, e);
405 return AdditionResult.Success;
408 public AdditionResult AddEventHandler (Statement stmt)
410 if (handlers == null)
411 handlers = new ArrayList ();
414 return AdditionResult.Success;
417 public void RegisterOrder (Interface iface)
419 if (interface_order == null)
420 interface_order = new ArrayList ();
422 interface_order.Add (iface);
424 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
426 base.ApplyAttributeBuilder (a, cb);
429 public override AttributeTargets AttributeTargets {
431 throw new NotSupportedException ();
435 public ArrayList Types {
441 public ArrayList Methods {
447 public ArrayList Constants {
453 public ArrayList Interfaces {
461 return base_class_name;
465 public ArrayList Bases {
475 public ArrayList Fields {
485 public ArrayList InstanceConstructors {
487 return instance_constructors;
491 public ArrayList Properties {
497 public ArrayList Events {
503 public ArrayList Enums {
509 public ArrayList Delegates {
515 public bool HaveStaticConstructor {
517 return have_static_constructor;
521 public virtual TypeAttributes TypeAttr {
523 return Modifiers.TypeAttr (ModFlags, this);
527 public ArrayList EventHandlers {
534 // Emits the instance field initializers
536 public bool EmitFieldInitializers (EmitContext ec)
539 ILGenerator ig = ec.ig;
540 Expression instance_expr;
543 fields = initialized_static_fields;
544 instance_expr = null;
546 fields = initialized_fields;
547 instance_expr = new This (Location.Null).Resolve (ec);
553 foreach (Field f in fields){
554 Expression e = f.GetInitializerExpression (ec);
558 Location l = f.Location;
559 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
560 fe.InstanceExpression = instance_expr;
561 Expression a = new Assign (fe, e, l);
567 if (a is ExpressionStatement)
568 ((ExpressionStatement) a).EmitStatement (ec);
570 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
578 // Defines the default constructors
580 void DefineDefaultConstructor (bool is_static)
585 c = new Constructor ("New", Parameters.EmptyReadOnlyParameters,
590 mods = Modifiers.STATIC;
594 c.Initializer = new ConstructorBaseInitializer (
595 null, Parameters.EmptyReadOnlyParameters,
600 c.Block = new Block (null);
604 public void ReportStructInitializedInstanceError ()
606 string n = TypeBuilder.FullName;
608 foreach (Field f in initialized_fields){
611 "`" + n + "." + f.Name + "': can not have " +
612 "instance field initializers in structs");
617 /// The pending methods that need to be implemented (interfaces or abstract methods)
619 public PendingImplementation Pending;
622 /// This function computes the Base class and also the
623 /// list of interfaces that the class or struct @c implements.
625 /// The return value is an array (might be null) of
626 /// interfaces implemented (as Types).
628 /// The @parent argument is set to the parent object or null
629 /// if this is `System.Object'.
631 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
633 ArrayList bases = Bases;
642 parent = TypeManager.value_type;
646 if (RootContext.StdLib)
647 parent = TypeManager.object_type;
648 else if (Name != "System.Object")
649 parent = TypeManager.object_type;
652 // If we are compiling our runtime,
653 // and we are defining ValueType, then our
654 // parent is `System.Object'.
656 if (!RootContext.StdLib && Name == "System.ValueType")
657 parent = TypeManager.object_type;
664 // Bases should be null if there are no bases at all
668 if (is_class && (!(this is Interface))){
669 Expression name = (Expression) bases [0];
670 name = ResolveTypeExpr (name, false, Location);
677 Type first = name.Type;
683 parent = TypeManager.object_type;
687 if (parent.IsSealed )
688 Report.Error (30299, Location,
689 "Class " + Name + " cannot inherit " +
690 "'NotInheritable' class " + TypeManager.MonoBASIC_Name (parent));
692 if (!AsAccessible (parent, ModFlags))
693 Report.Error (30389, Location,
694 "Inconsistent accessibility: base class `" +
695 TypeManager.MonoBASIC_Name (parent) + "' is less " +
696 "accessible than class `" +
703 Type [] ifaces = new Type [count-start];
705 for (i = start, j = 0; i < count; i++, j++){
706 Expression name = (Expression) bases [i];
707 Expression resolved = ResolveTypeExpr (name, false, Location);
708 bases [i] = resolved;
709 Type t = resolved.Type;
715 if (is_class == false && !t.IsInterface){
716 Report.Error (527, "In Struct `" + Name + "', type `"+
717 name +"' is not an interface");
724 Report.Error (30258, "class `"+ Name +
725 "': a class can not inherit from a struct/enum");
727 /*Report.Error (509, "class `"+ Name +
728 "': Cannot inherit from sealed class `"+
736 Report.Error (30121, Name + ": A class cannot inherit " +
737 "more than one class");
743 for (int x = 0; x < j; x++) {
744 if (t == ifaces [x]) {
745 Report.Error (528, "`" + name + "' is already listed in interface list");
758 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
760 public override TypeBuilder DefineType ()
765 if (TypeBuilder != null)
778 ec = new EmitContext (this, Mono.MonoBASIC.Location.Null, null, null, ModFlags);
780 if (((ModFlags & Modifiers.ABSTRACT ) != 0) &&
781 ((ModFlags & Modifiers.SEALED) != 0)){
782 Report.Error (31408, Location,
783 "Class declared as 'MustInherit' cannot be declared as 'NotInheritable'");
786 ifaces = GetClassBases (is_class, out base_class_type, out error);
790 if (this is Interface)
791 base_class_type = null;
793 if (is_class && base_class_type != null){
794 if (base_class_type == TypeManager.enum_type ||
795 (base_class_type == TypeManager.value_type && RootContext.StdLib) ||
796 base_class_type == TypeManager.delegate_type ||
797 base_class_type == TypeManager.array_type){
799 644, Location, "`" + Name + "' cannot inherit from " +
800 "special class `" + TypeManager.MonoBASIC_Name (base_class_type) + "'");
805 if (!is_class && TypeManager.value_type == null)
806 throw new Exception ();
808 if (is_class && Parent.Parent == null && (!(this is Interface)))
810 if ((ModFlags & Modifiers.PRIVATE) != 0)
811 Report.Error (31089, Location,
812 "Only internal classes can be declared as 'Private'");
814 if ((ModFlags & Modifiers.PROTECTED) != 0)
815 Report.Error (31047, Location,
816 "Only internal classes can be declared as 'Protected'");
819 if ((Parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
820 Report.Error (30735, Location,
821 "'Type' inside a 'Module' can not be " +
822 "declared as 'Protected'");
824 if ((Parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
825 Report.Error (30435, Location,
826 "'Type' inside a 'Structure' can not be " +
827 "declared as 'Protected'");
829 TypeAttributes type_attributes = TypeAttr;
832 ModuleBuilder builder = CodeGen.ModuleBuilder;
833 TypeBuilder = builder.DefineType (
834 Name, type_attributes, base_class_type, ifaces);
837 TypeBuilder builder = Parent.TypeBuilder;
838 TypeBuilder = builder.DefineNestedType (
839 Basename, type_attributes, base_class_type, ifaces);
844 // structure must contain atleast one member variable
845 if(!have_nonstatic_fields){
847 30281, Location, "Structure `" + Name + "' do not " +
848 "contain any member Variable");
850 /*TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
851 FieldAttributes.Private);*/
854 // add interfaces that were not added at type creation (weird API issue)
855 if (!have_nonstatic_fields && (ifaces != null)) {
856 foreach (Type i in ifaces)
857 TypeBuilder.AddInterfaceImplementation (i);
863 // Finish the setup for the EmitContext
865 ec.ContainerType = TypeBuilder;
867 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
869 if ((base_class_type != null) &&
870 (base_class_type == TypeManager.attribute_type ||
871 base_class_type.IsSubclassOf (TypeManager.attribute_type))) {
872 RootContext.RegisterAttribute (this);
874 RootContext.RegisterOrder (this);
876 if (Interfaces != null) {
877 foreach (Interface iface in Interfaces)
882 foreach (TypeContainer tc in Types)
886 if (Delegates != null) {
887 foreach (Delegate d in Delegates)
892 foreach (Enum en in Enums)
902 /// Defines the MemberCore objects that are in the `list' Arraylist
904 /// The `defined_names' array contains a list of members defined in
907 static ArrayList remove_list = new ArrayList ();
908 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
912 // if one of the overloaded method is having
913 // Shadows or Overloads modifier all other should
914 // have the same modifier
915 Hashtable members = new Hashtable();
917 foreach (MemberCore mc in list)
920 if(members[mc.Name] == null)
922 foreach (MemberCore m in list)
924 if(m.Name == mc.Name)
926 if ((m.ModFlags & Modifiers.SHADOWS) != 0)
928 modval = Modifiers.SHADOWS;
931 else if((m.ModFlags & Modifiers.NEW) != 0)
933 modval = Modifiers.NEW;
937 members.Add(mc.Name, modval);
940 modval = (int)members[mc.Name];
943 if(((modval & Modifiers.SHADOWS) != 0) && ((mc.ModFlags & Modifiers.SHADOWS) == 0))
946 "Function '" + mc.Name + "': must be declared 'Shadows' " +
947 "because another '" + mc.Name + "' declared 'Shadows'");
948 else if(((modval & Modifiers.NEW) != 0) && ((mc.ModFlags & Modifiers.NEW) == 0))
951 "Function '" + mc.Name + "': must be declared 'Overloads' " +
952 "because another '" + mc.Name + "' declared 'Overloads'");
956 remove_list.Clear ();
958 foreach (MemberCore mc in list){
959 if (!mc.Define (this)){
960 remove_list.Add (mc);
964 if (defined_names == null)
967 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
969 if (RootContext.WarningLevel >= 4){
970 if ((mc.ModFlags & Modifiers.NEW) != 0)
971 Warning_KewywordNewNotRequired (mc.Location, mc);
972 if ((mc.ModFlags & Modifiers.SHADOWS) != 0)
973 Warning_KewywordShadowsNotRequired (mc.Location, mc);
978 MemberInfo match = defined_names [idx];
980 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
984 // If we are both methods, let the method resolution emit warnings
986 if (match is MethodBase && mc is MethodCore)
989 if (((mc.ModFlags & Modifiers.SHADOWS) == 0) && idx > 0)
990 Warning_KeywordShadowsRequired (mc.Location, defined_names [idx]);
994 foreach (object o in remove_list)
997 remove_list.Clear ();
1000 static void Error_KeywordNotAllowed (Location loc)
1002 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1006 /// Populates our TypeBuilder with fields and methods
1008 public override bool DefineMembers (TypeContainer parent)
1010 MemberInfo [] defined_names = null;
1012 if (interface_order != null){
1013 foreach (Interface iface in interface_order)
1014 if ((iface.ModFlags & Modifiers.NEW) == 0)
1015 iface.DefineMembers (this);
1017 Error_KeywordNotAllowed (iface.Location);
1020 if (RootContext.WarningLevel > 1){
1024 // This code throws an exception in the comparer
1025 // I guess the string is not an object?
1027 ptype = TypeBuilder.BaseType;
1029 defined_names = (MemberInfo []) FindMembers (
1030 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1031 BindingFlags.Public | BindingFlags.Instance |
1032 BindingFlags.Static, null, null);
1034 Array.Sort (defined_names, mif_compare);
1038 if (constants != null)
1039 DefineMembers (constants, defined_names);
1042 DefineMembers (fields, defined_names);
1044 if (this is Class && (!(this is Interface))){
1045 if (instance_constructors == null){
1046 if (default_constructor == null)
1047 DefineDefaultConstructor (false);
1050 if (initialized_static_fields != null &&
1051 default_static_constructor == null)
1052 DefineDefaultConstructor (true);
1055 if (this is Struct){
1057 // Structs can not have initialized instance
1060 if (initialized_static_fields != null &&
1061 default_static_constructor == null)
1062 DefineDefaultConstructor (true);
1064 if (initialized_fields != null)
1065 ReportStructInitializedInstanceError ();
1068 if (!(this is Interface))
1069 Pending = PendingImplementation.GetPendingImplementations (this);
1071 // Constructors are not in the defined_names array
1073 if (instance_constructors != null)
1074 DefineMembers (instance_constructors, null);
1076 if (default_static_constructor != null)
1077 default_static_constructor.Define (this);
1079 if (methods != null)
1080 DefineMembers (methods, defined_names);
1082 if (properties != null)
1083 DefineMembers (properties, defined_names);
1086 DefineMembers (events, defined_names);
1089 DefineMembers (enums, defined_names);
1091 if (delegates != null)
1092 DefineMembers (delegates, defined_names);
1095 if (TypeBuilder.BaseType != null)
1096 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1098 member_cache = new MemberCache (this);
1104 public override bool Define (TypeContainer parent)
1106 if (interface_order != null){
1107 foreach (Interface iface in interface_order)
1108 if ((iface.ModFlags & Modifiers.NEW) == 0)
1109 iface.Define (this);
1116 /// This function is based by a delegate to the FindMembers routine
1118 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1124 /// This filter is used by FindMembers, and we just keep
1125 /// a global for the filter to `AlwaysAccept'
1127 static MemberFilter accepting_filter;
1131 /// A member comparission method based on name only
1133 static IComparer mif_compare;
1135 static TypeContainer ()
1137 accepting_filter = new MemberFilter (AlwaysAccept);
1138 mif_compare = new MemberInfoCompare ();
1142 /// This method returns the members of this type just like Type.FindMembers would
1143 /// Only, we need to use this for types which are _being_ defined because MS'
1144 /// implementation can't take care of that.
1147 // FIXME: return an empty static array instead of null, that cleans up
1148 // some code and is consistent with some coding conventions I just found
1152 // Notice that in various cases we check if our field is non-null,
1153 // something that would normally mean that there was a bug elsewhere.
1155 // The problem happens while we are defining p-invoke methods, as those
1156 // will trigger a FindMembers, but this happens before things are defined
1158 // Since the whole process is a no-op, it is fine to check for null here.
1160 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1161 MemberFilter filter, object criteria)
1163 ArrayList members = new ArrayList ();
1166 if ((bf & BindingFlags.Public) != 0)
1167 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1169 if ((bf & BindingFlags.NonPublic) != 0)
1170 modflags |= Modifiers.PRIVATE;
1172 int static_mask = 0, static_flags = 0;
1173 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1174 case BindingFlags.Static:
1175 static_mask = static_flags = Modifiers.STATIC;
1178 case BindingFlags.Instance:
1179 static_mask = Modifiers.STATIC;
1184 static_mask = static_flags = 0;
1188 Timer.StartTimer (TimerType.TcFindMembers);
1191 filter = accepting_filter;
1193 if ((mt & MemberTypes.Field) != 0) {
1194 if (fields != null) {
1195 foreach (Field f in fields) {
1196 if ((f.ModFlags & modflags) == 0)
1198 if ((f.ModFlags & static_mask) != static_flags)
1201 FieldBuilder fb = f.FieldBuilder;
1202 if (fb != null && filter (fb, criteria) == true)
1207 if (constants != null) {
1208 foreach (Const con in constants) {
1209 if ((con.ModFlags & modflags) == 0)
1211 if ((con.ModFlags & static_mask) != static_flags)
1214 FieldBuilder fb = con.FieldBuilder;
1215 if (fb != null && filter (fb, criteria) == true)
1221 if ((mt & MemberTypes.Method) != 0) {
1222 if (methods != null) {
1223 foreach (Method m in methods) {
1224 if ((m.ModFlags & modflags) == 0)
1226 if ((m.ModFlags & static_mask) != static_flags)
1229 MethodBuilder mb = m.MethodBuilder;
1231 if (mb != null && filter (mb, criteria) == true)
1236 if (properties != null){
1237 foreach (Property p in properties){
1238 if ((p.ModFlags & modflags) == 0)
1240 if ((p.ModFlags & static_mask) != static_flags)
1246 if (b != null && filter (b, criteria) == true)
1250 if (b != null && filter (b, criteria) == true)
1256 if ((mt & MemberTypes.Event) != 0) {
1258 foreach (Event e in events) {
1259 if ((e.ModFlags & modflags) == 0)
1261 if ((e.ModFlags & static_mask) != static_flags)
1264 MemberInfo eb = e.EventBuilder;
1265 if (eb != null && filter (eb, criteria) == true)
1266 members.Add (e.EventBuilder);
1270 if ((mt & MemberTypes.Property) != 0){
1271 if (properties != null)
1272 foreach (Property p in properties) {
1273 if ((p.ModFlags & modflags) == 0)
1275 if ((p.ModFlags & static_mask) != static_flags)
1278 MemberInfo pb = p.PropertyBuilder;
1280 if (pb != null && filter (pb, criteria) == true)
1281 members.Add (p.PropertyBuilder);
1285 if ((mt & MemberTypes.NestedType) != 0) {
1287 foreach (TypeContainer t in types) {
1288 if ((t.ModFlags & modflags) == 0)
1291 TypeBuilder tb = t.TypeBuilder;
1292 if (tb != null && (filter (tb, criteria) == true))
1298 foreach (Enum en in enums){
1299 if ((en.ModFlags & modflags) == 0)
1302 TypeBuilder tb = en.TypeBuilder;
1303 if (tb != null && (filter (tb, criteria) == true))
1308 if (delegates != null){
1309 foreach (Delegate d in delegates){
1310 if ((d.ModFlags & modflags) == 0)
1313 TypeBuilder tb = d.TypeBuilder;
1314 if (tb != null && (filter (tb, criteria) == true))
1319 if (interfaces != null){
1320 foreach (Interface iface in interfaces){
1321 if ((iface.ModFlags & modflags) == 0)
1324 TypeBuilder tb = iface.TypeBuilder;
1325 if (tb != null && (filter (tb, criteria) == true))
1331 if ((mt & MemberTypes.Constructor) != 0){
1332 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1333 foreach (Constructor c in instance_constructors){
1334 if ((c.ModFlags & modflags) == 0)
1337 ConstructorBuilder cb = c.ConstructorBuilder;
1339 if (filter (cb, criteria) == true)
1344 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null) &&
1345 ((default_static_constructor.ModFlags & modflags) != 0)){
1346 ConstructorBuilder cb =
1347 default_static_constructor.ConstructorBuilder;
1350 if (filter (cb, criteria) == true)
1356 // Lookup members in parent if requested.
1358 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1359 if ((mt & ~MemberTypes.Constructor) != 0) {
1360 MemberList list = FindMembers (TypeBuilder.BaseType, mt & ~MemberTypes.Constructor, bf, filter, criteria);
1361 members.AddRange (list);
1365 Timer.StopTimer (TimerType.TcFindMembers);
1367 return new MemberList (members);
1370 public override MemberCache MemberCache {
1372 return member_cache;
1376 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1377 MemberFilter filter, object criteria)
1379 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1382 return tc.FindMembers (mt, bf, filter, criteria);
1384 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1388 // FindMethods will look for methods not only in the type `t', but in
1389 // any interfaces implemented by the type.
1391 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1392 MemberFilter filter, object criteria)
1398 /// Emits the values for the constants
1400 public void EmitConstants ()
1402 if (constants != null)
1403 foreach (Const con in constants)
1404 con.EmitConstant (this);
1409 /// Emits the code, this step is performed after all
1410 /// the types, enumerations, constructors
1414 if (instance_constructors != null)
1415 foreach (Constructor c in instance_constructors)
1418 if (default_static_constructor != null)
1419 default_static_constructor.Emit (this);
1421 if (methods != null)
1422 foreach (Method m in methods)
1425 if (properties != null)
1426 foreach (Property p in properties)
1429 if (this.DefaultPropName != null) {
1430 CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { DefaultPropName });
1431 TypeBuilder.SetCustomAttribute (cb);
1435 foreach (Field f in fields)
1438 if (events != null){
1439 foreach (Event e in Events)
1443 if (Pending != null)
1444 if (Pending.VerifyPendingMethods ())
1447 if (OptAttributes != null)
1448 OptAttributes.Emit (ec, this);
1451 // Check for internal or private fields that were never assigned
1453 if (fields != null && RootContext.WarningLevel >= 3) {
1454 foreach (Field f in fields) {
1455 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1460 169, f.Location, "Private field " +
1461 MakeName (f.Name) + " is never used");
1466 // Only report 649 on level 4
1468 if (RootContext.WarningLevel < 4)
1471 if ((f.status & Field.Status.ASSIGNED) != 0)
1476 "Field " + MakeName (f.Name) + " is never assigned " +
1477 " to and will always have its default value");
1481 // if (types != null)
1482 // foreach (TypeContainer tc in types)
1486 public override void CloseType ()
1491 TypeBuilder.CreateType ();
1493 } catch (TypeLoadException){
1495 // This is fine, the code still created the type
1497 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1498 // Console.WriteLine (e.Message);
1500 Console.WriteLine ("In type: " + Name);
1505 foreach (Enum en in Enums)
1508 if (interface_order != null){
1509 foreach (Interface iface in interface_order)
1514 foreach (TypeContainer tc in Types)
1518 foreach (TypeContainer tc in Types)
1519 if (!(tc is Struct))
1523 if (Delegates != null)
1524 foreach (Delegate d in Delegates)
1528 public string MakeName (string n)
1530 return "`" + Name + "." + n + "'";
1533 public void Warning_KeywordShadowsRequired (Location l, MemberInfo mi)
1536 108, l, "The keyword 'Shadows' is required on " +
1537 MakeName (mi.Name) + " because it shadows `" +
1538 mi.ReflectedType.Name + "." + mi.Name + "'");
1541 public void Warning_KewywordShadowsNotRequired (Location l, MemberCore mc)
1544 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1545 "inherited member, the keyword shadows is not required");
1548 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1551 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1552 "inherited member, the keyword new is not required");
1555 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1561 // Performs the validation on a Method's modifiers (properties have
1562 // the same properties).
1564 public bool MethodModifiersValid (int flags, string n, Location loc)
1566 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1567 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1568 const int nv = (Modifiers.SHADOWS | Modifiers.VIRTUAL);
1570 string name = MakeName (n);
1573 // At most one of static, virtual or override
1575 if ((flags & Modifiers.STATIC) != 0){
1576 if ((flags & vao) != 0){
1578 30501, loc, "Shared method " + name + " can not be " +
1579 "declared as Overridable");
1584 if (this is Struct){
1585 if ((flags & va) != 0){
1586 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1591 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.VIRTUAL) != 0)
1595 ": Methods marked as Overrides cannot be made Overridable");
1599 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.SHADOWS) != 0){
1602 ": Methods marked as Overrides cannot be marked as Shadows");
1607 // If the declaration includes the abstract modifier, then the
1608 // declaration does not include static, virtual or extern
1610 if ((flags & Modifiers.ABSTRACT) != 0){
1611 if ((flags & Modifiers.EXTERN) != 0){
1613 180, loc, name + " can not be both abstract and extern");
1617 if ((flags & Modifiers.VIRTUAL) != 0){
1619 503, loc, name + " can not be both abstract and virtual");
1623 if((ModFlags & Modifiers.SEALED) != 0){
1626 "Class declared as 'NotInheritable' " +
1627 "cannot have a 'MustOverride' member");
1630 else if ((ModFlags & Modifiers.ABSTRACT) == 0){
1633 " is declared as 'MustOverride', hence its container " +
1634 "class should be declared as 'MustInherit'");
1640 if ((flags & Modifiers.PRIVATE) != 0){
1641 if ((flags & vao) != 0){
1644 ": Members marked as Overridable or Overrides can not be Private");
1649 if ((flags & Modifiers.SEALED) != 0){
1650 if ((flags & Modifiers.OVERRIDE) == 0){
1653 ": cannot be sealed because it is not an override");
1657 if ((flags & Modifiers.NEW) != 0){
1658 if ((flags & Modifiers.SHADOWS) != 0){
1661 " 'Overloads' and 'Shadows' cannot be combined ");
1669 // Access level of a type.
1672 ProtectedInternal = 1,
1678 // Check whether `flags' denotes a more restricted access than `level'
1679 // and return the new level.
1680 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1682 AccessLevel old_level = level;
1684 if ((flags & Modifiers.INTERNAL) != 0) {
1685 if ((flags & Modifiers.PROTECTED) != 0) {
1686 if ((int) level < (int) AccessLevel.ProtectedInternal)
1687 level = AccessLevel.ProtectedInternal;
1689 if ((int) level < (int) AccessLevel.Internal)
1690 level = AccessLevel.Internal;
1692 } else if ((flags & Modifiers.PROTECTED) != 0) {
1693 if ((int) level < (int) AccessLevel.Protected)
1694 level = AccessLevel.Protected;
1695 } else if ((flags & Modifiers.PRIVATE) != 0)
1696 level = AccessLevel.Private;
1701 // Return the access level for a new member which is defined in the current
1702 // TypeContainer with access modifiers `flags'.
1703 AccessLevel GetAccessLevel (int flags)
1705 if ((flags & Modifiers.PRIVATE) != 0)
1706 return AccessLevel.Private;
1709 if (!IsTopLevel && (Parent != null))
1710 level = Parent.GetAccessLevel (flags);
1712 level = AccessLevel.Public;
1714 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1717 // Return the access level for type `t', but don't give more access than `flags'.
1718 static AccessLevel GetAccessLevel (Type t, int flags)
1720 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1721 return AccessLevel.Private;
1724 if (TypeManager.IsBuiltinType (t))
1725 return AccessLevel.Public;
1726 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1727 level = GetAccessLevel (t.DeclaringType, flags);
1729 level = CheckAccessLevel (AccessLevel.Public, flags);
1732 if (t.IsNestedPublic)
1735 if (t.IsNestedAssembly || t.IsNotPublic) {
1736 if ((int) level < (int) AccessLevel.Internal)
1737 level = AccessLevel.Internal;
1740 if (t.IsNestedFamily) {
1741 if ((int) level < (int) AccessLevel.Protected)
1742 level = AccessLevel.Protected;
1745 if (t.IsNestedFamORAssem) {
1746 if ((int) level < (int) AccessLevel.ProtectedInternal)
1747 level = AccessLevel.ProtectedInternal;
1754 // Returns true if `parent' is as accessible as the flags `flags'
1755 // given for this member.
1757 public bool AsAccessible (Type parent, int flags)
1759 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1760 parent = parent.GetElementType ();
1762 AccessLevel level = GetAccessLevel (flags);
1763 AccessLevel level2 = GetAccessLevel (parent, flags);
1765 return (int) level >= (int) level2;
1768 Hashtable builder_and_args;
1770 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1772 if (builder_and_args == null)
1773 builder_and_args = new Hashtable ();
1778 /// Performs checks for an explicit interface implementation. First it
1779 /// checks whether the `interface_type' is a base inteface implementation.
1780 /// Then it checks whether `name' exists in the interface type.
1782 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1786 if (ifaces != null){
1787 foreach (Type t in ifaces){
1788 if (t == interface_type){
1796 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1803 public static void Error_NotInterfaceMember (Location loc, string member_name, string iface_name)
1805 Report.Error (30401, loc, "'" + member_name + "' is not a member of the interface '" + iface_name + "'");
1812 string IMemberContainer.Name {
1818 Type IMemberContainer.Type {
1824 IMemberContainer IMemberContainer.Parent {
1826 return parent_container;
1830 MemberCache IMemberContainer.MemberCache {
1832 return member_cache;
1836 bool IMemberContainer.IsInterface {
1838 return this is Interface;
1842 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1844 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1849 public class Class : TypeContainer {
1851 // Modifiers allowed in a class declaration
1853 public const int AllowedModifiers =
1856 Modifiers.PROTECTED |
1857 Modifiers.INTERNAL |
1859 Modifiers.ABSTRACT |
1862 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1863 : base (parent, name, attrs, l)
1867 if (parent.Parent == null)
1868 accmods = Modifiers.INTERNAL;
1870 accmods = Modifiers.PUBLIC;
1872 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1875 public override AttributeTargets AttributeTargets {
1877 return AttributeTargets.Class;
1881 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
1883 if (a.UsageAttribute != null) {
1884 if (base_class_type != TypeManager.attribute_type && !base_class_type.IsSubclassOf (TypeManager.attribute_type) &&
1885 TypeBuilder.FullName != "System.Attribute") {
1886 Report.Error (641, a.Location, "Attribute '" + a.Name + "' is only valid on classes derived from System.Attribute");
1888 AttributeUsage = a.UsageAttribute;
1890 base.ApplyAttributeBuilder (a, cb);
1894 // FIXME: How do we deal with the user specifying a different
1897 public override TypeAttributes TypeAttr {
1899 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1904 public class Struct : TypeContainer {
1906 // Modifiers allowed in a struct declaration
1908 public const int AllowedModifiers =
1911 Modifiers.PROTECTED |
1912 Modifiers.INTERNAL |
1916 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1917 : base (parent, name, attrs, l)
1921 if (parent.Parent == null)
1922 accmods = Modifiers.INTERNAL;
1924 accmods = Modifiers.PUBLIC;
1926 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1928 this.ModFlags |= Modifiers.SEALED;
1931 public override AttributeTargets AttributeTargets {
1933 return AttributeTargets.Struct;
1938 // FIXME: Allow the user to specify a different set of attributes
1939 // in some cases (Sealed for example is mandatory for a class,
1940 // but what SequentialLayout can be changed
1942 public override TypeAttributes TypeAttr {
1944 return base.TypeAttr |
1945 TypeAttributes.SequentialLayout |
1946 TypeAttributes.Sealed |
1947 TypeAttributes.BeforeFieldInit;
1952 public abstract class MethodCore : MemberBase {
1953 public /* readonly */ Parameters Parameters;
1957 // Parameters, cached for semantic analysis.
1959 protected InternalParameters parameter_info;
1960 protected Type [] parameter_types;
1962 // Whether this is an operator
1963 public bool IsOperator;
1965 public MethodCore (Expression type, int mod, int allowed_mod, string name,
1966 Attributes attrs, Parameters parameters, Location loc)
1967 : base (type, mod, allowed_mod, name, attrs, loc)
1969 Parameters = parameters;
1973 // Returns the System.Type array for the parameters of this method
1975 public Type [] ParameterTypes {
1977 return parameter_types;
1981 public InternalParameters ParameterInfo
1984 return parameter_info;
1988 public Block Block {
1998 protected virtual bool DoDefineParameters (TypeContainer parent)
2000 // Check if arguments were correct
2001 parameter_types = Parameters.GetParameterInfo (parent);
2002 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2005 parameter_info = new InternalParameters (parent, Parameters);
2010 public CallingConventions GetCallingConvention (bool is_class)
2012 CallingConventions cc = 0;
2014 cc = Parameters.GetCallingConvention ();
2017 if ((ModFlags & Modifiers.STATIC) == 0)
2018 cc |= CallingConventions.HasThis;
2020 // FIXME: How is `ExplicitThis' used in C#?
2026 public class Method : MethodCore {
2027 public MethodBuilder MethodBuilder;
2028 public MethodData MethodData;
2031 /// Modifiers allowed in a class declaration
2033 const int AllowedModifiers =
2036 Modifiers.PROTECTED |
2037 Modifiers.INTERNAL |
2041 Modifiers.NONVIRTUAL |
2042 Modifiers.OVERRIDE |
2043 Modifiers.ABSTRACT |
2049 // return_type can be "null" for VOID values.
2051 public Method (Expression return_type, int mod, string name, Parameters parameters,
2052 Attributes attrs, Location l)
2053 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2058 public Method (Expression return_type, int mod, string name, Parameters parameters,
2059 Attributes attrs, ArrayList impl_what, Location l)
2060 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2062 Implements = impl_what;
2065 public override AttributeTargets AttributeTargets {
2067 return AttributeTargets.Method;
2072 // Returns the `System.Type' for the ReturnType of this
2073 // function. Provides a nice cache. (used between semantic analysis
2074 // and actual code generation
2076 public Type GetReturnType ()
2081 void DuplicateEntryPoint (MethodInfo b, Location location)
2085 "Program `" + CodeGen.FileName +
2086 "' has more than one entry point defined: `" +
2087 TypeManager.MonoBASIC_Signature(b) + "'");
2090 void Report28 (MethodInfo b)
2092 if (RootContext.WarningLevel < 4)
2097 "`" + TypeManager.MonoBASIC_Signature(b) +
2098 "' has the wrong signature to be an entry point");
2101 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2103 if (b.ReturnType != TypeManager.void_type &&
2104 b.ReturnType != TypeManager.int32_type)
2107 if (pinfo.Count == 0)
2110 if (pinfo.Count > 1)
2113 Type t = pinfo.ParameterType(0);
2115 (t.GetArrayRank() == 1) &&
2116 (t.GetElementType() == TypeManager.string_type) &&
2117 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2124 // Checks our base implementation if any
2126 protected override bool CheckBase (TypeContainer parent)
2128 // Check whether arguments were correct.
2129 if (!DoDefineParameters (parent))
2132 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2136 mi_this = TypeContainer.FindMembers (
2137 parent.TypeBuilder, MemberTypes.Method,
2138 BindingFlags.NonPublic | BindingFlags.Public |
2139 BindingFlags.Static | BindingFlags.Instance |
2140 BindingFlags.DeclaredOnly,
2141 MethodSignature.method_signature_filter, ms);
2143 if (mi_this.Count > 0) {
2144 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2145 "already defines a member called `" + Name + "' " +
2146 "with the same parameter types");
2152 // Verify if the parent has a type with the same name, and then
2153 // check whether we have to create a new slot for it or not.
2155 Type ptype = parent.TypeBuilder.BaseType;
2157 // ptype is only null for System.Object while compiling corlib.
2159 MemberList mi, mi_static, mi_instance;
2161 mi_static = TypeContainer.FindMembers (
2162 ptype, MemberTypes.Method,
2163 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2164 MethodSignature.inheritable_method_signature_filter, ms);
2166 mi_instance = TypeContainer.FindMembers (
2167 ptype, MemberTypes.Method,
2168 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2169 MethodSignature.inheritable_method_signature_filter,
2172 if (mi_instance.Count > 0){
2174 } else if (mi_static.Count > 0)
2179 if (mi != null && mi.Count > 0){
2180 parent_method = (MethodInfo) mi [0];
2181 string name = parent_method.DeclaringType.Name + "." +
2184 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2187 if ((ModFlags & Modifiers.NEW) == 0) {
2188 Type parent_ret = TypeManager.TypeToCoreType (
2189 parent_method.ReturnType);
2191 if (parent_ret != MemberType) {
2193 508, parent.MakeName (Name) + ": cannot " +
2194 "change return type when overriding " +
2195 "inherited member " + name);
2200 /*if ((ModFlags & Modifiers.NEW) != 0)
2201 WarningNotHiding (parent);*/
2203 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2204 Report.Error (30284, Location,
2205 parent.MakeName (Name) +
2206 " : No suitable methods found to override");
2208 if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0)
2210 if ((ModFlags & Modifiers.NONVIRTUAL) != 0)
2212 Report.Error (31088, Location,
2213 parent.MakeName (Name) + " : Cannot " +
2214 "be declared NotOverridable since this method is " +
2215 "not maked as Overrides");
2218 // if a member of module is not inherited from Object class
2219 // can not be declared protected
2220 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
2221 Report.Error (31066, Location,
2222 "'Sub' or 'Function' inside a 'Module' can not be declared as " +
2223 "'Protected' or 'Protected Friend'");
2226 /* else if ((ModFlags & Modifiers.NEW) != 0)
2227 WarningNotHiding (parent);
2236 public override bool Define (TypeContainer parent)
2238 if (!DoDefine (parent))
2241 if (!CheckBase (parent))
2244 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
2245 Report.Error (31067, Location,
2246 "'Sub' or 'Function' inside a 'Structure' can not be declared as " +
2247 "'Protected' or 'Protected Friend'");
2249 CallingConventions cc = GetCallingConvention (parent is Class);
2251 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2252 ParameterInfo, cc, OptAttributes,
2253 ModFlags, flags, true);
2255 if (!MethodData.Define (parent))
2258 MethodBuilder = MethodData.MethodBuilder;
2261 // This is used to track the Entry Point,
2263 if (Name.ToUpper() == "MAIN" &&
2264 ((ModFlags & Modifiers.STATIC) != 0) &&
2265 (RootContext.MainClass == null ||
2266 RootContext.MainClass == parent.TypeBuilder.FullName ||
2267 (RootContext.RootNamespace != null &&
2268 RootContext.RootNamespace.Length > 0 &&
2269 (RootContext.RootNamespace + "." + RootContext.MainClass) == parent.TypeBuilder.FullName))) {
2270 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2271 if (RootContext.EntryPoint == null) {
2272 RootContext.EntryPoint = MethodBuilder;
2273 RootContext.EntryPointLocation = Location;
2275 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2276 DuplicateEntryPoint (MethodBuilder, Location);
2279 Report28(MethodBuilder);
2288 public void Emit (TypeContainer parent)
2290 MethodData.Emit (parent, Block, this);
2293 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2295 throw new Exception ("FIXME: I am just a placeholder implementation");
2299 public abstract class ConstructorInitializer {
2300 ArrayList argument_list;
2301 ConstructorInfo parent_constructor;
2302 Parameters parameters;
2304 public bool implicit_initialization;
2306 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2309 this.argument_list = argument_list;
2310 this.parameters = parameters;
2312 this.implicit_initialization = false;
2315 public ArrayList Arguments {
2317 return argument_list;
2321 public ConstructorInfo ParentConstructor
2325 return parent_constructor;
2329 public bool Resolve (EmitContext ec)
2331 Expression parent_constructor_group;
2334 ec.CurrentBlock = new Block (null, true, parameters);
2336 if (argument_list != null){
2337 foreach (Argument a in argument_list){
2338 if (!a.Resolve (ec, loc))
2343 ec.CurrentBlock = null;
2345 if (this is ConstructorBaseInitializer) {
2346 if (ec.ContainerType.BaseType == null)
2349 t = ec.ContainerType.BaseType;
2350 if (ec.ContainerType.IsValueType){
2351 Report.Error (522, loc,
2352 "structs cannot call base class constructors");
2357 t = ec.ContainerType;
2359 parent_constructor_group = Expression.MemberLookup (
2361 MemberTypes.Constructor,
2362 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2365 if (parent_constructor_group == null){
2366 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2370 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2371 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2373 if (parent_constructor == null) {
2374 if (this.implicit_initialization)
2375 Report.Error (30148, loc, "Must declare 'MyBase.New' in the constructor " +
2376 "of the class '" + ec.TypeContainer.Name + "' with appropriate arguments, since the base class '" +
2377 t.FullName + "' does not contain a definition of 'New' without any parameter");
2379 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2387 public void Emit (EmitContext ec)
2389 if (parent_constructor != null){
2391 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2393 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2400 public class ConstructorBaseInitializer : ConstructorInitializer {
2401 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2402 base (argument_list, pars, l)
2407 public class ConstructorThisInitializer : ConstructorInitializer {
2408 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2409 base (argument_list, pars, l)
2414 public class Constructor : MethodCore {
2415 public ConstructorBuilder ConstructorBuilder;
2416 public ConstructorInitializer Initializer;
2419 // Modifiers allowed for a constructor.
2421 public const int AllowedModifiers =
2423 Modifiers.PROTECTED |
2424 Modifiers.INTERNAL |
2431 // The spec claims that static is not permitted, but
2432 // my very own code has static constructors.
2434 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2435 : base (null, 0, AllowedModifiers, name, null, args, l)
2440 public Constructor (string name, int mod, Parameters args, ConstructorInitializer init, Location l)
2441 : base (null, mod, AllowedModifiers, name, null, args, l)
2446 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2448 ConstructorBuilder.SetCustomAttribute (cb);
2451 public override AttributeTargets AttributeTargets {
2453 return AttributeTargets.Constructor;
2458 // Returns true if this is a default constructor
2460 public bool IsDefault ()
2462 if ((ModFlags & Modifiers.STATIC) != 0)
2463 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2464 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2467 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2468 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2469 (Initializer is ConstructorBaseInitializer) &&
2470 (Initializer.Arguments == null);
2474 // Creates the ConstructorBuilder
2476 public override bool Define (TypeContainer parent)
2478 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2479 MethodAttributes.SpecialName);
2481 if (parent.EventHandlers != null) {
2482 ArrayList hdlrs = parent.EventHandlers;
2483 foreach(Statement stmt in hdlrs)
2484 this.Block.AddStatement (stmt);
2488 // Check if arguments were correct.
2489 if (!DoDefineParameters (parent))
2492 if ((ModFlags & Modifiers.STATIC) != 0) {
2493 ca |= MethodAttributes.Static;
2495 if (this.Parameters != Parameters.EmptyReadOnlyParameters)
2498 "Shared constructor can not have parameters");
2500 if ((ModFlags & Modifiers.Accessibility) != 0)
2503 "Shared constructor can not be declared " +
2504 "explicitly as public, private, friend or protected");
2506 if (this.Initializer != null)
2509 "Keywords like MyBase, MyClass, Me are not " +
2510 "valid inside a Shared Constructor");
2513 if (parent is Struct && ParameterTypes.Length == 0) {
2516 "Structs can not contain explicit parameterless " +
2520 ca |= MethodAttributes.HideBySig;
2522 if ((ModFlags & Modifiers.PUBLIC) != 0)
2523 ca |= MethodAttributes.Public;
2524 else if ((ModFlags & Modifiers.PROTECTED) != 0) {
2525 if ((ModFlags & Modifiers.INTERNAL) != 0)
2526 ca |= MethodAttributes.FamORAssem;
2528 ca |= MethodAttributes.Family;
2530 else if ((ModFlags & Modifiers.INTERNAL) != 0)
2531 ca |= MethodAttributes.Assembly;
2532 else if (IsDefault ())
2533 ca |= MethodAttributes.Public;
2535 ca |= MethodAttributes.Private;
2538 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2539 ca, GetCallingConvention (parent is Class), ParameterTypes);
2542 // HACK because System.Reflection.Emit is lame
2544 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2547 "Class `" +parent.Name+ "' already contains a definition with the " +
2548 "same return value and parameter types for constructor `" + Name
2559 public void Emit (TypeContainer parent)
2561 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2562 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2564 if ((ModFlags & Modifiers.STATIC) == 0){
2565 if (parent is Class && Initializer == null) {
2566 Initializer = new ConstructorBaseInitializer (
2567 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2568 Initializer.implicit_initialization = true;
2572 // Spec mandates that Initializers will not have
2576 if (Initializer != null && !Initializer.Resolve (ec))
2578 ec.IsStatic = false;
2581 Parameters.LabelParameters (ec, ConstructorBuilder, Location);
2584 // Classes can have base initializers and instance field initializers.
2586 if (parent is Class){
2587 if ((ModFlags & Modifiers.STATIC) == 0)
2588 parent.EmitFieldInitializers (ec);
2591 if (Initializer != null) {
2592 if (this.ConstructorBuilder.Equals (Initializer.ParentConstructor))
2595 "A constructor can not call itself" );
2597 Initializer.Emit (ec);
2600 if ((ModFlags & Modifiers.STATIC) != 0)
2601 parent.EmitFieldInitializers (ec);
2603 if (OptAttributes != null)
2604 OptAttributes.Emit (ec, this);
2606 // If this is a non-static `struct' constructor and doesn't have any
2607 // initializer, it must initialize all of the struct's fields.
2608 if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2609 (Initializer == null))
2610 Block.AddThisVariable (parent, Location);
2612 ec.EmitTopBlock (Block, ParameterInfo, Location);
2616 public class MethodData {
2618 // The return type of this method
2620 public readonly Type ReturnType;
2621 public readonly Type[] ParameterTypes;
2622 public readonly InternalParameters ParameterInfo;
2623 public readonly CallingConventions CallingConventions;
2624 public readonly Attributes OptAttributes;
2625 public readonly Location Location;
2628 // Are we implementing an interface ?
2630 public bool IsImplementing = false;
2635 readonly MemberBase member;
2636 readonly int modifiers;
2637 MethodAttributes flags;
2638 readonly bool is_method;
2639 readonly string accessor_name;
2640 ArrayList conditionals;
2642 MethodBuilder builder = null;
2643 public MethodBuilder MethodBuilder {
2649 public MethodData (MemberBase member, string name, Type return_type,
2650 Type [] parameter_types, InternalParameters parameters,
2651 CallingConventions cc, Attributes opt_attrs,
2652 int modifiers, MethodAttributes flags, bool is_method)
2654 this.member = member;
2655 this.accessor_name = name;
2656 this.ReturnType = return_type;
2657 this.ParameterTypes = parameter_types;
2658 this.ParameterInfo = parameters;
2659 this.CallingConventions = cc;
2660 this.OptAttributes = opt_attrs;
2661 this.modifiers = modifiers;
2663 this.is_method = is_method;
2664 this.Location = member.Location;
2665 this.conditionals = new ArrayList ();
2671 Attribute dllimport_attribute = null;
2672 string obsolete = null;
2673 bool obsolete_error = false;
2675 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2677 if ((opt_attrs == null) || (opt_attrs.Attrs == null))
2680 foreach (Attribute a in opt_attrs.Attrs) {
2681 if (a.Name == "Conditional") {
2682 if (!ApplyConditionalAttribute (a))
2684 } else if (a.Name == "Obsolete") {
2685 if (!ApplyObsoleteAttribute (a))
2687 } else if (a.Name.IndexOf ("DllImport") != -1) {
2689 a.Type = TypeManager.dllimport_type;
2690 Attribute.Error_AttributeNotValidForElement (a, Location);
2693 if (!ApplyDllImportAttribute (a))
2702 // Applies the `DllImport' attribute to the method.
2704 protected virtual bool ApplyDllImportAttribute (Attribute a)
2706 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2707 if ((modifiers & extern_static) != extern_static) {
2708 Report.Error (601, Location,
2709 "The DllImport attribute must be specified on a method " +
2710 "marked `static' and `extern'.");
2714 flags |= MethodAttributes.PinvokeImpl;
2715 dllimport_attribute = a;
2720 // Applies the `Obsolete' attribute to the method.
2722 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2724 if (obsolete != null) {
2725 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2729 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2730 return obsolete != null;
2734 // Applies the `Conditional' attribute to the method.
2736 protected virtual bool ApplyConditionalAttribute (Attribute a)
2738 // The Conditional attribute is only valid on methods.
2740 Attribute.Error_AttributeNotValidForElement (a, Location);
2744 string condition = a.Conditional_GetConditionName ();
2746 if (condition == null)
2749 if (ReturnType != TypeManager.void_type) {
2750 Report.Error (578, Location,
2751 "Conditional not valid on `" + member.Name + "' " +
2752 "because its return type is not void");
2756 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2757 Report.Error (243, Location,
2758 "Conditional not valid on `" + member.Name + "' " +
2759 "because it is an override method");
2763 if (member.IsExplicitImpl) {
2764 Report.Error (577, Location,
2765 "Conditional not valid on `" + member.Name + "' " +
2766 "because it is an explicit interface implementation");
2770 if (IsImplementing) {
2771 Report.Error (623, Location,
2772 "Conditional not valid on `" + member.Name + "' " +
2773 "because it is an interface method");
2777 conditionals.Add (condition);
2783 // Checks whether this method should be ignored due to its Conditional attributes.
2785 bool ShouldIgnore (Location loc)
2787 // When we're overriding a virtual method, we implicitly inherit the
2788 // Conditional attributes from our parent.
2789 if (member.ParentMethod != null) {
2790 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2791 member.ParentMethod, loc);
2793 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2797 foreach (string condition in conditionals)
2798 if (RootContext.AllDefines [condition] == null)
2805 // Returns the TypeManager.MethodFlags for this method.
2806 // This emits an error 619 / warning 618 if the method is obsolete.
2807 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2809 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2811 TypeManager.MethodFlags flags = 0;
2813 if (obsolete != null) {
2814 if (obsolete_error) {
2815 Report.Error (619, loc, "Method `" + member.Name +
2816 "' is obsolete: `" + obsolete + "'");
2817 return TypeManager.MethodFlags.IsObsoleteError;
2819 Report.Warning (618, loc, "Method `" + member.Name +
2820 "' is obsolete: `" + obsolete + "'");
2822 flags |= TypeManager.MethodFlags.IsObsolete;
2825 if (ShouldIgnore (loc))
2826 flags |= TypeManager.MethodFlags.ShouldIgnore;
2832 // Search all the interface bases recursively for unimplemented methods
2834 bool SearchBasesForAbstractMethods (
2835 TypeContainer parent, Type iface_type,
2836 string method_name, ref ArrayList implementing_list,
2837 ref ArrayList implementing_iface)
2839 MethodInfo implementing = null;
2840 bool IsImplementing = false;
2841 Type current_iface_type = iface_type;
2843 implementing = parent.Pending.IsAbstractMethod (
2844 current_iface_type, method_name, ReturnType, ParameterTypes);
2846 if (implementing != null) {
2847 if (!implementing_list.Contains (implementing)) {
2848 implementing_list.Add (implementing);
2849 implementing_iface.Add(current_iface_type);
2851 IsImplementing = true;
2853 Type[] current_iface_types = current_iface_type.GetInterfaces();
2854 if (current_iface_types.Length == 0)
2857 foreach (Type curr_iface_type in current_iface_types) {
2858 IsImplementing = SearchBasesForAbstractMethods (
2859 parent, curr_iface_type, method_name,
2860 ref implementing_list, ref implementing_iface);
2867 return IsImplementing;
2870 public virtual bool Define (TypeContainer parent)
2872 MethodInfo implementing = null;
2873 ArrayList implementing_list = null;
2874 ArrayList implementing_iface = null;
2875 string method_name, name, prefix, impl_method_name;
2878 if (OptAttributes != null)
2879 if (!ApplyAttributes (OptAttributes, is_method))
2882 if (accessor_name != null)
2883 name = accessor_name + "_" + member.ShortName;
2885 name = member.ShortName;
2888 impl_method_name = name;
2890 if ((member.ModFlags & Modifiers.OVERRIDE) != 0) {
2891 if (parent.Pending == null)
2892 implementing = null;
2894 implementing = parent.Pending.IsAbstractMethod (
2895 (Type) parent.TypeBuilder.BaseType, name,
2896 ReturnType, ParameterTypes);
2898 if (implementing != null)
2899 IsImplementing = true;
2902 if (member.Implements != null) {
2903 implementing_list = new ArrayList();
2904 implementing_iface = new ArrayList();
2906 foreach (Expression Impl in member.Implements) {
2907 name = Impl.ToString();
2908 prefix = name.Substring(0, name.LastIndexOf("."));
2909 name = name.Substring(name.LastIndexOf(".") + 1);
2911 if (accessor_name != null)
2912 impl_method_name = accessor_name + "_" + name;
2914 impl_method_name = name;
2916 Type current_iface_type = (Type) member.InterfaceTypes[++pos];
2917 IsImplementing = SearchBasesForAbstractMethods (
2918 parent, current_iface_type, impl_method_name,
2919 ref implementing_list, ref implementing_iface);
2921 if (IsImplementing == false) {
2922 TypeContainer.Error_NotInterfaceMember (
2923 Location, name, prefix);
2930 // For implicit implementations, make sure we are public, for
2931 // explicit implementations, make sure we are private.
2933 //if (IsImplementing){
2935 // Setting null inside this block will trigger a more
2936 // verbose error reporting for missing interface implementations
2938 // The "candidate" function has been flagged already
2939 // but it wont get cleared
2941 /* if (!member.IsExplicitImpl){
2943 // We already catch different accessibility settings
2944 // so we just need to check that we are not private
2946 if ((modifiers & Modifiers.PRIVATE) != 0)
2947 implementing = null;
2950 // Static is not allowed
2952 if ((modifiers & Modifiers.STATIC) != 0)
2953 implementing = null;
2955 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2956 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2957 implementing = null;
2963 // If implementing is still valid, set flags
2965 if (IsImplementing){
2967 // When implementing interface methods, set NewSlot.
2969 if (implementing_list != null && implementing_list.Count != 0)
2970 flags |= MethodAttributes.NewSlot;
2973 MethodAttributes.Virtual |
2974 MethodAttributes.HideBySig;
2978 // Create the MethodBuilder for the method
2980 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2981 if ((modifiers & Modifiers.STATIC) == 0) {
2982 Report.Error (601, Location,
2983 "The DllImport attribute must be specified on " +
2984 "a method marked 'static' and 'extern'.");
2988 EmitContext ec = new EmitContext (
2989 parent, Location, null, ReturnType, modifiers);
2991 builder = dllimport_attribute.DefinePInvokeMethod (
2992 ec, parent.TypeBuilder, method_name, flags,
2993 ReturnType, ParameterTypes);
2995 builder = parent.TypeBuilder.DefineMethod (
2996 method_name, flags, CallingConventions,
2997 ReturnType, ParameterTypes);
2999 if (builder == null)
3002 if (IsImplementing) {
3004 // implement abstract methods from abstract classes
3006 if ((member.ModFlags & Modifiers.OVERRIDE) != 0) {
3008 if (member is Indexer)
3009 parent.Pending.ImplementIndexer (
3010 (Type) parent.TypeBuilder.BaseType,
3011 builder, ReturnType,
3012 ParameterTypes, true);
3015 parent.Pending.ImplementMethod (
3016 (Type) parent.TypeBuilder.BaseType,
3018 ParameterTypes, member.IsExplicitImpl);
3022 // implement abstract methods of interfaces
3024 if (member.Implements != null) {
3026 foreach (MethodInfo Impl in implementing_list) {
3029 if (member is Indexer)
3030 parent.Pending.ImplementIndexer (
3031 (Type) implementing_iface[pos++],
3032 builder, ReturnType,
3033 ParameterTypes, true);
3036 parent.Pending.ImplementMethod (
3037 (Type) implementing_iface[pos++],
3038 Impl.Name, ReturnType,
3039 ParameterTypes, member.IsExplicitImpl);
3041 parent.TypeBuilder.DefineMethodOverride (
3048 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3049 Report.Error (111, Location,
3050 "Class `" + parent.Name +
3051 "' already contains a definition with the " +
3052 "same return value and parameter types as the " +
3053 "'get' method of property `" + member.Name + "'");
3057 TypeManager.AddMethod (builder, this);
3064 public virtual void Emit (TypeContainer parent, Block block, object kind)
3069 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3070 ig = builder.GetILGenerator ();
3074 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3076 if (OptAttributes != null)
3077 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3079 if (member is MethodCore)
3080 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, ((MethodCore) member).Location);
3083 // abstract or extern methods have no bodies
3085 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3090 // abstract or extern methods have no bodies.
3092 if ((modifiers & Modifiers.ABSTRACT) != 0)
3094 500, Location, "Abstract method `" +
3095 TypeManager.MonoBASIC_Signature (builder) +
3096 "' can not have a body");
3098 if ((modifiers & Modifiers.EXTERN) != 0)
3100 179, Location, "External method `" +
3101 TypeManager.MonoBASIC_Signature (builder) +
3102 "' can not have a body");
3108 // Methods must have a body unless they're extern or abstract
3110 if (block == null) {
3112 501, Location, "Method `" +
3113 TypeManager.MonoBASIC_Signature (builder) +
3114 "' must declare a body since it is not marked " +
3115 "abstract or extern");
3120 // Handle destructors specially
3122 // FIXME: This code generates buggy code
3124 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3125 EmitDestructor (ec, block);
3127 ISymbolWriter sw = CodeGen.SymbolWriter;
3129 if ((sw != null) && !Location.IsNull (Location) &&
3130 !Location.IsNull (block.EndLocation)) {
3131 Location end = block.EndLocation;
3132 MethodToken token = MethodBuilder.GetToken ();
3133 sw.OpenMethod (new SymbolToken (token.Token));
3134 // Avoid error if we don't support debugging for the platform
3136 sw.SetMethodSourceRange (Location.SymbolDocument,
3140 } catch (Exception) {
3143 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3147 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3151 void EmitDestructor (EmitContext ec, Block block)
3153 ILGenerator ig = ec.ig;
3155 Label finish = ig.DefineLabel ();
3156 bool old_in_try = ec.InTry;
3158 ig.BeginExceptionBlock ();
3160 ec.ReturnLabel = finish;
3161 ec.HasReturnLabel = true;
3162 ec.EmitTopBlock (block, null, Location);
3163 ec.InTry = old_in_try;
3165 // ig.MarkLabel (finish);
3166 bool old_in_finally = ec.InFinally;
3167 ec.InFinally = true;
3168 ig.BeginFinallyBlock ();
3170 if (ec.ContainerType.BaseType != null) {
3171 Expression member_lookup = Expression.MemberLookup (
3172 ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3173 MemberTypes.Method, Expression.AllBindingFlags, Location);
3175 if (member_lookup != null){
3176 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3178 ig.Emit (OpCodes.Ldarg_0);
3179 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3182 ec.InFinally = old_in_finally;
3184 ig.EndExceptionBlock ();
3185 //ig.MarkLabel (ec.ReturnLabel);
3186 ig.Emit (OpCodes.Ret);
3190 abstract public class MemberBase : MemberCore {
3191 public Expression Type;
3192 public ArrayList Implements;
3194 protected MethodAttributes flags;
3197 // The "short" name of this property / indexer / event. This is the
3198 // name without the explicit interface.
3200 public string ShortName;
3203 // The type of this property / indexer / event
3205 public Type MemberType;
3208 // If true, this is an explicit interface implementation
3210 public bool IsExplicitImpl = false;
3213 // The name of the interface we are explicitly implementing
3215 public string ExplicitInterfaceName = null;
3218 // If true, the interface type we are explicitly implementing
3220 public Type InterfaceType = null;
3221 public ArrayList InterfaceTypes = null;
3224 // The method we're overriding if this is an override method.
3226 protected MethodInfo parent_method = null;
3227 public MethodInfo ParentMethod {
3229 return parent_method;
3234 // The constructor is only exposed to our children
3236 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3237 Attributes attrs, Location loc)
3238 : base (name, attrs, loc)
3241 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PUBLIC, loc);
3244 protected virtual bool CheckBase (TypeContainer parent)
3249 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3253 foreach (Type partype in parameters){
3254 if (partype.IsPointer && !UnsafeOK (parent))
3257 if (parent.AsAccessible (partype, ModFlags))
3260 Report.Error (51, Location,
3261 "Inconsistent accessibility: parameter type `" +
3262 TypeManager.MonoBASIC_Name (partype) + "' is less " +
3263 "accessible than method `" + Name + "'");
3270 protected virtual bool DoDefine (TypeContainer parent)
3275 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3278 flags = Modifiers.MethodAttr (ModFlags);
3280 // Lookup Type, verify validity
3281 MemberType = parent.ResolveType (Type, false, Location);
3282 if (MemberType == null)
3285 // check for whether the Interface is implemented by the class
3286 if (Implements != null) {
3287 InterfaceTypes = new ArrayList ();
3288 foreach (Expression Impls in Implements) {
3289 string iname = Impls.ToString();
3290 iname = iname.Substring(0, iname.LastIndexOf("."));
3291 bool iface_found = false;
3293 InterfaceType = RootContext.LookupType (
3294 parent, iname, false, Location);
3295 if (InterfaceType == null)
3298 InterfaceTypes.Add (InterfaceType);
3299 Type[] tbases = parent.TypeBuilder.GetInterfaces();
3301 if (tbases.Length != 0) {
3302 ArrayList bases = new ArrayList();
3303 TypeManager.ExpandAllInterfaces (tbases, ref bases);
3305 foreach (Type tbase in bases) {
3306 string bname = tbase.Name;
3307 if (bname.LastIndexOf(".") != -1)
3308 bname = bname.Substring(bname.LastIndexOf("."));
3310 if (bname == iname) {
3318 Report.Error (31035, Location,
3319 "Class '" + parent.Name + "' doesn't implement interface '" + iname + "'");
3325 // verify accessibility
3326 if (!parent.AsAccessible (MemberType, ModFlags)) {
3327 if (this is Property)
3328 Report.Error (53, Location,
3329 "Inconsistent accessibility: property type `" +
3330 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3331 "accessible than property `" + Name + "'");
3332 else if (this is Method)
3333 Report.Error (50, Location,
3334 "Inconsistent accessibility: return type `" +
3335 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3336 "accessible than method `" + Name + "'");
3338 Report.Error (52, Location,
3339 "Inconsistent accessibility: field type `" +
3340 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3341 "accessible than field `" + Name + "'");
3345 if (MemberType.IsPointer && !UnsafeOK (parent))
3349 // Check for explicit interface implementation
3351 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)) {
3352 int pos = Name.LastIndexOf (".");
3354 ExplicitInterfaceName = Name.Substring (0, pos);
3355 ShortName = Name.Substring (pos + 1);
3364 // Fields and Events both generate FieldBuilders, we use this to share
3365 // their common bits. This is also used to flag usage of the field
3367 abstract public class FieldBase : MemberBase {
3368 public FieldBuilder FieldBuilder;
3369 public Status status;
3372 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3375 // The constructor is only exposed to our children
3377 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3378 object init, Attributes attrs, Location loc)
3379 : base (type, mod, allowed_mod, name, attrs, loc)
3384 public override AttributeTargets AttributeTargets {
3386 return AttributeTargets.Field;
3392 // Whether this field has an initializer.
3394 public bool HasInitializer {
3396 return init != null;
3401 readonly Object init;
3402 Expression init_expr;
3403 bool init_expr_initialized = false;
3406 // Resolves and returns the field initializer.
3408 public Expression GetInitializerExpression (EmitContext ec)
3410 if (init_expr_initialized)
3414 if (init is Expression)
3415 e = (Expression) init;
3417 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3419 ec.IsFieldInitializer = true;
3420 e = e.DoResolve (ec);
3421 ec.IsFieldInitializer = false;
3424 init_expr_initialized = true;
3432 // The Field class is used to represents class/struct fields during parsing.
3434 public class Field : FieldBase {
3436 // Modifiers allowed in a class declaration
3438 const int AllowedModifiers =
3441 Modifiers.PROTECTED |
3442 Modifiers.INTERNAL |
3445 // Modifiers.VOLATILE |
3446 // Modifiers.UNSAFE |
3449 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3450 Attributes attrs, Location loc)
3451 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3455 public override AttributeTargets AttributeTargets {
3457 return AttributeTargets.Field;
3461 public override bool Define (TypeContainer parent)
3463 Type t = parent.ResolveType (Type, false, Location);
3468 if (!parent.AsAccessible (t, ModFlags)) {
3469 Report.Error (52, Location,
3470 "Inconsistent accessibility: field type `" +
3471 TypeManager.MonoBASIC_Name (t) + "' is less " +
3472 "accessible than field `" + Name + "'");
3476 if (t.IsPointer && !UnsafeOK (parent))
3479 Type ptype = parent.TypeBuilder.BaseType;
3481 // ptype is only null for System.Object while compiling corlib.
3483 MemberList list = TypeContainer.FindMembers (
3484 ptype, MemberTypes.Field,
3485 BindingFlags.Public |
3486 BindingFlags.Static | BindingFlags.Instance,
3487 System.Type.FilterName, Name);
3489 if (RootContext.WarningLevel > 1){
3490 if ((list.Count > 0) && ((ModFlags & Modifiers.SHADOWS) == 0))
3494 "Variable '" + Name + "' should be declared " +
3495 "Shadows since the base type '" + ptype.Name +
3496 "' has a variable with same name");
3498 ModFlags |= Modifiers.SHADOWS;
3501 if (list.Count == 0)
3502 // if a member of module is not inherited from Object class
3503 // can not be declared protected
3504 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
3505 Report.Error (30593, Location,
3506 "'Variable' inside a 'Module' can not be " +
3507 "declared as 'Protected'");
3510 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
3511 Report.Error (30435, Location,
3512 "'Variable' inside a 'Structure' can not be " +
3513 "declared as 'Protected'");
3515 if ((ModFlags & Modifiers.VOLATILE) != 0){
3517 if (TypeManager.IsEnumType (t))
3518 t = TypeManager.EnumToUnderlying (t);
3520 if (!((t == TypeManager.bool_type) ||
3521 (t == TypeManager.sbyte_type) ||
3522 (t == TypeManager.byte_type) ||
3523 (t == TypeManager.short_type) ||
3524 (t == TypeManager.ushort_type) ||
3525 (t == TypeManager.int32_type) ||
3526 (t == TypeManager.uint32_type) ||
3527 (t == TypeManager.char_type) ||
3528 (t == TypeManager.float_type))){
3530 677, Location, parent.MakeName (Name) +
3531 " A volatile field can not be of type `" +
3532 TypeManager.MonoBASIC_Name (t) + "'");
3538 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3540 if (parent is Struct &&
3541 ((fa & FieldAttributes.Static) == 0) &&
3542 t == parent.TypeBuilder &&
3543 !TypeManager.IsBuiltinType (t)){
3544 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
3545 "' causes a cycle in the structure layout");
3548 FieldBuilder = parent.TypeBuilder.DefineField (
3549 Name, t, Modifiers.FieldAttr (ModFlags));
3551 TypeManager.RegisterFieldBase (FieldBuilder, this);
3555 public void Emit (TypeContainer tc)
3557 EmitContext ec = new EmitContext (tc, Location, null,
3558 FieldBuilder.FieldType, ModFlags);
3560 if (OptAttributes != null)
3561 OptAttributes.Emit (ec, this);
3564 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3566 FieldBuilder.SetCustomAttribute (cb);
3572 // `set' and `get' accessors are represented with an Accessor.
3574 public class Accessor {
3576 // Null if the accessor is empty, or a Block if not
3579 public Attributes OptAttributes;
3581 public Accessor (Block b, Attributes attrs)
3584 OptAttributes = attrs;
3588 public class GetMethod {
3589 private Accessor Get;
3590 public MethodData GetData;
3591 public MethodBuilder GetBuilder;
3593 Property parent_property;
3596 Parameters get_params;
3598 public GetMethod (Property parent_property, Accessor get_block, Attributes attrs, Parameters p_get, Location loc)
3600 this.parent_property = parent_property;
3606 public MethodBuilder Define (TypeContainer parent)
3608 Type [] g_parameters=null;
3609 Parameter [] g_parms;
3610 InternalParameters g_ip=null;
3612 if (get_params == Parameters.EmptyReadOnlyParameters) {
3613 g_parameters = TypeManager.NoTypes;
3614 g_ip = new InternalParameters (parent, Parameters.EmptyReadOnlyParameters);
3616 g_parameters = new Type [get_params.FixedParameters.Length];
3617 for (int i = 0; i < get_params.FixedParameters.Length; i ++) {
3618 g_parameters[i] = get_params.FixedParameters[i].ParameterType;
3620 g_parms = new Parameter [get_params.FixedParameters.Length];
3621 for (int i = 0; i < get_params.FixedParameters.Length; i ++) {
3622 Parameter tp = get_params.FixedParameters[i];
3623 g_parms[i] = new Parameter (tp.TypeName, tp.Name,
3624 Parameter.Modifier.NONE, null);
3626 g_ip = new InternalParameters (
3627 parent, new Parameters (g_parms, null, Location));
3630 GetData = new MethodData (parent_property, "get", parent_property.MemberType,
3631 g_parameters, g_ip, CallingConventions.Standard,
3632 Get.OptAttributes, parent_property.ModFlags, parent_property.MethodAttributeFlags, false);
3634 if (!GetData.Define (parent))
3637 GetBuilder = GetData.MethodBuilder;
3642 public void Emit (TypeContainer tc)
3644 if (GetData != null)
3646 parent_property.Parameters = get_params;
3647 GetData.Emit (tc, Get.Block, Get);
3652 public class SetMethod {
3655 MethodBuilder SetBuilder;
3657 Property parent_property;
3660 string set_parameter_name;
3661 Parameters set_params;
3663 public SetMethod (Property parent_property, Accessor set_block, string set_name,
3664 Parameters p_set, Location loc)
3666 this.parent_property = parent_property;
3669 set_parameter_name = set_name;
3670 this.Location = loc;
3673 public MethodBuilder Define (TypeContainer parent)
3675 Type [] s_parameters=null;
3676 Parameter [] s_parms;
3677 InternalParameters s_ip=null;
3679 if (set_params == Parameters.EmptyReadOnlyParameters)
3681 s_parameters = new Type [1];
3682 s_parameters [0] = parent_property.MemberType;
3684 s_parms = new Parameter [1];
3685 s_parms [0] = new Parameter (parent_property.Type, set_parameter_name,
3686 Parameter.Modifier.NONE, null);
3688 s_parameters = new Type [set_params.FixedParameters.Length];
3689 for (int i = 0; i < set_params.FixedParameters.Length; i ++) {
3690 s_parameters[i] = set_params.FixedParameters[i].ParameterType;
3693 s_parms = new Parameter [set_params.FixedParameters.Length];
3694 for (int i = 0; i < set_params.FixedParameters.Length; i ++) {
3695 Parameter tp = set_params.FixedParameters[i];
3696 s_parms[i] = new Parameter (tp.TypeName, tp.Name,
3697 Parameter.Modifier.NONE, null);
3701 s_ip = new InternalParameters (
3702 parent, new Parameters (s_parms, null, Location));
3704 SetData = new MethodData (parent_property, "set", TypeManager.void_type,
3705 s_parameters, s_ip, CallingConventions.Standard,
3706 Set.OptAttributes, parent_property.ModFlags, parent_property.MethodAttributeFlags, false);
3708 if (!SetData.Define (parent))
3711 SetBuilder = SetData.MethodBuilder;
3712 SetBuilder.DefineParameter (1, ParameterAttributes.None,
3713 set_parameter_name);
3718 public void Emit (TypeContainer tc)
3720 if (SetData != null)
3722 parent_property.Parameters = set_params;
3723 SetData.Emit (tc, Set.Block, Set);
3728 public class Property : MethodCore {
3729 GetMethod GetMethod;
3730 SetMethod SetMethod;
3732 public Accessor Set;
3733 public PropertyBuilder PropertyBuilder;
3734 public MethodBuilder GetBuilder;
3735 public MethodBuilder SetBuilder;
3736 public MethodData SetData;
3738 protected EmitContext ec;
3740 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3742 PropertyBuilder.SetCustomAttribute (cb);
3745 public override AttributeTargets AttributeTargets {
3747 return AttributeTargets.Property;
3751 protected override bool DoDefine (TypeContainer parent)
3753 if (!base.DoDefine (parent))
3756 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3762 // Checks our base implementation if any
3764 protected override bool CheckBase (TypeContainer container)
3766 base.CheckBase (container);
3768 // Check whether arguments were correct.
3769 if (!DoDefineParameters (container))
3775 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
3780 mi_this = TypeContainer.FindMembers (
3781 container.TypeBuilder, MemberTypes.Property,
3782 BindingFlags.NonPublic | BindingFlags.Public |
3783 BindingFlags.Static | BindingFlags.Instance |
3784 BindingFlags.DeclaredOnly,
3785 MethodSignature.method_signature_filter, ms);
3787 if (mi_this.Count > 0) {
3788 Report.Error (111, Location, "Class `" + container.Name + "' " +
3789 "already defines a member called `" + Name + "' " +
3790 "with the same parameter types");
3795 if (container is Interface)
3799 if ((ModFlags & Modifiers.READONLY) != 0)
3800 retval = MemberType;
3803 MethodSignature base_ms;
3806 if (this is Indexer) {
3807 string name, base_name;
3809 report_name = "this";
3810 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
3811 ms = new MethodSignature (name, null, ParameterTypes);
3812 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
3813 base_ms = new MethodSignature (base_name, retval, ParameterTypes);
3816 ms = base_ms = new MethodSignature (Name, retval, ParameterTypes);
3820 // Verify if the parent has a type with the same name, and then
3821 // check whether we have to create a new slot for it or not.
3823 Type ptype = container.TypeBuilder.BaseType;
3825 MemberInfo parent_member = null;
3826 MemberList mi, mi_static, mi_instance;
3829 // Find properties with the same name on the base class
3831 mi_static = TypeContainer.FindMembers (
3832 ptype, MemberTypes.Property,
3833 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3834 MethodSignature.inheritable_property_signature_filter, base_ms);
3836 mi_instance = TypeContainer.FindMembers (
3837 ptype, MemberTypes.Property,
3838 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3839 MethodSignature.inheritable_property_signature_filter,
3843 if (mi_instance.Count > 0)
3845 else if (mi_static.Count > 0)
3850 if (mi != null && mi.Count > 0)
3851 parent_member = (PropertyInfo) mi [0];
3853 if (parent_member is PropertyInfo) {
3854 PropertyInfo parent_property = (PropertyInfo)parent_member;
3856 string name = parent_property.DeclaringType.Name + "." +
3857 parent_property.Name;
3859 MethodInfo get, set, parent_method;
3860 get = parent_property.GetGetMethod (true);
3861 set = parent_property.GetSetMethod (true);
3864 parent_method = get;
3865 else if (set != null)
3866 parent_method = set;
3868 throw new Exception ("Internal error!");
3870 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
3873 if ((ModFlags & Modifiers.NEW) == 0) {
3874 Type parent_type = TypeManager.TypeToCoreType (
3875 parent_property.PropertyType);
3877 if (parent_type != MemberType) {
3879 508, Location, container.MakeName (Name) + ": cannot " +
3880 "change return type when overriding " +
3881 "inherited member " + name);
3885 } else if (parent_member == null) {
3886 /*if ((ModFlags & Modifiers.NEW) != 0)
3887 WarningNotHiding (container);
3889 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3892 if (this is Indexer)
3893 Report.Error (115, Location,
3894 container.MakeName (Name) +
3895 " no suitable indexers found to override");
3898 Report.Error (115, Location,
3899 container.MakeName (Name) +
3900 " no suitable properties found to override");
3904 if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0) {
3905 if ((ModFlags & Modifiers.NONVIRTUAL) != 0) {
3906 Report.Error (31088, Location,
3907 container.MakeName (Name) + " : Cannot " +
3908 "be declared NotOverridable since this method is " +
3909 "not maked as Overrides");
3912 // if a member of module is not inherited from Object class
3913 // can not be declared protected
3914 if ((container is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
3915 Report.Error (31066, Location,
3916 "'Property' inside a 'Module' can not be declared as " +
3917 "'Protected' or 'Protected Friend'");
3923 const int AllowedModifiers =
3926 Modifiers.PROTECTED |
3927 Modifiers.INTERNAL |
3931 Modifiers.OVERRIDE |
3932 Modifiers.ABSTRACT |
3936 Modifiers.NONVIRTUAL |
3938 Modifiers.READONLY |
3939 Modifiers.WRITEONLY |
3942 string set_parameter_name;
3943 Parameters get_params;
3944 Parameters set_params;
3946 public Property (Expression type, string name, int mod_flags,
3947 Accessor get_block, Accessor set_block,
3948 Attributes attrs, Location loc, string set_name,
3949 Parameters p_get, Parameters p_set, ArrayList impl_what)
3950 : base (type, mod_flags, AllowedModifiers, name, attrs, p_set, loc)
3953 if (get_block != null)
3954 GetMethod = new GetMethod (this, get_block, attrs, p_get, loc);
3956 if (set_block != null)
3957 SetMethod = new SetMethod (this, set_block, set_name, p_set, loc);
3959 Implements = impl_what;
3962 public Property (Expression type, string name, int mod_flags,
3963 Accessor get_block, Accessor set_block,
3964 Attributes attrs, Location loc)
3965 : this (type, name, mod_flags, get_block, set_block, attrs, loc,
3966 "Value", Parameters.EmptyReadOnlyParameters, Parameters.EmptyReadOnlyParameters, null)
3970 public override bool Define (TypeContainer parent)
3972 Type [] s_parameters=null;
3973 Parameter [] s_parms;
3974 InternalParameters s_ip=null;
3976 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
3977 Report.Error (30435, Location,
3978 "'Property' inside a 'Structure' can not be declared as " +
3979 "'Protected' or 'Protected Friend'");
3981 if (!DoDefine (parent))
3984 if (!CheckBase (parent))
3987 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3989 if (GetMethod == null) {
3990 if ((ModFlags & Modifiers.WRITEONLY) == 0)
3993 "Property without 'Get' accessor must have a 'WriteOnly' modifier");
3995 GetBuilder = GetMethod.Define (parent);
3997 if (SetMethod== null) {
3998 if ((ModFlags & Modifiers.READONLY) == 0)
4001 "Property without 'Set' accessor must have a 'ReadOnly' modifier");
4005 SetBuilder = SetMethod.Define (parent);
4007 // FIXME - PropertyAttributes.HasDefault ?
4009 PropertyAttributes prop_attr =
4010 PropertyAttributes.RTSpecialName |
4011 PropertyAttributes.SpecialName;
4013 if (!IsExplicitImpl){
4014 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4015 Name, prop_attr, MemberType, null);
4017 PropertyBuilder.SetGetMethod (GetBuilder);
4018 PropertyBuilder.SetSetMethod (SetBuilder);
4021 // HACK for the reasons exposed above
4023 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4026 "Class `" + parent.Name +
4027 "' already contains a definition for the property `" +
4035 public void Emit (TypeContainer tc)
4038 // The PropertyBuilder can be null for explicit implementations, in that
4039 // case, we do not actually emit the ".property", so there is nowhere to
4040 // put the attribute
4043 if (PropertyBuilder != null && OptAttributes != null)
4044 OptAttributes.Emit (ec, this);
4046 if (GetMethod != null)
4048 GetMethod.Emit (tc);
4051 if (SetMethod != null)
4053 SetMethod.Emit (tc);
4057 public MethodAttributes MethodAttributeFlags {
4066 /// Gigantic workaround for lameness in SRE follows :
4067 /// This class derives from EventInfo and attempts to basically
4068 /// wrap around the EventBuilder so that FindMembers can quickly
4069 /// return this in it search for members
4071 public class MyEventBuilder : EventInfo {
4074 // We use this to "point" to our Builder which is
4075 // not really a MemberInfo
4077 EventBuilder MyBuilder;
4080 // We "catch" and wrap these methods
4082 MethodInfo raise, remove, add;
4084 EventAttributes attributes;
4085 Type declaring_type, reflected_type, event_type;
4088 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4090 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4092 // And now store the values in our own fields.
4094 declaring_type = type_builder;
4096 reflected_type = type_builder;
4098 attributes = event_attr;
4100 this.event_type = event_type;
4104 // Methods that you have to override. Note that you only need
4105 // to "implement" the variants that take the argument (those are
4106 // the "abstract" methods, the others (GetAddMethod()) are
4109 public override MethodInfo GetAddMethod (bool nonPublic)
4114 public override MethodInfo GetRemoveMethod (bool nonPublic)
4119 public override MethodInfo GetRaiseMethod (bool nonPublic)
4125 // These methods make "MyEventInfo" look like a Builder
4127 public void SetRaiseMethod (MethodBuilder raiseMethod)
4129 raise = raiseMethod;
4130 MyBuilder.SetRaiseMethod (raiseMethod);
4133 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4135 remove = removeMethod;
4136 MyBuilder.SetRemoveOnMethod (removeMethod);
4139 public void SetAddOnMethod (MethodBuilder addMethod)
4142 MyBuilder.SetAddOnMethod (addMethod);
4145 public void SetCustomAttribute (CustomAttributeBuilder cb)
4147 MyBuilder.SetCustomAttribute (cb);
4150 public override object [] GetCustomAttributes (bool inherit)
4152 // FIXME : There's nothing which can be seemingly done here because
4153 // we have no way of getting at the custom attribute objects of the
4158 public override object [] GetCustomAttributes (Type t, bool inherit)
4160 // FIXME : Same here !
4164 public override bool IsDefined (Type t, bool b)
4169 public override EventAttributes Attributes {
4175 public override string Name {
4181 public override Type DeclaringType {
4183 return declaring_type;
4187 public override Type ReflectedType {
4189 return reflected_type;
4193 public Type EventType {
4201 public class AddDelegateMethod {
4202 MethodBuilder AddBuilder;
4207 public AddDelegateMethod (Event parent_event, Location loc)
4209 this.parent_event = parent_event;
4213 public MethodBuilder Define (TypeContainer parent)
4215 Type [] parameter_types = new Type [1];
4216 parameter_types [0] = parent_event.MemberType;
4218 Parameter [] parms = new Parameter [1];
4219 parms [0] = new Parameter (parent_event.Type, /* was "value" */ parent_event.Name, Parameter.Modifier.NONE, null);
4220 InternalParameters ip = new InternalParameters (
4221 parent, new Parameters (parms, null, Location));
4223 AddData = new MethodData (parent_event, "add", TypeManager.void_type,
4224 parameter_types, ip, CallingConventions.Standard, null,
4225 parent_event.ModFlags, parent_event.MethodAttributeFlags, false);
4227 if (!AddData.Define (parent))
4230 AddBuilder = AddData.MethodBuilder;
4231 AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ parent_event.Name);
4238 public void Emit (TypeContainer tc)
4240 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4241 EmitContext ec = new EmitContext (tc, Location, ig, TypeManager.void_type, parent_event.ModFlags);
4242 parent_event.EmitDefaultMethod (ec, true);
4246 public class RemoveDelegateMethod {
4247 MethodBuilder RemoveBuilder;
4248 MethodData RemoveData;
4252 public RemoveDelegateMethod (Event parent_event, Location loc)
4254 this.parent_event = parent_event;
4258 public MethodBuilder Define (TypeContainer parent)
4260 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4262 Type [] parameter_types = new Type [1];
4263 parameter_types [0] = parent_event.MemberType;
4265 Parameter [] parms = new Parameter [1];
4266 parms [0] = new Parameter (parent_event.Type, /* was "value" */ parent_event.Name, Parameter.Modifier.NONE, null);
4267 InternalParameters ip = new InternalParameters (
4268 parent, new Parameters (parms, null, Location));
4271 RemoveData = new MethodData (parent_event, "remove", TypeManager.void_type,
4272 parameter_types, ip, CallingConventions.Standard, null,
4273 parent_event.ModFlags, parent_event.MethodAttributeFlags, false);
4275 if (!RemoveData.Define (parent))
4278 RemoveBuilder = RemoveData.MethodBuilder;
4279 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ parent_event.Name);
4281 return RemoveBuilder;
4284 public void Emit (TypeContainer tc)
4286 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4287 EmitContext ec = new EmitContext (tc, Location, ig, TypeManager.void_type, parent_event.ModFlags);
4288 parent_event.EmitDefaultMethod (ec, false);
4292 public class Event : FieldBase {
4293 const int AllowedModifiers =
4296 Modifiers.PROTECTED |
4297 Modifiers.INTERNAL |
4302 Modifiers.OVERRIDE |
4306 public readonly AddDelegateMethod Add;
4307 public readonly RemoveDelegateMethod Remove;
4308 public MyEventBuilder EventBuilder;
4310 MethodBuilder AddBuilder, RemoveBuilder;
4312 public Event (Expression type, string name, Object init, int mod, Attributes attrs, Location loc)
4313 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4315 Add = new AddDelegateMethod (this, loc);
4316 Remove = new RemoveDelegateMethod (this, loc);
4321 public Event (Expression type, string name, Object init, int mod, Attributes attrs, ArrayList impl_what, Location loc)
4322 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4324 Add = new AddDelegateMethod (this, loc);
4325 Remove = new RemoveDelegateMethod (this, loc);
4327 Implements = impl_what;
4330 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4332 EventBuilder.SetCustomAttribute (cb);
4335 public override AttributeTargets AttributeTargets {
4337 return AttributeTargets.Event;
4341 public override bool Define (TypeContainer parent)
4343 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4345 if (!DoDefine (parent))
4348 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4349 Report.Error (31044, Location, "'" + parent.Name + "." + Name +
4350 "' : event must be of a delegate type");
4354 Type [] parameter_types = new Type [1];
4355 parameter_types [0] = MemberType;
4357 Parameter [] parms = new Parameter [1];
4358 parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4359 InternalParameters ip = new InternalParameters (
4360 parent, new Parameters (parms, null, Location));
4362 if (!CheckBase (parent))
4365 AddBuilder = Add.Define (parent);
4366 RemoveBuilder = Remove.Define (parent);
4369 if (!IsExplicitImpl){
4370 EventBuilder = new MyEventBuilder (
4371 parent.TypeBuilder, Name, e_attr, MemberType);
4373 FieldBuilder = parent.TypeBuilder.DefineField (Name, MemberType,
4374 FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4375 TypeManager.RegisterPrivateFieldOfEvent ((EventInfo) EventBuilder, FieldBuilder);
4376 TypeManager.RegisterFieldBase (FieldBuilder, this);
4378 EventBuilder.SetAddOnMethod (AddBuilder);
4379 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4381 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4382 Report.Error (111, Location,
4383 "Class `" + parent.Name +
4384 "' already contains a definition for the event `" +
4393 public void EmitDefaultMethod (EmitContext ec, bool is_add)
4395 ILGenerator ig = ec.ig;
4396 MethodInfo method = null;
4399 method = TypeManager.delegate_combine_delegate_delegate;
4401 method = TypeManager.delegate_remove_delegate_delegate;
4403 if ((ModFlags & Modifiers.STATIC) != 0) {
4404 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4405 ig.Emit (OpCodes.Ldarg_0);
4406 ig.Emit (OpCodes.Call, method);
4407 ig.Emit (OpCodes.Castclass, MemberType);
4408 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4410 ig.Emit (OpCodes.Ldarg_0);
4411 ig.Emit (OpCodes.Ldarg_0);
4412 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4413 ig.Emit (OpCodes.Ldarg_1);
4414 ig.Emit (OpCodes.Call, method);
4415 ig.Emit (OpCodes.Castclass, MemberType);
4416 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4418 ig.Emit (OpCodes.Ret);
4421 public void Emit (TypeContainer tc)
4425 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4427 if (OptAttributes != null)
4428 OptAttributes.Emit (ec, this);
4434 public MethodAttributes MethodAttributeFlags {
4442 struct MethodSignature {
4444 public Type RetType;
4445 public Type [] Parameters;
4448 /// This delegate is used to extract methods which have the
4449 /// same signature as the argument
4451 public static MemberFilter method_signature_filter;
4454 /// This delegate is used to extract methods which have the
4455 /// same signature as the argument except for the name
4457 public static MemberFilter method_signature_noname_filter;
4460 /// This delegate is used to extract inheritable methods which
4461 /// have the same signature as the argument. By inheritable,
4462 /// this means that we have permissions to override the method
4463 /// from the current assembly and class
4465 public static MemberFilter inheritable_method_signature_filter;
4468 /// This delegate is used to extract inheritable methods which
4469 /// have the same signature as the argument. By inheritable,
4470 /// this means that we have permissions to override the method
4471 /// from the current assembly and class
4473 public static MemberFilter inheritable_property_signature_filter;
4475 static MethodSignature ()
4477 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4478 method_signature_noname_filter = new MemberFilter (MemberSignatureCompareNoName);
4479 inheritable_method_signature_filter = new MemberFilter (
4480 InheritableMemberSignatureCompare);
4481 inheritable_property_signature_filter = new MemberFilter (
4482 InheritablePropertySignatureCompare);
4485 public MethodSignature (string name, Type ret_type, Type [] parameters)
4490 if (parameters == null)
4491 Parameters = TypeManager.NoTypes;
4493 Parameters = parameters;
4496 public override int GetHashCode ()
4498 return Name.GetHashCode ();
4501 public override bool Equals (Object o)
4503 MethodSignature other = (MethodSignature) o;
4505 if (other.Name != Name)
4508 if (other.RetType != RetType)
4511 if (Parameters == null){
4512 if (other.Parameters == null)
4517 if (other.Parameters == null)
4520 int c = Parameters.Length;
4521 if (other.Parameters.Length != c)
4524 for (int i = 0; i < c; i++)
4525 if (other.Parameters [i] != Parameters [i])
4531 static bool MemberSignatureCompareNoName (MemberInfo m, object filter_criteria)
4533 return MemberSignatureCompare (m, filter_criteria, false);
4536 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4538 return MemberSignatureCompare (m, filter_criteria, true);
4541 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria, bool use_name)
4543 MethodSignature sig = (MethodSignature) filter_criteria;
4545 if (use_name && (m.Name != sig.Name))
4549 MethodInfo mi = m as MethodInfo;
4550 PropertyInfo pi = m as PropertyInfo;
4553 ReturnType = mi.ReturnType;
4554 else if (pi != null)
4555 ReturnType = pi.PropertyType;
4560 // we use sig.RetType == null to mean `do not check the
4561 // method return value.
4563 if (sig.RetType != null)
4564 if (ReturnType != sig.RetType)
4569 args = TypeManager.GetArgumentTypes (mi);
4571 args = TypeManager.GetArgumentTypes (pi);
4573 Type [] sigp = sig.Parameters;
4575 if (args.Length != sigp.Length)
4578 for (int i = args.Length; i > 0; ){
4580 if (args [i] != sigp [i])
4587 // This filter should be used when we are requesting methods that
4588 // we want to override.
4590 // This makes a number of assumptions, for example
4591 // that the methods being extracted are of a parent
4592 // class (this means we know implicitly that we are
4593 // being called to find out about members by a derived
4596 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4598 if (MemberSignatureCompare (m, filter_criteria)){
4599 MethodInfo mi = (MethodInfo) m;
4600 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4602 // If only accessible to the current class.
4603 if (prot == MethodAttributes.Private)
4606 // If only accessible to the defining assembly or
4607 if (prot == MethodAttributes.FamANDAssem ||
4608 prot == MethodAttributes.Assembly){
4609 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4615 // Anything else (FamOrAssembly and Public) is fine
4622 // This filter should be used when we are requesting properties that
4623 // we want to override.
4625 // This makes a number of assumptions, for example
4626 // that the methods being extracted are of a parent
4627 // class (this means we know implicitly that we are
4628 // being called to find out about members by a derived
4631 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4633 if (MemberSignatureCompare (m, filter_criteria)){
4634 PropertyInfo pi = (PropertyInfo) m;
4636 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4637 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4639 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4641 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4643 // If only accessible to the current class.
4644 if (prot == MethodAttributes.Private)
4647 // If only accessible to the defining assembly or
4648 if (prot == MethodAttributes.FamANDAssem ||
4649 prot == MethodAttributes.Assembly){
4650 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4656 // Anything else (FamOrAssembly and Public) is fine