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 statements 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)
146 types = new ArrayList ();
148 base_class_name = null;
157 Console.WriteLine ("New class " + name + " inside " + n);*/
160 public AdditionResult AddConstant (Const constant)
163 string basename = constant.Name;
165 if ((res = IsValid (basename)) != AdditionResult.Success)
168 if (constants == null)
169 constants = new ArrayList ();
171 constants.Add (constant);
172 DefineName (Name + "." + basename, constant);
174 return AdditionResult.Success;
177 public AdditionResult AddEnum (Mono.MonoBASIC.Enum e)
181 if ((res = IsValid (e.Basename)) != AdditionResult.Success)
185 enums = new ArrayList ();
188 DefineName (e.Name, e);
190 return AdditionResult.Success;
193 public AdditionResult AddClass (Class c)
197 if ((res = IsValid (c.Basename)) != AdditionResult.Success)
202 DefineName (c.Name, c);
205 // FIXME: Do we really need to explicitly add an empty default static constructor?
206 // Apparently we don't
207 /* if (c.default_static_constructor == null)
209 bool isModule = c is Mono.MonoBASIC.Module;
210 Constructor dc = new Constructor ("New", Parameters.EmptyReadOnlyParameters, null, c.Location);
211 dc.ModFlags = isModule ? Modifiers.PUBLIC | Modifiers.STATIC : Modifiers.PUBLIC;
212 c.AddConstructor (dc);
215 //--------------------------------------------------------------
217 return AdditionResult.Success;
220 public AdditionResult AddStruct (Struct s)
224 if ((res = IsValid (s.Basename)) != AdditionResult.Success)
227 DefineName (s.Name, s);
230 return AdditionResult.Success;
233 public AdditionResult AddDelegate (Delegate d)
237 if ((res = IsValid (d.Basename)) != AdditionResult.Success)
240 if (delegates == null)
241 delegates = new ArrayList ();
243 DefineName (d.Name, d);
246 return AdditionResult.Success;
249 public AdditionResult AddMethod (Method method)
251 string basename = method.Name;
252 string fullname = Name + "." + basename;
254 Object value = defined_names [fullname];
256 if (value != null && (!(value is Method)))
257 return AdditionResult.NameExists;
260 methods = new ArrayList ();
262 if (method.Name.IndexOf (".") != -1)
263 methods.Insert (0, method);
265 methods.Add (method);
268 DefineName (fullname, method);
270 return AdditionResult.Success;
273 public AdditionResult AddConstructor (Constructor c)
276 return AdditionResult.NotAConstructor;
278 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
281 have_static_constructor = true;
282 if (default_static_constructor != null){
283 Console.WriteLine ("I have a static constructor already");
284 Console.WriteLine (" " + default_static_constructor);
285 return AdditionResult.MethodExists;
288 default_static_constructor = c;
291 /*if (default_constructor != null)
292 return AdditionResult.MethodExists;*/
293 default_constructor = c;
296 if (instance_constructors == null)
297 instance_constructors = new ArrayList ();
299 instance_constructors.Add (c);
302 return AdditionResult.Success;
305 public AdditionResult AddInterface (Interface iface)
309 if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
312 if (interfaces == null)
313 interfaces = new ArrayList ();
314 interfaces.Add (iface);
315 DefineName (iface.Name, iface);
317 return AdditionResult.Success;
320 public AdditionResult AddField (Field field)
323 string basename = field.Name;
325 if ((res = IsValid (basename)) != AdditionResult.Success)
329 fields = new ArrayList ();
333 if (field.HasInitializer){
334 if ((field.ModFlags & Modifiers.STATIC) != 0) {
335 if (initialized_static_fields == null)
336 initialized_static_fields = new ArrayList ();
338 initialized_static_fields.Add (field);
341 // We have not seen a static constructor,
342 // but we will provide static initialization of fields
344 have_static_constructor = true;
346 if (initialized_fields == null)
347 initialized_fields = new ArrayList ();
349 initialized_fields.Add (field);
353 if ((field.ModFlags & Modifiers.STATIC) == 0)
354 have_nonstatic_fields = true;
356 DefineName (Name + "." + basename, field);
357 return AdditionResult.Success;
360 public AdditionResult AddProperty (Property prop)
363 string basename = prop.Name;
365 string fullname = Name + "." + basename;
367 Object value = defined_names [fullname];
369 if (value != null && (!(value is Property)))
370 return AdditionResult.NameExists;
372 if ((res = IsValid (basename)) != AdditionResult.Success)
375 if (properties == null)
376 properties = new ArrayList ();
378 if (prop.Name.IndexOf (".") != -1)
379 properties.Insert (0, prop);
381 properties.Add (prop);
384 DefineName (Name + "." + basename, prop);
386 return AdditionResult.Success;
389 public AdditionResult AddEvent (Event e)
392 string basename = e.Name;
394 if ((res = IsValid (basename)) != AdditionResult.Success)
398 events = new ArrayList ();
401 DefineName (Name + "." + basename, e);
403 return AdditionResult.Success;
406 public AdditionResult AddEventHandler (Statement stmt)
408 if (handlers == null)
409 handlers = new ArrayList ();
412 return AdditionResult.Success;
415 public void RegisterOrder (Interface iface)
417 if (interface_order == null)
418 interface_order = new ArrayList ();
420 interface_order.Add (iface);
422 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
424 base.ApplyAttributeBuilder (a, cb);
427 public override AttributeTargets AttributeTargets {
429 throw new NotSupportedException ();
433 public ArrayList Types {
439 public ArrayList Methods {
445 public ArrayList Constants {
451 public ArrayList Interfaces {
459 return base_class_name;
463 public ArrayList Bases {
473 public ArrayList Fields {
483 public ArrayList InstanceConstructors {
485 return instance_constructors;
489 public ArrayList Properties {
495 public ArrayList Events {
501 public ArrayList Enums {
507 public ArrayList Delegates {
513 public bool HaveStaticConstructor {
515 return have_static_constructor;
519 public virtual TypeAttributes TypeAttr {
521 return Modifiers.TypeAttr (ModFlags, this);
525 public ArrayList EventHandlers {
532 // Emits the instance field initializers
534 public bool EmitFieldInitializers (EmitContext ec)
537 //ILGenerator ig = ec.ig;
538 Expression instance_expr;
541 fields = initialized_static_fields;
542 instance_expr = null;
544 fields = initialized_fields;
545 instance_expr = new This (Location.Null).Resolve (ec);
551 foreach (Field f in fields){
552 Expression e = f.GetInitializerExpression (ec);
556 Location l = f.Location;
557 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
558 fe.InstanceExpression = instance_expr;
559 Expression a = new Assign (fe, e, l);
565 if (a is ExpressionStatement)
566 ((ExpressionStatement) a).EmitStatement (ec);
568 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
576 // Defines the default constructors
578 void DefineDefaultConstructor (bool is_static)
583 c = new Constructor ("New", Parameters.EmptyReadOnlyParameters,
588 mods = Modifiers.STATIC;
592 c.Initializer = new ConstructorBaseInitializer (
593 null, Parameters.EmptyReadOnlyParameters,
598 c.Block = new Block (null);
602 public void ReportStructInitializedInstanceError ()
604 string n = TypeBuilder.FullName;
606 foreach (Field f in initialized_fields){
609 "`" + n + "." + f.Name + "': can not have " +
610 "instance field initializers in structs");
615 /// The pending methods that need to be implemented (interfaces or abstract methods)
617 public PendingImplementation Pending;
620 /// This function computes the Base class and also the
621 /// list of interfaces that the class or struct @c implements.
623 /// The return value is an array (might be null) of
624 /// interfaces implemented (as Types).
626 /// The @parent argument is set to the parent object or null
627 /// if this is `System.Object'.
629 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
631 ArrayList bases = Bases;
640 parent = TypeManager.value_type;
644 if (RootContext.StdLib)
645 parent = TypeManager.object_type;
646 else if (Name != "System.Object")
647 parent = TypeManager.object_type;
650 // If we are compiling our runtime,
651 // and we are defining ValueType, then our
652 // parent is `System.Object'.
654 if (!RootContext.StdLib && Name == "System.ValueType")
655 parent = TypeManager.object_type;
662 // Bases should be null if there are no bases at all
666 if (is_class && (!(this is Interface))){
667 Expression name = (Expression) bases [0];
668 name = ResolveTypeExpr (name, false, Location);
675 Type first = name.Type;
681 parent = TypeManager.object_type;
685 if (parent.IsSealed )
686 Report.Error (30299, Location,
687 "Class " + Name + " cannot inherit " +
688 "'NotInheritable' class " + TypeManager.MonoBASIC_Name (parent));
690 if (!AsAccessible (parent, ModFlags))
691 Report.Error (30389, Location,
692 "Inconsistent accessibility: base class `" +
693 TypeManager.MonoBASIC_Name (parent) + "' is less " +
694 "accessible than class `" +
701 Type [] ifaces = new Type [count-start];
703 for (i = start, j = 0; i < count; i++, j++){
704 Expression name = (Expression) bases [i];
705 Expression resolved = ResolveTypeExpr (name, false, Location);
706 bases [i] = resolved;
707 Type t = resolved.Type;
713 if (is_class == false && !t.IsInterface){
714 Report.Error (527, Location, "In Struct `" + Name + "', type `"+
715 name +"' is not an interface");
722 Report.Error (30258, Location, "class `"+ Name +
723 "': a class can not inherit from a struct/enum");
725 /*Report.Error (509, Location, "class `"+ Name +
726 "': Cannot inherit from sealed class `"+
734 Report.Error (30121, Location, Name + ": A class cannot inherit " +
735 "more than one class");
741 for (int x = 0; x < j; x++) {
742 if (t == ifaces [x]) {
743 Report.Error (528,Location, "`" + name + "' is already listed in interface list");
756 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
758 public override TypeBuilder DefineType ()
763 if (TypeBuilder != null)
776 ec = new EmitContext (this, Mono.MonoBASIC.Location.Null, null, null, ModFlags);
778 if (((ModFlags & Modifiers.ABSTRACT ) != 0) &&
779 ((ModFlags & Modifiers.SEALED) != 0)){
780 Report.Error (31408, Location,
781 "Class declared as 'MustInherit' cannot be declared as 'NotInheritable'");
784 ifaces = GetClassBases (is_class, out base_class_type, out error);
788 if (this is Interface)
789 base_class_type = null;
791 if (is_class && base_class_type != null){
792 if (base_class_type == TypeManager.enum_type ||
793 (base_class_type == TypeManager.value_type && RootContext.StdLib) ||
794 base_class_type == TypeManager.delegate_type ||
795 base_class_type == TypeManager.array_type){
797 644, Location, "`" + Name + "' cannot inherit from " +
798 "special class `" + TypeManager.MonoBASIC_Name (base_class_type) + "'");
803 if (!is_class && TypeManager.value_type == null)
804 throw new Exception ();
806 if (is_class && Parent.Parent == null && (!(this is Interface)))
808 if ((ModFlags & Modifiers.PRIVATE) != 0)
809 Report.Error (31089, Location,
810 "Only internal classes can be declared as 'Private'");
812 if ((ModFlags & Modifiers.PROTECTED) != 0)
813 Report.Error (31047, Location,
814 "Only internal classes can be declared as 'Protected'");
817 if ((Parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
818 Report.Error (30735, Location,
819 "'Type' inside a 'Module' can not be " +
820 "declared as 'Protected'");
822 if ((Parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
823 Report.Error (30435, Location,
824 "'Type' inside a 'Structure' can not be " +
825 "declared as 'Protected'");
827 TypeAttributes type_attributes = TypeAttr;
830 ModuleBuilder builder = CodeGen.ModuleBuilder;
831 TypeBuilder = builder.DefineType (
832 Name, type_attributes, base_class_type, ifaces);
835 TypeBuilder builder = Parent.TypeBuilder;
836 TypeBuilder = builder.DefineNestedType (
837 Basename, type_attributes, base_class_type, ifaces);
842 // structure must contain atleast one member variable
843 if(!have_nonstatic_fields){
845 30281, Location, "Structure `" + Name + "' do not " +
846 "contain any member Variable");
848 /*TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
849 FieldAttributes.Private);*/
852 // add interfaces that were not added at type creation (weird API issue)
853 if (!have_nonstatic_fields && (ifaces != null)) {
854 foreach (Type i in ifaces)
855 TypeBuilder.AddInterfaceImplementation (i);
861 // Finish the setup for the EmitContext
863 ec.ContainerType = TypeBuilder;
865 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
867 if ((base_class_type != null) &&
868 (base_class_type == TypeManager.attribute_type ||
869 base_class_type.IsSubclassOf (TypeManager.attribute_type))) {
870 RootContext.RegisterAttribute (this);
874 if ( this is Interface)
875 RootContext.RegisterOrder ((Interface) this);
877 RootContext.RegisterOrder (this);
880 if (Interfaces != null) {
881 foreach (Interface iface in Interfaces)
886 foreach (TypeContainer tc in Types)
890 if (Delegates != null) {
891 foreach (Delegate d in Delegates)
896 foreach (Enum en in Enums)
906 /// Defines the MemberCore objects that are in the `list' Arraylist
908 /// The `defined_names' array contains a list of members defined in
911 static ArrayList remove_list = new ArrayList ();
912 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
916 // if one of the overloaded method is having
917 // Shadows or Overloads modifier all other should
918 // have the same modifier
919 Hashtable members = new Hashtable();
921 foreach (MemberCore mc in list)
924 if(members[mc.Name] == null)
926 foreach (MemberCore m in list)
928 if(m.Name == mc.Name)
930 if ((m.ModFlags & Modifiers.SHADOWS) != 0)
932 modval = Modifiers.SHADOWS;
935 else if((m.ModFlags & Modifiers.NEW) != 0)
937 modval = Modifiers.NEW;
941 members.Add(mc.Name, modval);
944 modval = (int)members[mc.Name];
947 if(((modval & Modifiers.SHADOWS) != 0) && ((mc.ModFlags & Modifiers.SHADOWS) == 0))
950 "Function '" + mc.Name + "': must be declared 'Shadows' " +
951 "because another '" + mc.Name + "' declared 'Shadows'");
952 else if(((modval & Modifiers.NEW) != 0) && ((mc.ModFlags & Modifiers.NEW) == 0))
955 "Function '" + mc.Name + "': must be declared 'Overloads' " +
956 "because another '" + mc.Name + "' declared 'Overloads'");
960 remove_list.Clear ();
962 foreach (MemberCore mc in list){
963 if (!mc.Define (this)){
964 remove_list.Add (mc);
968 if (defined_names == null)
971 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
973 if (RootContext.WarningLevel >= 4){
974 if ((mc.ModFlags & Modifiers.NEW) != 0)
975 Warning_KewywordNewNotRequired (mc.Location, mc);
976 if ((mc.ModFlags & Modifiers.SHADOWS) != 0)
977 Warning_KewywordShadowsNotRequired (mc.Location, mc);
982 MemberInfo match = defined_names [idx];
984 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
988 // If we are both methods, let the method resolution emit warnings
990 if (match is MethodBase && mc is MethodCore)
993 if (((mc.ModFlags & Modifiers.SHADOWS) == 0) && idx > 0)
994 Warning_KeywordShadowsRequired (mc.Location, defined_names [idx]);
998 foreach (object o in remove_list)
1001 remove_list.Clear ();
1004 static void Error_KeywordNotAllowed (Location loc)
1006 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1010 /// Populates our TypeBuilder with fields and methods
1012 public override bool DefineMembers (TypeContainer parent)
1014 MemberInfo [] defined_names = null;
1016 if (interface_order != null){
1017 foreach (Interface iface in interface_order)
1018 if ((iface.ModFlags & Modifiers.NEW) == 0)
1019 iface.DefineMembers (this);
1021 Error_KeywordNotAllowed (iface.Location);
1024 if (RootContext.WarningLevel > 1){
1028 // This code throws an exception in the comparer
1029 // I guess the string is not an object?
1031 ptype = TypeBuilder.BaseType;
1033 defined_names = (MemberInfo []) FindMembers (
1034 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1035 BindingFlags.Public | BindingFlags.Instance |
1036 BindingFlags.Static, null, null);
1038 Array.Sort (defined_names, mif_compare);
1042 if (constants != null)
1043 DefineMembers (constants, defined_names);
1046 DefineMembers (fields, defined_names);
1048 if (this is Class && (!(this is Interface))){
1049 if (instance_constructors == null){
1050 if (default_constructor == null)
1051 DefineDefaultConstructor (false);
1054 if (initialized_static_fields != null &&
1055 default_static_constructor == null)
1056 DefineDefaultConstructor (true);
1059 if (this is Struct){
1061 // Structs can not have initialized instance
1064 if (initialized_static_fields != null &&
1065 default_static_constructor == null)
1066 DefineDefaultConstructor (true);
1068 if (initialized_fields != null)
1069 ReportStructInitializedInstanceError ();
1072 if (!(this is Interface))
1073 Pending = PendingImplementation.GetPendingImplementations (this);
1075 // Constructors are not in the defined_names array
1077 if (instance_constructors != null)
1078 DefineMembers (instance_constructors, null);
1080 if (default_static_constructor != null)
1081 default_static_constructor.Define (this);
1083 if (methods != null)
1084 DefineMembers (methods, defined_names);
1086 if (properties != null)
1087 DefineMembers (properties, defined_names);
1090 DefineMembers (events, defined_names);
1093 DefineMembers (enums, defined_names);
1095 if (delegates != null)
1096 DefineMembers (delegates, defined_names);
1099 if (TypeBuilder.BaseType != null)
1100 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1102 member_cache = new MemberCache (this);
1108 public override bool Define (TypeContainer parent)
1110 if (interface_order != null){
1111 foreach (Interface iface in interface_order)
1112 if ((iface.ModFlags & Modifiers.NEW) == 0)
1113 iface.Define (this);
1120 /// This function is based by a delegate to the FindMembers routine
1122 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1128 /// This filter is used by FindMembers, and we just keep
1129 /// a global for the filter to `AlwaysAccept'
1131 static MemberFilter accepting_filter;
1135 /// A member comparission method based on name only
1137 static IComparer mif_compare;
1139 static TypeContainer ()
1141 accepting_filter = new MemberFilter (AlwaysAccept);
1142 mif_compare = new MemberInfoCompare ();
1146 /// This method returns the members of this type just like Type.FindMembers would
1147 /// Only, we need to use this for types which are _being_ defined because MS'
1148 /// implementation can't take care of that.
1151 // FIXME: return an empty static array instead of null, that cleans up
1152 // some code and is consistent with some coding conventions I just found
1156 // Notice that in various cases we check if our field is non-null,
1157 // something that would normally mean that there was a bug elsewhere.
1159 // The problem happens while we are defining p-invoke methods, as those
1160 // will trigger a FindMembers, but this happens before things are defined
1162 // Since the whole process is a no-op, it is fine to check for null here.
1164 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1165 MemberFilter filter, object criteria)
1167 ArrayList members = new ArrayList ();
1170 if ((bf & BindingFlags.Public) != 0)
1171 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1173 if ((bf & BindingFlags.NonPublic) != 0)
1174 modflags |= Modifiers.PRIVATE;
1176 int static_mask = 0, static_flags = 0;
1177 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1178 case BindingFlags.Static:
1179 static_mask = static_flags = Modifiers.STATIC;
1182 case BindingFlags.Instance:
1183 static_mask = Modifiers.STATIC;
1188 static_mask = static_flags = 0;
1192 Timer.StartTimer (TimerType.TcFindMembers);
1195 filter = accepting_filter;
1197 if ((mt & MemberTypes.Field) != 0) {
1198 if (fields != null) {
1199 foreach (Field f in fields) {
1200 if ((f.ModFlags & modflags) == 0)
1202 if ((f.ModFlags & static_mask) != static_flags)
1205 FieldBuilder fb = f.FieldBuilder;
1206 if (fb != null && filter (fb, criteria) == true)
1211 if (constants != null) {
1212 foreach (Const con in constants) {
1213 if ((con.ModFlags & modflags) == 0)
1215 if ((con.ModFlags & static_mask) != static_flags)
1218 FieldBuilder fb = con.FieldBuilder;
1219 if (fb != null && filter (fb, criteria) == true)
1225 if ((mt & MemberTypes.Method) != 0) {
1226 if (methods != null) {
1227 foreach (Method m in methods) {
1228 if ((m.ModFlags & modflags) == 0)
1230 if ((m.ModFlags & static_mask) != static_flags)
1233 MethodBuilder mb = m.MethodBuilder;
1235 if (mb != null && filter (mb, criteria) == true)
1240 if (properties != null){
1241 foreach (Property p in properties){
1242 if ((p.ModFlags & modflags) == 0)
1244 if ((p.ModFlags & static_mask) != static_flags)
1250 if (b != null && filter (b, criteria) == true)
1254 if (b != null && filter (b, criteria) == true)
1260 if ((mt & MemberTypes.Event) != 0) {
1262 foreach (Event e in events) {
1263 if ((e.ModFlags & modflags) == 0)
1265 if ((e.ModFlags & static_mask) != static_flags)
1268 MemberInfo eb = e.EventBuilder;
1269 if (eb != null && filter (eb, criteria) == true)
1270 members.Add (e.EventBuilder);
1274 if ((mt & MemberTypes.Property) != 0){
1275 if (properties != null)
1276 foreach (Property p in properties) {
1277 if ((p.ModFlags & modflags) == 0)
1279 if ((p.ModFlags & static_mask) != static_flags)
1282 MemberInfo pb = p.PropertyBuilder;
1284 if (pb != null && filter (pb, criteria) == true)
1285 members.Add (p.PropertyBuilder);
1289 if ((mt & MemberTypes.NestedType) != 0) {
1291 foreach (TypeContainer t in types) {
1292 if ((t.ModFlags & modflags) == 0)
1295 TypeBuilder tb = t.TypeBuilder;
1296 if (tb != null && (filter (tb, criteria) == true))
1302 foreach (Enum en in enums){
1303 if ((en.ModFlags & modflags) == 0)
1306 TypeBuilder tb = en.TypeBuilder;
1307 if (tb != null && (filter (tb, criteria) == true))
1312 if (delegates != null){
1313 foreach (Delegate d in delegates){
1314 if ((d.ModFlags & modflags) == 0)
1317 TypeBuilder tb = d.TypeBuilder;
1318 if (tb != null && (filter (tb, criteria) == true))
1323 if (interfaces != null){
1324 foreach (Interface iface in interfaces){
1325 if ((iface.ModFlags & modflags) == 0)
1328 TypeBuilder tb = iface.TypeBuilder;
1329 if (tb != null && (filter (tb, criteria) == true))
1335 if ((mt & MemberTypes.Constructor) != 0){
1336 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1337 foreach (Constructor c in instance_constructors){
1338 if ((c.ModFlags & modflags) == 0)
1341 ConstructorBuilder cb = c.ConstructorBuilder;
1343 if (filter (cb, criteria) == true)
1348 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null) &&
1349 ((default_static_constructor.ModFlags & modflags) != 0)){
1350 ConstructorBuilder cb =
1351 default_static_constructor.ConstructorBuilder;
1354 if (filter (cb, criteria) == true)
1360 // Lookup members in parent if requested.
1362 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1363 if ((mt & ~MemberTypes.Constructor) != 0) {
1364 MemberList list = FindMembers (TypeBuilder.BaseType, mt & ~MemberTypes.Constructor, bf, filter, criteria);
1365 members.AddRange (list);
1369 Timer.StopTimer (TimerType.TcFindMembers);
1371 return new MemberList (members);
1374 public override MemberCache MemberCache {
1376 return member_cache;
1380 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1381 MemberFilter filter, object criteria)
1383 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1386 return tc.FindMembers (mt, bf, filter, criteria);
1388 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1392 // FindMethods will look for methods not only in the type `t', but in
1393 // any interfaces implemented by the type.
1395 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1396 MemberFilter filter, object criteria)
1402 /// Emits the values for the constants
1404 public void EmitConstants ()
1406 if (constants != null)
1407 foreach (Const con in constants)
1408 con.EmitConstant (this);
1413 /// Emits the code, this step is performed after all
1414 /// the types, enumerations, constructors
1418 if (instance_constructors != null)
1419 foreach (Constructor c in instance_constructors)
1422 if (default_static_constructor != null)
1423 default_static_constructor.Emit (this);
1425 if (methods != null)
1426 foreach (Method m in methods)
1429 if (properties != null)
1430 foreach (Property p in properties)
1433 if (this.DefaultPropName != null) {
1434 CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { DefaultPropName });
1435 TypeBuilder.SetCustomAttribute (cb);
1439 foreach (Field f in fields)
1442 if (events != null){
1443 foreach (Event e in Events)
1447 if (Pending != null)
1448 if (Pending.VerifyPendingMethods ())
1451 if (OptAttributes != null)
1452 OptAttributes.Emit (ec, this);
1455 // Check for internal or private fields that were never assigned
1457 if (fields != null && RootContext.WarningLevel >= 3) {
1458 foreach (Field f in fields) {
1459 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1462 if (f.Name.StartsWith(@"$STATIC$"))
1467 169, f.Location, "Private field " +
1468 MakeName (f.Name) + " is never used");
1473 // Only report 649 on level 4
1475 if (RootContext.WarningLevel < 4)
1478 if ((f.status & Field.Status.ASSIGNED) != 0)
1483 "Field " + MakeName (f.Name) + " is never assigned " +
1484 " to and will always have its default value");
1488 // if (types != null)
1489 // foreach (TypeContainer tc in types)
1493 public override void CloseType ()
1498 TypeBuilder.CreateType ();
1500 } catch (TypeLoadException){
1502 // This is fine, the code still created the type
1504 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1505 // Console.WriteLine (e.Message);
1507 Console.WriteLine ("In type: " + Name);
1512 foreach (Enum en in Enums)
1515 if (interface_order != null){
1516 foreach (Interface iface in interface_order)
1521 foreach (TypeContainer tc in Types)
1525 foreach (TypeContainer tc in Types)
1526 if (!(tc is Struct))
1530 if (Delegates != null)
1531 foreach (Delegate d in Delegates)
1535 public string MakeName (string n)
1537 return "`" + Name + "." + n + "'";
1540 public void Warning_KeywordShadowsRequired (Location l, MemberInfo mi)
1543 108, l, "The keyword 'Shadows' is required on " +
1544 MakeName (mi.Name) + " because it shadows `" +
1545 mi.ReflectedType.Name + "." + mi.Name + "'");
1548 public void Warning_KewywordShadowsNotRequired (Location l, MemberCore mc)
1551 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1552 "inherited member, the keyword shadows is not required");
1555 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1558 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1559 "inherited member, the keyword new is not required");
1562 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1568 // Performs the validation on a Method's modifiers (properties have
1569 // the same properties).
1571 public bool MethodModifiersValid (int flags, string n, Location loc)
1573 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1574 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1575 //const int nv = (Modifiers.SHADOWS | Modifiers.VIRTUAL);
1577 string name = MakeName (n);
1580 // At most one of static, virtual or override
1582 if ((flags & Modifiers.STATIC) != 0){
1583 if ((flags & vao) != 0){
1585 30501, loc, "Shared method " + name + " can not be " +
1586 "declared as Overridable");
1591 if (this is Struct){
1592 if ((flags & va) != 0){
1593 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1598 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.VIRTUAL) != 0)
1602 ": Methods marked as Overrides cannot be made Overridable");
1606 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.SHADOWS) != 0){
1609 ": Methods marked as Overrides cannot be marked as Shadows");
1614 // If the declaration includes the abstract modifier, then the
1615 // declaration does not include static, virtual or extern
1617 if ((flags & Modifiers.ABSTRACT) != 0){
1618 if ((flags & Modifiers.EXTERN) != 0){
1620 180, loc, name + " can not be both abstract and extern");
1624 if ((flags & Modifiers.VIRTUAL) != 0){
1626 503, loc, name + " can not be both abstract and virtual");
1630 if((ModFlags & Modifiers.SEALED) != 0){
1633 "Class declared as 'NotInheritable' " +
1634 "cannot have a 'MustOverride' member");
1637 else if ((ModFlags & Modifiers.ABSTRACT) == 0){
1640 " is declared as 'MustOverride', hence its container " +
1641 "class should be declared as 'MustInherit'");
1647 if ((flags & Modifiers.PRIVATE) != 0){
1648 if ((flags & vao) != 0){
1651 ": Members marked as Overridable or Overrides can not be Private");
1656 if ((flags & Modifiers.SEALED) != 0){
1657 if ((flags & Modifiers.OVERRIDE) == 0){
1660 ": cannot be sealed because it is not an override");
1664 if ((flags & Modifiers.NEW) != 0){
1665 if ((flags & Modifiers.SHADOWS) != 0){
1668 " 'Overloads' and 'Shadows' cannot be combined ");
1676 // Access level of a type.
1679 ProtectedInternal = 1,
1685 // Check whether `flags' denotes a more restricted access than `level'
1686 // and return the new level.
1687 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1689 //AccessLevel old_level = level;
1691 if ((flags & Modifiers.INTERNAL) != 0) {
1692 if ((flags & Modifiers.PROTECTED) != 0) {
1693 if ((int) level < (int) AccessLevel.ProtectedInternal)
1694 level = AccessLevel.ProtectedInternal;
1696 if ((int) level < (int) AccessLevel.Internal)
1697 level = AccessLevel.Internal;
1699 } else if ((flags & Modifiers.PROTECTED) != 0) {
1700 if ((int) level < (int) AccessLevel.Protected)
1701 level = AccessLevel.Protected;
1702 } else if ((flags & Modifiers.PRIVATE) != 0)
1703 level = AccessLevel.Private;
1708 // Return the access level for a new member which is defined in the current
1709 // TypeContainer with access modifiers `flags'.
1710 AccessLevel GetAccessLevel (int flags)
1712 if ((flags & Modifiers.PRIVATE) != 0)
1713 return AccessLevel.Private;
1716 if (!IsTopLevel && (Parent != null))
1717 level = Parent.GetAccessLevel (flags);
1719 level = AccessLevel.Public;
1721 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1724 // Return the access level for type `t', but don't give more access than `flags'.
1725 static AccessLevel GetAccessLevel (Type t, int flags)
1727 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1728 return AccessLevel.Private;
1731 if (TypeManager.IsBuiltinType (t))
1732 return AccessLevel.Public;
1733 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1734 level = GetAccessLevel (t.DeclaringType, flags);
1736 level = CheckAccessLevel (AccessLevel.Public, flags);
1739 if (t.IsNestedPublic)
1742 if (t.IsNestedAssembly || t.IsNotPublic) {
1743 if ((int) level < (int) AccessLevel.Internal)
1744 level = AccessLevel.Internal;
1747 if (t.IsNestedFamily) {
1748 if ((int) level < (int) AccessLevel.Protected)
1749 level = AccessLevel.Protected;
1752 if (t.IsNestedFamORAssem) {
1753 if ((int) level < (int) AccessLevel.ProtectedInternal)
1754 level = AccessLevel.ProtectedInternal;
1761 // Returns true if `parent' is as accessible as the flags `flags'
1762 // given for this member.
1764 public bool AsAccessible (Type parent, int flags)
1766 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1767 parent = parent.GetElementType ();
1769 AccessLevel level = GetAccessLevel (flags);
1770 AccessLevel level2 = GetAccessLevel (parent, flags);
1772 return (int) level >= (int) level2;
1775 Hashtable builder_and_args;
1777 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1779 if (builder_and_args == null)
1780 builder_and_args = new Hashtable ();
1785 /// Performs checks for an explicit interface implementation. First it
1786 /// checks whether the `interface_type' is a base inteface implementation.
1787 /// Then it checks whether `name' exists in the interface type.
1789 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1793 if (ifaces != null){
1794 foreach (Type t in ifaces){
1795 if (t == interface_type){
1803 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1810 public static void Error_NotInterfaceMember (Location loc, string member_name, string iface_name)
1812 Report.Error (30401, loc, "'" + member_name + "' is not a member of the interface '" + iface_name + "'");
1819 string IMemberContainer.Name {
1825 Type IMemberContainer.Type {
1831 IMemberContainer IMemberContainer.Parent {
1833 return parent_container;
1837 MemberCache IMemberContainer.MemberCache {
1839 return member_cache;
1843 bool IMemberContainer.IsInterface {
1845 return this is Interface;
1849 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1851 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1856 public class Class : TypeContainer {
1858 // Modifiers allowed in a class declaration
1860 public const int AllowedModifiers =
1863 Modifiers.PROTECTED |
1864 Modifiers.INTERNAL |
1866 Modifiers.ABSTRACT |
1869 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1870 : base (parent, name, attrs, l)
1874 if (parent.Parent == null)
1875 accmods = Modifiers.INTERNAL;
1877 accmods = Modifiers.PUBLIC;
1879 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1882 public override AttributeTargets AttributeTargets {
1884 return AttributeTargets.Class;
1888 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
1890 if (a.UsageAttribute != null) {
1891 if (base_class_type != TypeManager.attribute_type && !base_class_type.IsSubclassOf (TypeManager.attribute_type) &&
1892 TypeBuilder.FullName != "System.Attribute") {
1893 Report.Error (641, a.Location, "Attribute '" + a.Name + "' is only valid on classes derived from System.Attribute");
1895 AttributeUsage = a.UsageAttribute;
1897 base.ApplyAttributeBuilder (a, cb);
1901 // FIXME: How do we deal with the user specifying a different
1904 public override TypeAttributes TypeAttr {
1906 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1911 public class Struct : TypeContainer {
1913 // Modifiers allowed in a struct declaration
1915 public const int AllowedModifiers =
1918 Modifiers.PROTECTED |
1919 Modifiers.INTERNAL |
1923 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1924 : base (parent, name, attrs, l)
1928 if (parent.Parent == null)
1929 accmods = Modifiers.INTERNAL;
1931 accmods = Modifiers.PUBLIC;
1933 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1935 this.ModFlags |= Modifiers.SEALED;
1938 public override AttributeTargets AttributeTargets {
1940 return AttributeTargets.Struct;
1945 // FIXME: Allow the user to specify a different set of attributes
1946 // in some cases (Sealed for example is mandatory for a class,
1947 // but what SequentialLayout can be changed
1949 public override TypeAttributes TypeAttr {
1951 return base.TypeAttr |
1952 TypeAttributes.SequentialLayout |
1953 TypeAttributes.Sealed |
1954 TypeAttributes.BeforeFieldInit;
1959 public abstract class MethodCore : MemberBase {
1960 public /* readonly */ Parameters Parameters;
1964 // Parameters, cached for semantic analysis.
1966 protected InternalParameters parameter_info;
1967 protected Type [] parameter_types;
1969 // Whether this is an operator
1970 public bool IsOperator;
1972 public MethodCore (Expression type, int mod, int allowed_mod, string name,
1973 Attributes attrs, Parameters parameters, Location loc)
1974 : base (type, mod, allowed_mod, name, attrs, loc)
1976 Parameters = parameters;
1980 // Returns the System.Type array for the parameters of this method
1982 public Type [] ParameterTypes {
1984 return parameter_types;
1988 public InternalParameters ParameterInfo
1991 return parameter_info;
1995 public Block Block {
2005 protected virtual bool DoDefineParameters (TypeContainer parent)
2007 // Check if arguments were correct
2008 parameter_types = Parameters.GetParameterInfo (parent);
2009 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2012 parameter_info = new InternalParameters (parent, Parameters);
2017 public CallingConventions GetCallingConvention (bool is_class)
2019 CallingConventions cc = 0;
2021 cc = Parameters.GetCallingConvention ();
2024 if ((ModFlags & Modifiers.STATIC) == 0)
2025 cc |= CallingConventions.HasThis;
2027 // FIXME: How is `ExplicitThis' used in C#?
2033 public class Method : MethodCore {
2034 public MethodBuilder MethodBuilder;
2035 public MethodData MethodData;
2038 /// Modifiers allowed in a class declaration
2040 const int AllowedModifiers =
2043 Modifiers.PROTECTED |
2044 Modifiers.INTERNAL |
2048 Modifiers.NONVIRTUAL |
2049 Modifiers.OVERRIDE |
2050 Modifiers.ABSTRACT |
2056 // return_type can be "null" for VOID values.
2058 public Method (Expression return_type, int mod, string name, Parameters parameters,
2059 Attributes attrs, Location l)
2060 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2065 public Method (Expression return_type, int mod, string name, Parameters parameters,
2066 Attributes attrs, ArrayList impl_what, Location l)
2067 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2069 Implements = impl_what;
2072 public override AttributeTargets AttributeTargets {
2074 return AttributeTargets.Method;
2079 // Returns the `System.Type' for the ReturnType of this
2080 // function. Provides a nice cache. (used between semantic analysis
2081 // and actual code generation
2083 public Type GetReturnType ()
2088 void DuplicateEntryPoint (MethodInfo b, Location location)
2092 "Program `" + CodeGen.FileName +
2093 "' has more than one entry point defined: `" +
2094 TypeManager.MonoBASIC_Signature(b) + "'");
2097 void Report28 (MethodInfo b)
2099 if (RootContext.WarningLevel < 4)
2104 "`" + TypeManager.MonoBASIC_Signature(b) +
2105 "' has the wrong signature to be an entry point");
2108 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2110 if (b.ReturnType != TypeManager.void_type &&
2111 b.ReturnType != TypeManager.int32_type)
2114 if (pinfo.Count == 0)
2117 if (pinfo.Count > 1)
2120 Type t = pinfo.ParameterType(0);
2122 (t.GetArrayRank() == 1) &&
2123 (t.GetElementType() == TypeManager.string_type) &&
2124 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2131 // Checks our base implementation if any
2133 protected override bool CheckBase (TypeContainer parent)
2135 // Check whether arguments were correct.
2136 if (!DoDefineParameters (parent))
2139 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2143 mi_this = TypeContainer.FindMembers (
2144 parent.TypeBuilder, MemberTypes.Method,
2145 BindingFlags.NonPublic | BindingFlags.Public |
2146 BindingFlags.Static | BindingFlags.Instance |
2147 BindingFlags.DeclaredOnly,
2148 MethodSignature.method_signature_filter, ms);
2150 if (mi_this.Count > 0) {
2151 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2152 "already defines a member called `" + Name + "' " +
2153 "with the same parameter types");
2159 // Verify if the parent has a type with the same name, and then
2160 // check whether we have to create a new slot for it or not.
2162 Type ptype = parent.TypeBuilder.BaseType;
2164 // ptype is only null for System.Object while compiling corlib.
2166 MemberList mi, mi_static, mi_instance;
2168 mi_static = TypeContainer.FindMembers (
2169 ptype, MemberTypes.Method,
2170 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2171 MethodSignature.inheritable_method_signature_filter, ms);
2173 mi_instance = TypeContainer.FindMembers (
2174 ptype, MemberTypes.Method,
2175 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2176 MethodSignature.inheritable_method_signature_filter,
2179 if (mi_instance.Count > 0){
2181 } else if (mi_static.Count > 0)
2186 if (mi != null && mi.Count > 0){
2187 parent_method = (MethodInfo) mi [0];
2188 string name = parent_method.DeclaringType.Name + "." +
2191 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2194 if ((ModFlags & Modifiers.NEW) == 0) {
2195 Type parent_ret = TypeManager.TypeToCoreType (
2196 parent_method.ReturnType);
2198 if (parent_ret != MemberType) {
2200 508, parent.MakeName (Name) + ": cannot " +
2201 "change return type when overriding " +
2202 "inherited member " + name);
2207 /*if ((ModFlags & Modifiers.NEW) != 0)
2208 WarningNotHiding (parent);*/
2210 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2211 Report.Error (30398, Location,
2212 parent.MakeName (Name) +
2213 " : No suitable methods found to override");
2215 if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0)
2217 if ((ModFlags & Modifiers.NONVIRTUAL) != 0)
2219 Report.Error (31088, Location,
2220 parent.MakeName (Name) + " : Cannot " +
2221 "be declared NotOverridable since this method is " +
2222 "not maked as Overrides");
2225 // if a member of module is not inherited from Object class
2226 // can not be declared protected
2227 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
2228 Report.Error (31066, Location,
2229 "'Sub' or 'Function' inside a 'Module' can not be declared as " +
2230 "'Protected' or 'Protected Friend'");
2233 /* else if ((ModFlags & Modifiers.NEW) != 0)
2234 WarningNotHiding (parent);
2243 public override bool Define (TypeContainer parent)
2245 if (!DoDefine (parent))
2248 if (!CheckBase (parent))
2251 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
2252 Report.Error (31067, Location,
2253 "'Sub' or 'Function' inside a 'Structure' can not be declared as " +
2254 "'Protected' or 'Protected Friend'");
2256 CallingConventions cc = GetCallingConvention (parent is Class);
2258 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2259 ParameterInfo, cc, OptAttributes,
2260 ModFlags, flags, true);
2262 if (!MethodData.Define (parent))
2265 MethodBuilder = MethodData.MethodBuilder;
2268 // This is used to track the Entry Point,
2270 if (Name.ToUpper() == "MAIN" &&
2271 ((ModFlags & Modifiers.STATIC) != 0) &&
2272 (RootContext.MainClass == null ||
2273 RootContext.MainClass == parent.TypeBuilder.FullName ||
2274 (RootContext.RootNamespace != null &&
2275 RootContext.RootNamespace.Length > 0 &&
2276 (RootContext.RootNamespace + "." + RootContext.MainClass) == parent.TypeBuilder.FullName))) {
2277 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2278 if (RootContext.EntryPoint == null) {
2279 RootContext.EntryPoint = MethodBuilder;
2280 RootContext.EntryPointLocation = Location;
2282 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2283 DuplicateEntryPoint (MethodBuilder, Location);
2286 Report28(MethodBuilder);
2295 public void Emit (TypeContainer parent)
2297 MethodData.Emit (parent, Block, this);
2300 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2302 throw new Exception ("FIXME: I am just a placeholder implementation");
2306 public abstract class ConstructorInitializer {
2307 ArrayList argument_list;
2308 ConstructorInfo parent_constructor;
2309 Parameters parameters;
2311 public bool implicit_initialization;
2313 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2316 this.argument_list = argument_list;
2317 this.parameters = parameters;
2319 this.implicit_initialization = false;
2322 public ArrayList Arguments {
2324 return argument_list;
2328 public ConstructorInfo ParentConstructor
2332 return parent_constructor;
2336 public bool Resolve (EmitContext ec)
2338 Expression parent_constructor_group;
2341 ec.CurrentBlock = new Block (null, true, parameters);
2343 if (argument_list != null){
2344 foreach (Argument a in argument_list){
2345 if (!a.Resolve (ec, loc))
2350 ec.CurrentBlock = null;
2352 if (this is ConstructorBaseInitializer) {
2353 if (ec.ContainerType.BaseType == null)
2356 t = ec.ContainerType.BaseType;
2357 if (ec.ContainerType.IsValueType){
2358 Report.Error (522, loc,
2359 "structs cannot call base class constructors");
2364 t = ec.ContainerType;
2366 parent_constructor_group = Expression.MemberLookup (
2368 MemberTypes.Constructor,
2369 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2372 if (parent_constructor_group == null){
2373 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2377 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2378 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2380 if (parent_constructor == null) {
2381 if (this.implicit_initialization)
2382 Report.Error (30148, loc, "Must declare 'MyBase.New' in the constructor " +
2383 "of the class '" + ec.TypeContainer.Name + "' with appropriate arguments, since the base class '" +
2384 t.FullName + "' does not contain a definition of 'New' without any parameter");
2386 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2394 public void Emit (EmitContext ec)
2396 if (parent_constructor != null){
2398 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2400 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2407 public class ConstructorBaseInitializer : ConstructorInitializer {
2408 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2409 base (argument_list, pars, l)
2414 public class ConstructorThisInitializer : ConstructorInitializer {
2415 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2416 base (argument_list, pars, l)
2421 public class Constructor : MethodCore {
2422 public ConstructorBuilder ConstructorBuilder;
2423 public ConstructorInitializer Initializer;
2426 // Modifiers allowed for a constructor.
2428 public const int AllowedModifiers =
2430 Modifiers.PROTECTED |
2431 Modifiers.INTERNAL |
2438 // The spec claims that static is not permitted, but
2439 // my very own code has static constructors.
2441 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2442 : base (null, 0, AllowedModifiers, name, null, args, l)
2447 public Constructor (string name, int mod, Parameters args, ConstructorInitializer init, Location l)
2448 : base (null, mod, AllowedModifiers, name, null, args, l)
2453 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2455 ConstructorBuilder.SetCustomAttribute (cb);
2458 public override AttributeTargets AttributeTargets {
2460 return AttributeTargets.Constructor;
2465 // Returns true if this is a default constructor
2467 public bool IsDefault ()
2469 if ((ModFlags & Modifiers.STATIC) != 0)
2470 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2471 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2474 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2475 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2476 (Initializer is ConstructorBaseInitializer) &&
2477 (Initializer.Arguments == null);
2481 // Creates the ConstructorBuilder
2483 public override bool Define (TypeContainer parent)
2485 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2486 MethodAttributes.SpecialName);
2488 if (parent.EventHandlers != null) {
2489 ArrayList hdlrs = parent.EventHandlers;
2490 foreach(Statement stmt in hdlrs)
2491 this.Block.AddStatement (stmt);
2495 // Check if arguments were correct.
2496 if (!DoDefineParameters (parent))
2499 if ((ModFlags & Modifiers.STATIC) != 0) {
2500 ca |= MethodAttributes.Static;
2502 if (this.Parameters != Parameters.EmptyReadOnlyParameters)
2505 "Shared constructor can not have parameters");
2507 if ((ModFlags & Modifiers.Accessibility) != 0)
2510 "Shared constructor can not be declared " +
2511 "explicitly as public, private, friend or protected");
2513 if (this.Initializer != null)
2516 "Keywords like MyBase, MyClass, Me are not " +
2517 "valid inside a Shared Constructor");
2520 if (parent is Struct && ParameterTypes.Length == 0) {
2523 "Structs can not contain explicit parameterless " +
2527 ca |= MethodAttributes.HideBySig;
2529 if ((ModFlags & Modifiers.PUBLIC) != 0)
2530 ca |= MethodAttributes.Public;
2531 else if ((ModFlags & Modifiers.PROTECTED) != 0) {
2532 if ((ModFlags & Modifiers.INTERNAL) != 0)
2533 ca |= MethodAttributes.FamORAssem;
2535 ca |= MethodAttributes.Family;
2537 else if ((ModFlags & Modifiers.INTERNAL) != 0)
2538 ca |= MethodAttributes.Assembly;
2539 else if (IsDefault ())
2540 ca |= MethodAttributes.Public;
2542 ca |= MethodAttributes.Private;
2545 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2546 ca, GetCallingConvention (parent is Class), ParameterTypes);
2549 // HACK because System.Reflection.Emit is lame
2551 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2554 "Class `" +parent.Name+ "' already contains a definition with the " +
2555 "same return value and parameter types for constructor `" + Name
2566 public void Emit (TypeContainer parent)
2568 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2569 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2571 if ((ModFlags & Modifiers.STATIC) == 0){
2572 if (parent is Class && Initializer == null) {
2573 Initializer = new ConstructorBaseInitializer (
2574 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2575 Initializer.implicit_initialization = true;
2579 // Spec mandates that Initializers will not have
2583 if (Initializer != null && !Initializer.Resolve (ec))
2585 ec.IsStatic = false;
2588 Parameters.LabelParameters (ec, ConstructorBuilder, Location);
2591 // Classes can have base initializers and instance field initializers.
2593 if (parent is Class){
2594 if ((ModFlags & Modifiers.STATIC) == 0)
2595 parent.EmitFieldInitializers (ec);
2598 if (Initializer != null) {
2599 if (this.ConstructorBuilder.Equals (Initializer.ParentConstructor))
2602 "A constructor can not call itself" );
2604 Initializer.Emit (ec);
2607 if ((ModFlags & Modifiers.STATIC) != 0)
2608 parent.EmitFieldInitializers (ec);
2610 if (OptAttributes != null)
2611 OptAttributes.Emit (ec, this);
2613 // If this is a non-static `struct' constructor and doesn't have any
2614 // initializer, it must initialize all of the struct's fields.
2615 if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2616 (Initializer == null))
2617 Block.AddThisVariable (parent, Location);
2619 ec.EmitTopBlock (Block, ParameterInfo, Location);
2623 public class MethodData {
2625 // The return type of this method
2627 public readonly Type ReturnType;
2628 public readonly Type[] ParameterTypes;
2629 public readonly InternalParameters ParameterInfo;
2630 public readonly CallingConventions CallingConventions;
2631 public readonly Attributes OptAttributes;
2632 public readonly Location Location;
2635 // Are we implementing an interface ?
2637 public bool IsImplementing = false;
2642 readonly MemberBase member;
2643 readonly int modifiers;
2644 MethodAttributes flags;
2645 readonly bool is_method;
2646 readonly string accessor_name;
2647 ArrayList conditionals;
2649 MethodBuilder builder = null;
2650 public MethodBuilder MethodBuilder {
2656 public MethodData (MemberBase member, string name, Type return_type,
2657 Type [] parameter_types, InternalParameters parameters,
2658 CallingConventions cc, Attributes opt_attrs,
2659 int modifiers, MethodAttributes flags, bool is_method)
2661 this.member = member;
2662 this.accessor_name = name;
2663 this.ReturnType = return_type;
2664 this.ParameterTypes = parameter_types;
2665 this.ParameterInfo = parameters;
2666 this.CallingConventions = cc;
2667 this.OptAttributes = opt_attrs;
2668 this.modifiers = modifiers;
2670 this.is_method = is_method;
2671 this.Location = member.Location;
2672 this.conditionals = new ArrayList ();
2678 Attribute dllimport_attribute = null;
2679 string obsolete = null;
2680 bool obsolete_error = false;
2682 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2684 if ((opt_attrs == null) || (opt_attrs.Attrs == null))
2687 foreach (Attribute a in opt_attrs.Attrs) {
2688 if (a.Name == "Conditional") {
2689 if (!ApplyConditionalAttribute (a))
2691 } else if (a.Name == "Obsolete") {
2692 if (!ApplyObsoleteAttribute (a))
2694 } else if (a.Name.IndexOf ("DllImport") != -1) {
2696 a.Type = TypeManager.dllimport_type;
2697 Attribute.Error_AttributeNotValidForElement (a, Location);
2700 if (!ApplyDllImportAttribute (a))
2709 // Applies the `DllImport' attribute to the method.
2711 protected virtual bool ApplyDllImportAttribute (Attribute a)
2713 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2714 if ((modifiers & extern_static) != extern_static) {
2715 Report.Error (601, Location,
2716 "The DllImport attribute must be specified on a method " +
2717 "marked `static' and `extern'.");
2721 flags |= MethodAttributes.PinvokeImpl;
2722 dllimport_attribute = a;
2727 // Applies the `Obsolete' attribute to the method.
2729 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2731 if (obsolete != null) {
2732 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2736 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2737 return obsolete != null;
2741 // Applies the `Conditional' attribute to the method.
2743 protected virtual bool ApplyConditionalAttribute (Attribute a)
2745 // The Conditional attribute is only valid on methods.
2747 Attribute.Error_AttributeNotValidForElement (a, Location);
2751 string condition = a.Conditional_GetConditionName ();
2753 if (condition == null)
2756 if (ReturnType != TypeManager.void_type) {
2757 Report.Error (578, Location,
2758 "Conditional not valid on `" + member.Name + "' " +
2759 "because its return type is not void");
2763 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2764 Report.Error (243, Location,
2765 "Conditional not valid on `" + member.Name + "' " +
2766 "because it is an override method");
2770 if (member.IsExplicitImpl) {
2771 Report.Error (577, Location,
2772 "Conditional not valid on `" + member.Name + "' " +
2773 "because it is an explicit interface implementation");
2777 if (IsImplementing) {
2778 Report.Error (623, Location,
2779 "Conditional not valid on `" + member.Name + "' " +
2780 "because it is an interface method");
2784 conditionals.Add (condition);
2790 // Checks whether this method should be ignored due to its Conditional attributes.
2792 bool ShouldIgnore (Location loc)
2794 // When we're overriding a virtual method, we implicitly inherit the
2795 // Conditional attributes from our parent.
2796 if (member.ParentMethod != null) {
2797 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2798 member.ParentMethod, loc);
2800 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2804 foreach (string condition in conditionals)
2805 if (RootContext.AllDefines [condition] == null)
2812 // Returns the TypeManager.MethodFlags for this method.
2813 // This emits an error 619 / warning 618 if the method is obsolete.
2814 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2816 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2818 TypeManager.MethodFlags flags = 0;
2820 if (obsolete != null) {
2821 if (obsolete_error) {
2822 Report.Error (619, loc, "Method `" + member.Name +
2823 "' is obsolete: `" + obsolete + "'");
2824 return TypeManager.MethodFlags.IsObsoleteError;
2826 Report.Warning (618, loc, "Method `" + member.Name +
2827 "' is obsolete: `" + obsolete + "'");
2829 flags |= TypeManager.MethodFlags.IsObsolete;
2832 if (ShouldIgnore (loc))
2833 flags |= TypeManager.MethodFlags.ShouldIgnore;
2839 // Search all the interface bases recursively for unimplemented methods
2841 bool SearchBasesForAbstractMethods (
2842 TypeContainer parent, Type iface_type,
2843 string method_name, ref ArrayList implementing_list,
2844 ref ArrayList implementing_iface)
2846 MethodInfo implementing = null;
2847 bool IsImplementing = false;
2848 Type current_iface_type = iface_type;
2850 implementing = parent.Pending.IsAbstractMethod (
2851 current_iface_type, method_name, ReturnType, ParameterTypes);
2853 if (implementing != null) {
2854 if (!implementing_list.Contains (implementing)) {
2855 implementing_list.Add (implementing);
2856 implementing_iface.Add(current_iface_type);
2858 IsImplementing = true;
2860 Type[] current_iface_types = current_iface_type.GetInterfaces();
2861 if (current_iface_types.Length == 0)
2864 foreach (Type curr_iface_type in current_iface_types) {
2865 IsImplementing = SearchBasesForAbstractMethods (
2866 parent, curr_iface_type, method_name,
2867 ref implementing_list, ref implementing_iface);
2874 return IsImplementing;
2877 public virtual bool Define (TypeContainer parent)
2879 MethodInfo implementing = null;
2880 ArrayList implementing_list = null;
2881 ArrayList implementing_iface = null;
2882 string method_name, name, prefix, impl_method_name;
2885 if (OptAttributes != null)
2886 if (!ApplyAttributes (OptAttributes, is_method))
2889 if (accessor_name != null)
2890 name = accessor_name + "_" + member.ShortName;
2892 name = member.ShortName;
2895 impl_method_name = name;
2897 if ((member.ModFlags & Modifiers.OVERRIDE) != 0) {
2898 if (parent.Pending == null)
2899 implementing = null;
2901 implementing = parent.Pending.IsAbstractMethod (
2902 (Type) parent.TypeBuilder.BaseType, name,
2903 ReturnType, ParameterTypes);
2905 if (implementing != null)
2906 IsImplementing = true;
2909 if (member.Implements != null) {
2910 implementing_list = new ArrayList();
2911 implementing_iface = new ArrayList();
2913 foreach (Expression Impl in member.Implements) {
2914 name = Impl.ToString();
2915 prefix = name.Substring(0, name.LastIndexOf("."));
2916 name = name.Substring(name.LastIndexOf(".") + 1);
2918 if (accessor_name != null)
2919 impl_method_name = accessor_name + "_" + name;
2921 impl_method_name = name;
2923 Type current_iface_type = (Type) member.InterfaceTypes[++pos];
2924 IsImplementing = SearchBasesForAbstractMethods (
2925 parent, current_iface_type, impl_method_name,
2926 ref implementing_list, ref implementing_iface);
2928 if (IsImplementing == false) {
2929 TypeContainer.Error_NotInterfaceMember (
2930 Location, name, prefix);
2937 // For implicit implementations, make sure we are public, for
2938 // explicit implementations, make sure we are private.
2940 //if (IsImplementing){
2942 // Setting null inside this block will trigger a more
2943 // verbose error reporting for missing interface implementations
2945 // The "candidate" function has been flagged already
2946 // but it wont get cleared
2948 /* if (!member.IsExplicitImpl){
2950 // We already catch different accessibility settings
2951 // so we just need to check that we are not private
2953 if ((modifiers & Modifiers.PRIVATE) != 0)
2954 implementing = null;
2957 // Static is not allowed
2959 if ((modifiers & Modifiers.STATIC) != 0)
2960 implementing = null;
2962 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2963 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2964 implementing = null;
2970 // If implementing is still valid, set flags
2972 if (IsImplementing){
2974 // When implementing interface methods, set NewSlot.
2976 if (implementing_list != null && implementing_list.Count != 0)
2977 flags |= MethodAttributes.NewSlot;
2980 MethodAttributes.Virtual |
2981 MethodAttributes.HideBySig;
2985 // Create the MethodBuilder for the method
2987 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2988 if ((modifiers & Modifiers.STATIC) == 0) {
2989 Report.Error (601, Location,
2990 "The DllImport attribute must be specified on " +
2991 "a method marked 'static' and 'extern'.");
2995 EmitContext ec = new EmitContext (
2996 parent, Location, null, ReturnType, modifiers);
2998 builder = dllimport_attribute.DefinePInvokeMethod (
2999 ec, parent.TypeBuilder, method_name, flags,
3000 ReturnType, ParameterTypes);
3002 builder = parent.TypeBuilder.DefineMethod (
3003 method_name, flags, CallingConventions,
3004 ReturnType, ParameterTypes);
3006 if (builder == null)
3009 if (IsImplementing) {
3011 // implement abstract methods from abstract classes
3013 if ((member.ModFlags & Modifiers.OVERRIDE) != 0) {
3015 if (member is Indexer)
3016 parent.Pending.ImplementIndexer (
3017 (Type) parent.TypeBuilder.BaseType,
3018 builder, ReturnType,
3019 ParameterTypes, true);
3022 parent.Pending.ImplementMethod (
3023 (Type) parent.TypeBuilder.BaseType,
3025 ParameterTypes, member.IsExplicitImpl);
3029 // implement abstract methods of interfaces
3031 if (member.Implements != null) {
3033 foreach (MethodInfo Impl in implementing_list) {
3036 if (member is Indexer)
3037 parent.Pending.ImplementIndexer (
3038 (Type) implementing_iface[pos++],
3039 builder, ReturnType,
3040 ParameterTypes, true);
3043 parent.Pending.ImplementMethod (
3044 (Type) implementing_iface[pos++],
3045 Impl.Name, ReturnType,
3046 ParameterTypes, member.IsExplicitImpl);
3048 parent.TypeBuilder.DefineMethodOverride (
3055 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3056 Report.Error (111, Location,
3057 "Class `" + parent.Name +
3058 "' already contains a definition with the " +
3059 "same return value and parameter types as the " +
3060 "'get' method of property `" + member.Name + "'");
3064 TypeManager.AddMethod (builder, this);
3071 public virtual void Emit (TypeContainer parent, Block block, object kind)
3076 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3077 ig = builder.GetILGenerator ();
3081 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3083 if (OptAttributes != null)
3084 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3086 if (member is MethodCore)
3087 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, ((MethodCore) member).Location);
3090 // abstract or extern methods have no bodies
3092 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3097 // abstract or extern methods have no bodies.
3099 if ((modifiers & Modifiers.ABSTRACT) != 0)
3101 500, Location, "Abstract method `" +
3102 TypeManager.MonoBASIC_Signature (builder) +
3103 "' can not have a body");
3105 if ((modifiers & Modifiers.EXTERN) != 0)
3107 179, Location, "External method `" +
3108 TypeManager.MonoBASIC_Signature (builder) +
3109 "' can not have a body");
3115 // Methods must have a body unless they're extern or abstract
3117 if (block == null) {
3119 501, Location, "Method `" +
3120 TypeManager.MonoBASIC_Signature (builder) +
3121 "' must declare a body since it is not marked " +
3122 "abstract or extern");
3127 // Handle destructors specially
3129 // FIXME: This code generates buggy code
3131 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3132 EmitDestructor (ec, block);
3134 ISymbolWriter sw = CodeGen.SymbolWriter;
3136 if ((sw != null) && !Location.IsNull (Location) &&
3137 !Location.IsNull (block.EndLocation)) {
3138 Location end = block.EndLocation;
3139 MethodToken token = MethodBuilder.GetToken ();
3140 sw.OpenMethod (new SymbolToken (token.Token));
3141 // Avoid error if we don't support debugging for the platform
3143 sw.SetMethodSourceRange (Location.SymbolDocument,
3147 } catch (Exception) {
3150 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3154 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3158 void EmitDestructor (EmitContext ec, Block block)
3160 ILGenerator ig = ec.ig;
3162 Label finish = ig.DefineLabel ();
3163 bool old_in_try = ec.InTry;
3165 ig.BeginExceptionBlock ();
3167 ec.ReturnLabel = finish;
3168 ec.HasReturnLabel = true;
3169 ec.EmitTopBlock (block, null, Location);
3170 ec.InTry = old_in_try;
3172 // ig.MarkLabel (finish);
3173 bool old_in_finally = ec.InFinally;
3174 ec.InFinally = true;
3175 ig.BeginFinallyBlock ();
3177 if (ec.ContainerType.BaseType != null) {
3178 Expression member_lookup = Expression.MemberLookup (
3179 ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3180 MemberTypes.Method, Expression.AllBindingFlags, Location);
3182 if (member_lookup != null){
3183 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3185 ig.Emit (OpCodes.Ldarg_0);
3186 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3189 ec.InFinally = old_in_finally;
3191 ig.EndExceptionBlock ();
3192 //ig.MarkLabel (ec.ReturnLabel);
3193 ig.Emit (OpCodes.Ret);
3197 abstract public class MemberBase : MemberCore {
3198 public Expression Type;
3199 public ArrayList Implements;
3201 protected MethodAttributes flags;
3204 // The "short" name of this property / indexer / event. This is the
3205 // name without the explicit interface.
3207 public string ShortName;
3210 // The type of this property / indexer / event
3212 public Type MemberType;
3215 // If true, this is an explicit interface implementation
3217 public bool IsExplicitImpl = false;
3220 // The name of the interface we are explicitly implementing
3222 public string ExplicitInterfaceName = null;
3225 // If true, the interface type we are explicitly implementing
3227 public Type InterfaceType = null;
3228 public ArrayList InterfaceTypes = null;
3231 // The method we're overriding if this is an override method.
3233 protected MethodInfo parent_method = null;
3234 public MethodInfo ParentMethod {
3236 return parent_method;
3241 // The constructor is only exposed to our children
3243 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3244 Attributes attrs, Location loc)
3245 : base (name, attrs, loc)
3248 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PUBLIC, loc);
3251 protected virtual bool CheckBase (TypeContainer parent)
3256 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3260 foreach (Type partype in parameters){
3261 if (partype.IsPointer && !UnsafeOK (parent))
3264 if (parent.AsAccessible (partype, ModFlags))
3267 Report.Error (51, Location,
3268 "Inconsistent accessibility: parameter type `" +
3269 TypeManager.MonoBASIC_Name (partype) + "' is less " +
3270 "accessible than method `" + Name + "'");
3277 protected virtual bool DoDefine (TypeContainer parent)
3282 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3285 flags = Modifiers.MethodAttr (ModFlags);
3287 // Lookup Type, verify validity
3288 MemberType = parent.ResolveType (Type, false, Location);
3289 if (MemberType == null)
3292 // check for whether the Interface is implemented by the class
3293 if (Implements != null) {
3294 InterfaceTypes = new ArrayList ();
3295 foreach (Expression Impls in Implements) {
3296 string iname = Impls.ToString();
3297 iname = iname.Substring(0, iname.LastIndexOf("."));
3298 bool iface_found = false;
3300 InterfaceType = RootContext.LookupType (
3301 parent, iname, false, Location);
3302 if (InterfaceType == null)
3305 InterfaceTypes.Add (InterfaceType);
3306 Type[] tbases = parent.TypeBuilder.GetInterfaces();
3308 if (tbases.Length != 0) {
3309 ArrayList bases = new ArrayList();
3310 TypeManager.ExpandAllInterfaces (tbases, ref bases);
3312 foreach (Type tbase in bases) {
3314 string bname = tbase.Name;
3315 if (bname.LastIndexOf(".") != -1)
3316 bname = bname.Substring(bname.LastIndexOf("."));
3319 //if (bname == iname) {
3320 if (tbase == InterfaceType) {
3328 Report.Error (31035, Location,
3329 "Class '" + parent.Name + "' doesn't implement interface '" + iname + "'");
3335 // verify accessibility
3336 if (!parent.AsAccessible (MemberType, ModFlags)) {
3337 if (this is Property)
3338 Report.Error (53, Location,
3339 "Inconsistent accessibility: property type `" +
3340 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3341 "accessible than property `" + Name + "'");
3342 else if (this is Method)
3343 Report.Error (30508, Location,
3344 "Inconsistent accessibility: return type `" +
3345 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3346 "accessible than method `" + Name + "'");
3348 Report.Error (52, Location,
3349 "Inconsistent accessibility: field type `" +
3350 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3351 "accessible than field `" + Name + "'");
3355 if (MemberType.IsPointer && !UnsafeOK (parent))
3359 // Check for explicit interface implementation
3361 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)) {
3362 int pos = Name.LastIndexOf (".");
3364 ExplicitInterfaceName = Name.Substring (0, pos);
3365 ShortName = Name.Substring (pos + 1);
3374 // Fields and Events both generate FieldBuilders, we use this to share
3375 // their common bits. This is also used to flag usage of the field
3377 abstract public class FieldBase : MemberBase {
3378 public FieldBuilder FieldBuilder;
3379 public Status status;
3382 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3385 // The constructor is only exposed to our children
3387 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3388 object init, Attributes attrs, Location loc)
3389 : base (type, mod, allowed_mod, name, attrs, loc)
3394 public override AttributeTargets AttributeTargets {
3396 return AttributeTargets.Field;
3402 // Whether this field has an initializer.
3404 public bool HasInitializer {
3406 return init != null;
3411 readonly Object init;
3412 Expression init_expr;
3413 bool init_expr_initialized = false;
3416 // Resolves and returns the field initializer.
3418 public Expression GetInitializerExpression (EmitContext ec)
3420 if (init_expr_initialized)
3424 if (init is Expression)
3425 e = (Expression) init;
3427 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3429 ec.IsFieldInitializer = true;
3430 e = e.DoResolve (ec);
3431 ec.IsFieldInitializer = false;
3434 init_expr_initialized = true;
3442 // The Field class is used to represents class/struct fields during parsing.
3444 public class Field : FieldBase {
3446 // Modifiers allowed in a class declaration
3448 const int AllowedModifiers =
3451 Modifiers.PROTECTED |
3452 Modifiers.INTERNAL |
3455 // Modifiers.VOLATILE |
3456 // Modifiers.UNSAFE |
3459 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3460 Attributes attrs, Location loc)
3461 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3465 public override AttributeTargets AttributeTargets {
3467 return AttributeTargets.Field;
3471 public override bool Define (TypeContainer parent)
3473 Type t = parent.ResolveType (Type, false, Location);
3478 if (!parent.AsAccessible (t, ModFlags)) {
3479 Report.Error (52, Location,
3480 "Inconsistent accessibility: field type `" +
3481 TypeManager.MonoBASIC_Name (t) + "' is less " +
3482 "accessible than field `" + Name + "'");
3486 if (t.IsPointer && !UnsafeOK (parent))
3489 Type ptype = parent.TypeBuilder.BaseType;
3491 // ptype is only null for System.Object while compiling corlib.
3493 MemberList list = TypeContainer.FindMembers (
3494 ptype, MemberTypes.Field,
3495 BindingFlags.Public |
3496 BindingFlags.Static | BindingFlags.Instance,
3497 System.Type.FilterName, Name);
3499 if (RootContext.WarningLevel > 1){
3500 if ((list.Count > 0) && ((ModFlags & Modifiers.SHADOWS) == 0))
3504 "Variable '" + Name + "' should be declared " +
3505 "Shadows since the base type '" + ptype.Name +
3506 "' has a variable with same name");
3508 ModFlags |= Modifiers.SHADOWS;
3511 if (list.Count == 0)
3512 // if a member of module is not inherited from Object class
3513 // can not be declared protected
3514 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
3515 Report.Error (30593, Location,
3516 "'Variable' inside a 'Module' can not be " +
3517 "declared as 'Protected'");
3520 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
3521 Report.Error (30435, Location,
3522 "'Variable' inside a 'Structure' can not be " +
3523 "declared as 'Protected'");
3525 if ((ModFlags & Modifiers.VOLATILE) != 0){
3527 if (TypeManager.IsEnumType (t))
3528 t = TypeManager.EnumToUnderlying (t);
3530 if (!((t == TypeManager.bool_type) ||
3531 (t == TypeManager.sbyte_type) ||
3532 (t == TypeManager.byte_type) ||
3533 (t == TypeManager.short_type) ||
3534 (t == TypeManager.ushort_type) ||
3535 (t == TypeManager.int32_type) ||
3536 (t == TypeManager.uint32_type) ||
3537 (t == TypeManager.char_type) ||
3538 (t == TypeManager.float_type))){
3540 677, Location, parent.MakeName (Name) +
3541 " A volatile field can not be of type `" +
3542 TypeManager.MonoBASIC_Name (t) + "'");
3548 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3550 if (parent is Struct &&
3551 ((fa & FieldAttributes.Static) == 0) &&
3552 t == parent.TypeBuilder &&
3553 !TypeManager.IsBuiltinType (t)){
3554 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
3555 "' causes a cycle in the structure layout");
3559 //Local Static Variable
3560 if (Name.StartsWith(@"$STATIC$"))
3561 FieldBuilder = parent.TypeBuilder.DefineField (
3562 Name, t, Modifiers.FieldAttr (ModFlags) | FieldAttributes.SpecialName);
3564 FieldBuilder = parent.TypeBuilder.DefineField (
3565 Name, t, Modifiers.FieldAttr (ModFlags));
3567 TypeManager.RegisterFieldBase (FieldBuilder, this);
3571 public void Emit (TypeContainer tc)
3573 EmitContext ec = new EmitContext (tc, Location, null,
3574 FieldBuilder.FieldType, ModFlags);
3576 if (OptAttributes != null)
3577 OptAttributes.Emit (ec, this);
3580 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3582 FieldBuilder.SetCustomAttribute (cb);
3588 // `set' and `get' accessors are represented with an Accessor.
3590 public class Accessor {
3592 // Null if the accessor is empty, or a Block if not
3595 public Attributes OptAttributes;
3597 public Accessor (Block b, Attributes attrs)
3600 OptAttributes = attrs;
3604 public class GetMethod {
3605 private Accessor Get;
3606 public MethodData GetData;
3607 public MethodBuilder GetBuilder;
3609 Property parent_property;
3612 Parameters get_params;
3614 public GetMethod (Property parent_property, Accessor get_block, Attributes attrs, Parameters p_get, Location loc)
3616 this.parent_property = parent_property;
3622 public MethodBuilder Define (TypeContainer parent)
3624 Type [] g_parameters=null;
3625 Parameter [] g_parms;
3626 InternalParameters g_ip=null;
3628 if (get_params == Parameters.EmptyReadOnlyParameters) {
3629 g_parameters = TypeManager.NoTypes;
3630 g_ip = new InternalParameters (parent, Parameters.EmptyReadOnlyParameters);
3632 g_parameters = new Type [get_params.FixedParameters.Length];
3633 for (int i = 0; i < get_params.FixedParameters.Length; i ++) {
3634 g_parameters[i] = get_params.FixedParameters[i].ParameterType;
3636 g_parms = new Parameter [get_params.FixedParameters.Length];
3637 for (int i = 0; i < get_params.FixedParameters.Length; i ++) {
3638 Parameter tp = get_params.FixedParameters[i];
3639 g_parms[i] = new Parameter (tp.TypeName, tp.Name,
3640 Parameter.Modifier.NONE, null);
3642 g_ip = new InternalParameters (
3643 parent, new Parameters (g_parms, null, Location));
3646 GetData = new MethodData (parent_property, "get", parent_property.MemberType,
3647 g_parameters, g_ip, CallingConventions.Standard,
3648 Get.OptAttributes, parent_property.ModFlags, parent_property.MethodAttributeFlags, false);
3650 if (!GetData.Define (parent))
3653 GetBuilder = GetData.MethodBuilder;
3658 public void Emit (TypeContainer tc)
3660 if (GetData != null)
3662 parent_property.Parameters = get_params;
3663 GetData.Emit (tc, Get.Block, Get);
3668 public class SetMethod {
3671 MethodBuilder SetBuilder;
3673 Property parent_property;
3676 string set_parameter_name;
3677 Parameters set_params;
3679 public SetMethod (Property parent_property, Accessor set_block, string set_name,
3680 Parameters p_set, Location loc)
3682 this.parent_property = parent_property;
3685 set_parameter_name = set_name;
3686 this.Location = loc;
3689 public MethodBuilder Define (TypeContainer parent)
3691 Type [] s_parameters=null;
3692 Parameter [] s_parms;
3693 InternalParameters s_ip=null;
3695 if (set_params == Parameters.EmptyReadOnlyParameters)
3697 s_parameters = new Type [1];
3698 s_parameters [0] = parent_property.MemberType;
3700 s_parms = new Parameter [1];
3701 s_parms [0] = new Parameter (parent_property.Type, set_parameter_name,
3702 Parameter.Modifier.NONE, null);
3704 s_parameters = new Type [set_params.FixedParameters.Length];
3705 for (int i = 0; i < set_params.FixedParameters.Length; i ++) {
3706 s_parameters[i] = set_params.FixedParameters[i].ParameterType;
3709 s_parms = new Parameter [set_params.FixedParameters.Length];
3710 for (int i = 0; i < set_params.FixedParameters.Length; i ++) {
3711 Parameter tp = set_params.FixedParameters[i];
3712 s_parms[i] = new Parameter (tp.TypeName, tp.Name,
3713 Parameter.Modifier.NONE, null);
3717 s_ip = new InternalParameters (
3718 parent, new Parameters (s_parms, null, Location));
3720 SetData = new MethodData (parent_property, "set", TypeManager.void_type,
3721 s_parameters, s_ip, CallingConventions.Standard,
3722 Set.OptAttributes, parent_property.ModFlags, parent_property.MethodAttributeFlags, false);
3724 if (!SetData.Define (parent))
3727 SetBuilder = SetData.MethodBuilder;
3728 SetBuilder.DefineParameter (1, ParameterAttributes.None,
3729 set_parameter_name);
3734 public void Emit (TypeContainer tc)
3736 if (SetData != null)
3738 parent_property.Parameters = set_params;
3739 SetData.Emit (tc, Set.Block, Set);
3744 public class Property : MethodCore {
3745 GetMethod GetMethod;
3746 SetMethod SetMethod;
3748 public Accessor Set;
3749 public PropertyBuilder PropertyBuilder;
3750 public MethodBuilder GetBuilder;
3751 public MethodBuilder SetBuilder;
3752 public MethodData SetData;
3754 protected EmitContext ec;
3756 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3758 PropertyBuilder.SetCustomAttribute (cb);
3761 public override AttributeTargets AttributeTargets {
3763 return AttributeTargets.Property;
3767 protected override bool DoDefine (TypeContainer parent)
3769 if (!base.DoDefine (parent))
3772 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3778 // Checks our base implementation if any
3780 protected override bool CheckBase (TypeContainer container)
3782 base.CheckBase (container);
3784 // Check whether arguments were correct.
3785 if (!DoDefineParameters (container))
3791 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
3796 mi_this = TypeContainer.FindMembers (
3797 container.TypeBuilder, MemberTypes.Property,
3798 BindingFlags.NonPublic | BindingFlags.Public |
3799 BindingFlags.Static | BindingFlags.Instance |
3800 BindingFlags.DeclaredOnly,
3801 MethodSignature.method_signature_filter, ms);
3803 if (mi_this.Count > 0) {
3804 Report.Error (111, Location, "Class `" + container.Name + "' " +
3805 "already defines a member called `" + Name + "' " +
3806 "with the same parameter types");
3811 if (container is Interface)
3815 if ((ModFlags & Modifiers.READONLY) != 0)
3816 retval = MemberType;
3818 //string report_name;
3819 MethodSignature base_ms;
3822 if (this is Indexer) {
3823 string name, base_name;
3825 report_name = "this";
3826 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
3827 ms = new MethodSignature (name, null, ParameterTypes);
3828 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
3829 base_ms = new MethodSignature (base_name, retval, ParameterTypes);
3831 //report_name = Name;
3832 ms = base_ms = new MethodSignature (Name, retval, ParameterTypes);
3836 // Verify if the parent has a type with the same name, and then
3837 // check whether we have to create a new slot for it or not.
3839 Type ptype = container.TypeBuilder.BaseType;
3841 MemberInfo parent_member = null;
3842 MemberList mi, mi_static, mi_instance;
3845 // Find properties with the same name on the base class
3847 mi_static = TypeContainer.FindMembers (
3848 ptype, MemberTypes.Property,
3849 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3850 MethodSignature.inheritable_property_signature_filter, base_ms);
3852 mi_instance = TypeContainer.FindMembers (
3853 ptype, MemberTypes.Property,
3854 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3855 MethodSignature.inheritable_property_signature_filter,
3858 if (mi_instance.Count > 0)
3860 else if (mi_static.Count > 0)
3865 if (mi != null && mi.Count > 0)
3866 parent_member = (PropertyInfo) mi [0];
3867 if (parent_member is PropertyInfo) {
3868 PropertyInfo parent_property = (PropertyInfo)parent_member;
3870 string name = parent_property.DeclaringType.Name + "." +
3871 parent_property.Name;
3873 MethodInfo get, set, parent_method;
3874 get = parent_property.GetGetMethod (true);
3875 set = parent_property.GetSetMethod (true);
3878 parent_method = get;
3879 else if (set != null)
3880 parent_method = set;
3882 throw new Exception ("Internal error!");
3884 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
3887 if ((ModFlags & Modifiers.NEW) == 0) {
3888 Type parent_type = TypeManager.TypeToCoreType (
3889 parent_property.PropertyType);
3891 if (parent_type != MemberType) {
3893 508, Location, container.MakeName (Name) + ": cannot " +
3894 "change return type when overriding " +
3895 "inherited member " + name);
3899 } else if (parent_member == null) {
3900 /*if ((ModFlags & Modifiers.NEW) != 0)
3901 WarningNotHiding (container);
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 (((ModFlags & Modifiers.DEFAULT) != 0) && (Parameters == null || Parameters.CountStandardParams () == 0)) {
3982 Report.Error (31048, Location, "Properties with no required " +
3983 "parameters cannot be declared 'Default'");
3987 if (!DoDefine (parent))
3990 if (!CheckBase (parent))
3993 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3995 if (GetMethod == null) {
3996 if ((ModFlags & Modifiers.WRITEONLY) == 0)
3999 "Property without 'Get' accessor must have a 'WriteOnly' modifier");
4001 GetBuilder = GetMethod.Define (parent);
4003 if (SetMethod== null) {
4004 if ((ModFlags & Modifiers.READONLY) == 0)
4007 "Property without 'Set' accessor must have a 'ReadOnly' modifier");
4011 SetBuilder = SetMethod.Define (parent);
4013 // FIXME - PropertyAttributes.HasDefault ?
4015 PropertyAttributes prop_attr =
4016 PropertyAttributes.RTSpecialName |
4017 PropertyAttributes.SpecialName;
4019 if (!IsExplicitImpl){
4020 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4021 Name, prop_attr, MemberType, null);
4023 PropertyBuilder.SetGetMethod (GetBuilder);
4024 PropertyBuilder.SetSetMethod (SetBuilder);
4027 // HACK for the reasons exposed above
4029 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4032 "Class `" + parent.Name +
4033 "' already contains a definition for the property `" +
4041 public void Emit (TypeContainer tc)
4044 // The PropertyBuilder can be null for explicit implementations, in that
4045 // case, we do not actually emit the ".property", so there is nowhere to
4046 // put the attribute
4049 if (PropertyBuilder != null && OptAttributes != null)
4050 OptAttributes.Emit (ec, this);
4052 if (GetMethod != null)
4054 GetMethod.Emit (tc);
4057 if (SetMethod != null)
4059 SetMethod.Emit (tc);
4063 public MethodAttributes MethodAttributeFlags {
4072 /// Gigantic workaround for lameness in SRE follows :
4073 /// This class derives from EventInfo and attempts to basically
4074 /// wrap around the EventBuilder so that FindMembers can quickly
4075 /// return this in it search for members
4077 public class MyEventBuilder : EventInfo {
4080 // We use this to "point" to our Builder which is
4081 // not really a MemberInfo
4083 EventBuilder MyBuilder;
4086 // We "catch" and wrap these methods
4088 MethodInfo raise, remove, add;
4090 EventAttributes attributes;
4091 Type declaring_type, reflected_type, event_type;
4094 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4096 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4098 // And now store the values in our own fields.
4100 declaring_type = type_builder;
4102 reflected_type = type_builder;
4104 attributes = event_attr;
4106 this.event_type = event_type;
4110 // Methods that you have to override. Note that you only need
4111 // to "implement" the variants that take the argument (those are
4112 // the "abstract" methods, the others (GetAddMethod()) are
4115 public override MethodInfo GetAddMethod (bool nonPublic)
4120 public override MethodInfo GetRemoveMethod (bool nonPublic)
4125 public override MethodInfo GetRaiseMethod (bool nonPublic)
4131 // These methods make "MyEventInfo" look like a Builder
4133 public void SetRaiseMethod (MethodBuilder raiseMethod)
4135 raise = raiseMethod;
4136 MyBuilder.SetRaiseMethod (raiseMethod);
4139 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4141 remove = removeMethod;
4142 MyBuilder.SetRemoveOnMethod (removeMethod);
4145 public void SetAddOnMethod (MethodBuilder addMethod)
4148 MyBuilder.SetAddOnMethod (addMethod);
4151 public void SetCustomAttribute (CustomAttributeBuilder cb)
4153 MyBuilder.SetCustomAttribute (cb);
4156 public override object [] GetCustomAttributes (bool inherit)
4158 // FIXME : There's nothing which can be seemingly done here because
4159 // we have no way of getting at the custom attribute objects of the
4164 public override object [] GetCustomAttributes (Type t, bool inherit)
4166 // FIXME : Same here !
4170 public override bool IsDefined (Type t, bool b)
4175 public override EventAttributes Attributes {
4181 public override string Name {
4187 public override Type DeclaringType {
4189 return declaring_type;
4193 public override Type ReflectedType {
4195 return reflected_type;
4199 public Type EventType {
4207 public class AddDelegateMethod {
4208 MethodBuilder AddBuilder;
4213 public AddDelegateMethod (Event parent_event, Location loc)
4215 this.parent_event = parent_event;
4219 public MethodBuilder Define (TypeContainer parent)
4221 Type [] parameter_types = new Type [1];
4222 parameter_types [0] = parent_event.MemberType;
4224 Parameter [] parms = new Parameter [1];
4225 parms [0] = new Parameter (parent_event.Type, /* was "value" */ parent_event.Name, Parameter.Modifier.NONE, null);
4226 InternalParameters ip = new InternalParameters (
4227 parent, new Parameters (parms, null, Location));
4229 AddData = new MethodData (parent_event, "add", TypeManager.void_type,
4230 parameter_types, ip, CallingConventions.Standard, null,
4231 parent_event.ModFlags, parent_event.MethodAttributeFlags, false);
4233 if (!AddData.Define (parent))
4236 AddBuilder = AddData.MethodBuilder;
4237 AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ parent_event.Name);
4244 public void Emit (TypeContainer tc)
4246 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4247 EmitContext ec = new EmitContext (tc, Location, ig, TypeManager.void_type, parent_event.ModFlags);
4248 parent_event.EmitDefaultMethod (ec, true);
4252 public class RemoveDelegateMethod {
4253 MethodBuilder RemoveBuilder;
4254 MethodData RemoveData;
4258 public RemoveDelegateMethod (Event parent_event, Location loc)
4260 this.parent_event = parent_event;
4264 public MethodBuilder Define (TypeContainer parent)
4266 //EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4268 Type [] parameter_types = new Type [1];
4269 parameter_types [0] = parent_event.MemberType;
4271 Parameter [] parms = new Parameter [1];
4272 parms [0] = new Parameter (parent_event.Type, /* was "value" */ parent_event.Name, Parameter.Modifier.NONE, null);
4273 InternalParameters ip = new InternalParameters (
4274 parent, new Parameters (parms, null, Location));
4277 RemoveData = new MethodData (parent_event, "remove", TypeManager.void_type,
4278 parameter_types, ip, CallingConventions.Standard, null,
4279 parent_event.ModFlags, parent_event.MethodAttributeFlags, false);
4281 if (!RemoveData.Define (parent))
4284 RemoveBuilder = RemoveData.MethodBuilder;
4285 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ parent_event.Name);
4287 return RemoveBuilder;
4290 public void Emit (TypeContainer tc)
4292 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4293 EmitContext ec = new EmitContext (tc, Location, ig, TypeManager.void_type, parent_event.ModFlags);
4294 parent_event.EmitDefaultMethod (ec, false);
4298 public class Event : FieldBase {
4299 const int AllowedModifiers =
4302 Modifiers.PROTECTED |
4303 Modifiers.INTERNAL |
4308 Modifiers.OVERRIDE |
4312 public readonly AddDelegateMethod Add;
4313 public readonly RemoveDelegateMethod Remove;
4314 public MyEventBuilder EventBuilder;
4316 MethodBuilder AddBuilder, RemoveBuilder;
4318 public Event (Expression type, string name, Object init, int mod, Attributes attrs, Location loc)
4319 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4321 Add = new AddDelegateMethod (this, loc);
4322 Remove = new RemoveDelegateMethod (this, loc);
4327 public Event (Expression type, string name, Object init, int mod, Attributes attrs, ArrayList impl_what, Location loc)
4328 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4330 Add = new AddDelegateMethod (this, loc);
4331 Remove = new RemoveDelegateMethod (this, loc);
4333 Implements = impl_what;
4336 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4338 EventBuilder.SetCustomAttribute (cb);
4341 public override AttributeTargets AttributeTargets {
4343 return AttributeTargets.Event;
4347 public override bool Define (TypeContainer parent)
4349 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4351 if (!DoDefine (parent))
4354 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4355 Report.Error (31044, Location, "'" + parent.Name + "." + Name +
4356 "' : event must be of a delegate type");
4360 Type [] parameter_types = new Type [1];
4361 parameter_types [0] = MemberType;
4363 Parameter [] parms = new Parameter [1];
4364 parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4365 /*InternalParameters ip = new InternalParameters (
4366 parent, new Parameters (parms, null, Location));
4369 if (!CheckBase (parent))
4372 AddBuilder = Add.Define (parent);
4373 RemoveBuilder = Remove.Define (parent);
4376 if (!IsExplicitImpl){
4377 EventBuilder = new MyEventBuilder (
4378 parent.TypeBuilder, Name, e_attr, MemberType);
4380 FieldBuilder = parent.TypeBuilder.DefineField (Name, MemberType,
4381 FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4382 TypeManager.RegisterPrivateFieldOfEvent ((EventInfo) EventBuilder, FieldBuilder);
4383 TypeManager.RegisterFieldBase (FieldBuilder, this);
4385 EventBuilder.SetAddOnMethod (AddBuilder);
4386 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4388 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4389 Report.Error (111, Location,
4390 "Class `" + parent.Name +
4391 "' already contains a definition for the event `" +
4400 public void EmitDefaultMethod (EmitContext ec, bool is_add)
4402 ILGenerator ig = ec.ig;
4403 MethodInfo method = null;
4406 method = TypeManager.delegate_combine_delegate_delegate;
4408 method = TypeManager.delegate_remove_delegate_delegate;
4410 if ((ModFlags & Modifiers.STATIC) != 0) {
4411 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4412 ig.Emit (OpCodes.Ldarg_0);
4413 ig.Emit (OpCodes.Call, method);
4414 ig.Emit (OpCodes.Castclass, MemberType);
4415 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4417 ig.Emit (OpCodes.Ldarg_0);
4418 ig.Emit (OpCodes.Ldarg_0);
4419 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4420 ig.Emit (OpCodes.Ldarg_1);
4421 ig.Emit (OpCodes.Call, method);
4422 ig.Emit (OpCodes.Castclass, MemberType);
4423 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4425 ig.Emit (OpCodes.Ret);
4428 public void Emit (TypeContainer tc)
4432 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4434 if (OptAttributes != null)
4435 OptAttributes.Emit (ec, this);
4441 public MethodAttributes MethodAttributeFlags {
4449 struct MethodSignature {
4451 public Type RetType;
4452 public Type [] Parameters;
4455 /// This delegate is used to extract methods which have the
4456 /// same signature as the argument
4458 public static MemberFilter method_signature_filter;
4461 /// This delegate is used to extract methods which have the
4462 /// same signature as the argument except for the name
4464 public static MemberFilter method_signature_noname_filter;
4467 /// This delegate is used to extract inheritable methods which
4468 /// have the same signature as the argument. By inheritable,
4469 /// this means that we have permissions to override the method
4470 /// from the current assembly and class
4472 public static MemberFilter inheritable_method_signature_filter;
4475 /// This delegate is used to extract inheritable methods which
4476 /// have the same signature as the argument. By inheritable,
4477 /// this means that we have permissions to override the method
4478 /// from the current assembly and class
4480 public static MemberFilter inheritable_property_signature_filter;
4482 static MethodSignature ()
4484 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4485 method_signature_noname_filter = new MemberFilter (MemberSignatureCompareNoName);
4486 inheritable_method_signature_filter = new MemberFilter (
4487 InheritableMemberSignatureCompare);
4488 inheritable_property_signature_filter = new MemberFilter (
4489 InheritablePropertySignatureCompare);
4492 public MethodSignature (string name, Type ret_type, Type [] parameters)
4497 if (parameters == null)
4498 Parameters = TypeManager.NoTypes;
4500 Parameters = parameters;
4503 public override int GetHashCode ()
4505 return Name.GetHashCode ();
4508 public override bool Equals (Object o)
4510 MethodSignature other = (MethodSignature) o;
4512 if (other.Name != Name)
4515 if (other.RetType != RetType)
4518 if (Parameters == null){
4519 if (other.Parameters == null)
4524 if (other.Parameters == null)
4527 int c = Parameters.Length;
4528 if (other.Parameters.Length != c)
4531 for (int i = 0; i < c; i++)
4532 if (other.Parameters [i] != Parameters [i])
4538 static bool MemberSignatureCompareNoName (MemberInfo m, object filter_criteria)
4540 return MemberSignatureCompare (m, filter_criteria, false);
4543 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4545 return MemberSignatureCompare (m, filter_criteria, true);
4548 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria, bool use_name)
4550 MethodSignature sig = (MethodSignature) filter_criteria;
4552 if (use_name && (m.Name != sig.Name))
4556 MethodInfo mi = m as MethodInfo;
4557 PropertyInfo pi = m as PropertyInfo;
4560 ReturnType = mi.ReturnType;
4561 else if (pi != null)
4562 ReturnType = pi.PropertyType;
4567 // we use sig.RetType == null to mean `do not check the
4568 // method return value.
4570 if (sig.RetType != null)
4571 if (ReturnType != sig.RetType)
4576 args = TypeManager.GetArgumentTypes (mi);
4578 args = TypeManager.GetArgumentTypes (pi);
4580 Type [] sigp = sig.Parameters;
4582 if (args.Length != sigp.Length)
4585 for (int i = args.Length; i > 0; ){
4587 if (args [i] != sigp [i])
4594 // This filter should be used when we are requesting methods that
4595 // we want to override.
4597 // This makes a number of assumptions, for example
4598 // that the methods being extracted are of a parent
4599 // class (this means we know implicitly that we are
4600 // being called to find out about members by a derived
4603 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4605 if (MemberSignatureCompare (m, filter_criteria)){
4606 MethodInfo mi = (MethodInfo) m;
4607 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4609 // If only accessible to the current class.
4610 if (prot == MethodAttributes.Private)
4613 // If only accessible to the defining assembly or
4614 if (prot == MethodAttributes.FamANDAssem ||
4615 prot == MethodAttributes.Assembly){
4616 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4622 // Anything else (FamOrAssembly and Public) is fine
4629 // This filter should be used when we are requesting properties that
4630 // we want to override.
4632 // This makes a number of assumptions, for example
4633 // that the methods being extracted are of a parent
4634 // class (this means we know implicitly that we are
4635 // being called to find out about members by a derived
4638 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4640 if (MemberSignatureCompare (m, filter_criteria)){
4641 PropertyInfo pi = (PropertyInfo) m;
4643 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4644 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4646 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4648 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4650 // If only accessible to the current class.
4651 if (prot == MethodAttributes.Private)
4654 // If only accessible to the defining assembly or
4655 if (prot == MethodAttributes.FamANDAssem ||
4656 prot == MethodAttributes.Assembly){
4657 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4663 // Anything else (FamOrAssembly and Public) is fine