3 // class.cs: Class and Struct handlers
5 // Authors: Miguel de Icaza (miguel@gnu.org)
6 // Martin Baulig (martin@gnome.org)
7 // Anirban Bhattacharjee (banirban@novell.com)
9 // Licensed under the terms of the GNU GPL
11 // (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
14 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
16 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
17 // have fixed a remaining problem: not every AddXXXX was adding a
18 // fully qualified name.
20 // Now everyone registers a fully qualified name in the DeclSpace as
21 // being defined instead of the partial name.
23 // Downsides: we are slower than we need to be due to the excess
24 // copies and the names being registered this way.
26 // The reason for this is that we currently depend (on the corlib
27 // bootstrap for instance) that types are fully qualified, because
28 // we dump all the types in the namespace, and we should really have
29 // types inserted into the proper namespace, so we can only store the
30 // basenames in the defined_names array.
35 using System.Collections;
36 using System.Reflection;
37 using System.Reflection.Emit;
38 using System.Runtime.CompilerServices;
39 using System.Diagnostics.SymbolStore;
41 namespace Mono.MonoBASIC {
44 /// This is the base class for structs and classes.
46 public class TypeContainer : DeclSpace, IMemberContainer {
47 // Holds a list of classes and structures
50 // Holds the list of properties
53 // Holds the list of enumerations
56 // Holds the list of delegates
59 // Holds the list of constructors
60 ArrayList instance_constructors;
62 // Holds the list of fields
65 // Holds a list of fields that have initializers
66 ArrayList initialized_fields;
68 // Holds a list of static fields that have initializers
69 ArrayList initialized_static_fields;
71 // Holds the list of constants
77 // Holds order in which interfaces must be closed
78 ArrayList interface_order;
86 // Holds AddHandlers stements for events
89 // The emit context for toplevel objects.
93 // Pointers to the default constructor and the default static constructor
95 Constructor default_constructor;
96 Constructor default_static_constructor;
99 // Whether we have seen a static constructor for this class or not
101 bool have_static_constructor = false;
104 // Whether we have at least one non-static field
106 bool have_nonstatic_fields = false;
109 // This one is computed after we can distinguish interfaces
110 // from classes from the arraylist `type_bases'
112 string base_class_name;
113 public Type base_class_type;
115 ArrayList type_bases;
117 // Information in the case we are an attribute type
119 AttributeUsageAttribute attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
121 public AttributeUsageAttribute AttributeUsage {
123 return attribute_usage;
127 attribute_usage = value;
131 // The interfaces we implement.
134 // The parent member container and our member cache
135 IMemberContainer parent_container;
136 MemberCache member_cache;
139 // The indexer name for this class
141 public string DefaultPropName;
143 public TypeContainer (TypeContainer parent, string name, Attributes attrs, Location l)
144 : base (parent, name, attrs, l)
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;
259 if (basename == Basename)
260 return AdditionResult.EnclosingClash;
263 methods = new ArrayList ();
265 if (method.Name.IndexOf (".") != -1)
266 methods.Insert (0, method);
268 methods.Add (method);
271 DefineName (fullname, method);
273 return AdditionResult.Success;
276 public AdditionResult AddConstructor (Constructor c)
279 return AdditionResult.NotAConstructor;
281 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
284 have_static_constructor = true;
285 if (default_static_constructor != null){
286 Console.WriteLine ("I have a static constructor already");
287 Console.WriteLine (" " + default_static_constructor);
288 return AdditionResult.MethodExists;
291 default_static_constructor = c;
294 /*if (default_constructor != null)
295 return AdditionResult.MethodExists;*/
296 default_constructor = c;
299 if (instance_constructors == null)
300 instance_constructors = new ArrayList ();
302 instance_constructors.Add (c);
305 return AdditionResult.Success;
308 public AdditionResult AddInterface (Interface iface)
312 if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
315 if (interfaces == null)
316 interfaces = new ArrayList ();
317 interfaces.Add (iface);
318 DefineName (iface.Name, iface);
320 return AdditionResult.Success;
323 public AdditionResult AddField (Field field)
326 string basename = field.Name;
328 if ((res = IsValid (basename)) != AdditionResult.Success)
332 fields = new ArrayList ();
336 if (field.HasInitializer){
337 if ((field.ModFlags & Modifiers.STATIC) != 0) {
338 if (initialized_static_fields == null)
339 initialized_static_fields = new ArrayList ();
341 initialized_static_fields.Add (field);
344 // We have not seen a static constructor,
345 // but we will provide static initialization of fields
347 have_static_constructor = true;
349 if (initialized_fields == null)
350 initialized_fields = new ArrayList ();
352 initialized_fields.Add (field);
356 if ((field.ModFlags & Modifiers.STATIC) == 0)
357 have_nonstatic_fields = true;
359 DefineName (Name + "." + basename, field);
360 return AdditionResult.Success;
363 public AdditionResult AddProperty (Property prop)
366 string basename = prop.Name;
368 string fullname = Name + "." + basename;
370 Object value = defined_names [fullname];
372 if (value != null && (!(value is Property)))
373 return AdditionResult.NameExists;
375 if ((res = IsValid (basename)) != AdditionResult.Success)
378 if (properties == null)
379 properties = new ArrayList ();
381 if (prop.Name.IndexOf (".") != -1)
382 properties.Insert (0, prop);
384 properties.Add (prop);
387 DefineName (Name + "." + basename, prop);
389 return AdditionResult.Success;
392 public AdditionResult AddEvent (Event e)
395 string basename = e.Name;
397 if ((res = IsValid (basename)) != AdditionResult.Success)
401 events = new ArrayList ();
404 DefineName (Name + "." + basename, e);
406 return AdditionResult.Success;
409 public AdditionResult AddEventHandler (Statement stmt)
411 if (handlers == null)
412 handlers = new ArrayList ();
415 return AdditionResult.Success;
418 public void RegisterOrder (Interface iface)
420 if (interface_order == null)
421 interface_order = new ArrayList ();
423 interface_order.Add (iface);
425 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
427 base.ApplyAttributeBuilder (a, cb);
430 public override AttributeTargets AttributeTargets {
432 throw new NotSupportedException ();
436 public ArrayList Types {
442 public ArrayList Methods {
448 public ArrayList Constants {
454 public ArrayList Interfaces {
462 return base_class_name;
466 public ArrayList Bases {
476 public ArrayList Fields {
486 public ArrayList InstanceConstructors {
488 return instance_constructors;
492 public ArrayList Properties {
498 public ArrayList Events {
504 public ArrayList Enums {
510 public ArrayList Delegates {
516 public bool HaveStaticConstructor {
518 return have_static_constructor;
522 public virtual TypeAttributes TypeAttr {
524 return Modifiers.TypeAttr (ModFlags, this);
528 public ArrayList EventHandlers {
535 // Emits the instance field initializers
537 public bool EmitFieldInitializers (EmitContext ec)
540 //ILGenerator ig = ec.ig;
541 Expression instance_expr;
544 fields = initialized_static_fields;
545 instance_expr = null;
547 fields = initialized_fields;
548 instance_expr = new This (Location.Null).Resolve (ec);
554 foreach (Field f in fields){
555 Expression e = f.GetInitializerExpression (ec);
559 Location l = f.Location;
560 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
561 fe.InstanceExpression = instance_expr;
562 Expression a = new Assign (fe, e, l);
568 if (a is ExpressionStatement)
569 ((ExpressionStatement) a).EmitStatement (ec);
571 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
579 // Defines the default constructors
581 void DefineDefaultConstructor (bool is_static)
586 c = new Constructor ("New", Parameters.EmptyReadOnlyParameters,
591 mods = Modifiers.STATIC;
595 c.Initializer = new ConstructorBaseInitializer (
596 null, Parameters.EmptyReadOnlyParameters,
601 c.Block = new Block (null);
605 public void ReportStructInitializedInstanceError ()
607 string n = TypeBuilder.FullName;
609 foreach (Field f in initialized_fields){
612 "`" + n + "." + f.Name + "': can not have " +
613 "instance field initializers in structs");
618 /// The pending methods that need to be implemented (interfaces or abstract methods)
620 public PendingImplementation Pending;
623 /// This function computes the Base class and also the
624 /// list of interfaces that the class or struct @c implements.
626 /// The return value is an array (might be null) of
627 /// interfaces implemented (as Types).
629 /// The @parent argument is set to the parent object or null
630 /// if this is `System.Object'.
632 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
634 ArrayList bases = Bases;
643 parent = TypeManager.value_type;
647 if (RootContext.StdLib)
648 parent = TypeManager.object_type;
649 else if (Name != "System.Object")
650 parent = TypeManager.object_type;
653 // If we are compiling our runtime,
654 // and we are defining ValueType, then our
655 // parent is `System.Object'.
657 if (!RootContext.StdLib && Name == "System.ValueType")
658 parent = TypeManager.object_type;
665 // Bases should be null if there are no bases at all
669 if (is_class && (!(this is Interface))){
670 Expression name = (Expression) bases [0];
671 name = ResolveTypeExpr (name, false, Location);
678 Type first = name.Type;
684 parent = TypeManager.object_type;
688 if (parent.IsSealed )
689 Report.Error (30299, Location,
690 "Class " + Name + " cannot inherit " +
691 "'NotInheritable' class " + TypeManager.MonoBASIC_Name (parent));
693 if (!AsAccessible (parent, ModFlags))
694 Report.Error (30389, Location,
695 "Inconsistent accessibility: base class `" +
696 TypeManager.MonoBASIC_Name (parent) + "' is less " +
697 "accessible than class `" +
704 Type [] ifaces = new Type [count-start];
706 for (i = start, j = 0; i < count; i++, j++){
707 Expression name = (Expression) bases [i];
708 Expression resolved = ResolveTypeExpr (name, false, Location);
709 bases [i] = resolved;
710 Type t = resolved.Type;
716 if (is_class == false && !t.IsInterface){
717 Report.Error (527, Location, "In Struct `" + Name + "', type `"+
718 name +"' is not an interface");
725 Report.Error (30258, Location, "class `"+ Name +
726 "': a class can not inherit from a struct/enum");
728 /*Report.Error (509, Location, "class `"+ Name +
729 "': Cannot inherit from sealed class `"+
737 Report.Error (30121, Location, Name + ": A class cannot inherit " +
738 "more than one class");
744 for (int x = 0; x < j; x++) {
745 if (t == ifaces [x]) {
746 Report.Error (528,Location, "`" + name + "' is already listed in interface list");
759 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
761 public override TypeBuilder DefineType ()
766 if (TypeBuilder != null)
779 ec = new EmitContext (this, Mono.MonoBASIC.Location.Null, null, null, ModFlags);
781 if (((ModFlags & Modifiers.ABSTRACT ) != 0) &&
782 ((ModFlags & Modifiers.SEALED) != 0)){
783 Report.Error (31408, Location,
784 "Class declared as 'MustInherit' cannot be declared as 'NotInheritable'");
787 ifaces = GetClassBases (is_class, out base_class_type, out error);
791 if (this is Interface)
792 base_class_type = null;
794 if (is_class && base_class_type != null){
795 if (base_class_type == TypeManager.enum_type ||
796 (base_class_type == TypeManager.value_type && RootContext.StdLib) ||
797 base_class_type == TypeManager.delegate_type ||
798 base_class_type == TypeManager.array_type){
800 644, Location, "`" + Name + "' cannot inherit from " +
801 "special class `" + TypeManager.MonoBASIC_Name (base_class_type) + "'");
806 if (!is_class && TypeManager.value_type == null)
807 throw new Exception ();
809 if (is_class && Parent.Parent == null && (!(this is Interface)))
811 if ((ModFlags & Modifiers.PRIVATE) != 0)
812 Report.Error (31089, Location,
813 "Only internal classes can be declared as 'Private'");
815 if ((ModFlags & Modifiers.PROTECTED) != 0)
816 Report.Error (31047, Location,
817 "Only internal classes can be declared as 'Protected'");
820 if ((Parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
821 Report.Error (30735, Location,
822 "'Type' inside a 'Module' can not be " +
823 "declared as 'Protected'");
825 if ((Parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
826 Report.Error (30435, Location,
827 "'Type' inside a 'Structure' can not be " +
828 "declared as 'Protected'");
830 TypeAttributes type_attributes = TypeAttr;
833 ModuleBuilder builder = CodeGen.ModuleBuilder;
834 TypeBuilder = builder.DefineType (
835 Name, type_attributes, base_class_type, ifaces);
838 TypeBuilder builder = Parent.TypeBuilder;
839 TypeBuilder = builder.DefineNestedType (
840 Basename, type_attributes, base_class_type, ifaces);
845 // structure must contain atleast one member variable
846 if(!have_nonstatic_fields){
848 30281, Location, "Structure `" + Name + "' do not " +
849 "contain any member Variable");
851 /*TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
852 FieldAttributes.Private);*/
855 // add interfaces that were not added at type creation (weird API issue)
856 if (!have_nonstatic_fields && (ifaces != null)) {
857 foreach (Type i in ifaces)
858 TypeBuilder.AddInterfaceImplementation (i);
864 // Finish the setup for the EmitContext
866 ec.ContainerType = TypeBuilder;
868 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
870 if ((base_class_type != null) &&
871 (base_class_type == TypeManager.attribute_type ||
872 base_class_type.IsSubclassOf (TypeManager.attribute_type))) {
873 RootContext.RegisterAttribute (this);
875 RootContext.RegisterOrder (this);
877 if (Interfaces != null) {
878 foreach (Interface iface in Interfaces)
883 foreach (TypeContainer tc in Types)
887 if (Delegates != null) {
888 foreach (Delegate d in Delegates)
893 foreach (Enum en in Enums)
903 /// Defines the MemberCore objects that are in the `list' Arraylist
905 /// The `defined_names' array contains a list of members defined in
908 static ArrayList remove_list = new ArrayList ();
909 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
913 // if one of the overloaded method is having
914 // Shadows or Overloads modifier all other should
915 // have the same modifier
916 Hashtable members = new Hashtable();
918 foreach (MemberCore mc in list)
921 if(members[mc.Name] == null)
923 foreach (MemberCore m in list)
925 if(m.Name == mc.Name)
927 if ((m.ModFlags & Modifiers.SHADOWS) != 0)
929 modval = Modifiers.SHADOWS;
932 else if((m.ModFlags & Modifiers.NEW) != 0)
934 modval = Modifiers.NEW;
938 members.Add(mc.Name, modval);
941 modval = (int)members[mc.Name];
944 if(((modval & Modifiers.SHADOWS) != 0) && ((mc.ModFlags & Modifiers.SHADOWS) == 0))
947 "Function '" + mc.Name + "': must be declared 'Shadows' " +
948 "because another '" + mc.Name + "' declared 'Shadows'");
949 else if(((modval & Modifiers.NEW) != 0) && ((mc.ModFlags & Modifiers.NEW) == 0))
952 "Function '" + mc.Name + "': must be declared 'Overloads' " +
953 "because another '" + mc.Name + "' declared 'Overloads'");
957 remove_list.Clear ();
959 foreach (MemberCore mc in list){
960 if (!mc.Define (this)){
961 remove_list.Add (mc);
965 if (defined_names == null)
968 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
970 if (RootContext.WarningLevel >= 4){
971 if ((mc.ModFlags & Modifiers.NEW) != 0)
972 Warning_KewywordNewNotRequired (mc.Location, mc);
973 if ((mc.ModFlags & Modifiers.SHADOWS) != 0)
974 Warning_KewywordShadowsNotRequired (mc.Location, mc);
979 MemberInfo match = defined_names [idx];
981 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
985 // If we are both methods, let the method resolution emit warnings
987 if (match is MethodBase && mc is MethodCore)
990 if (((mc.ModFlags & Modifiers.SHADOWS) == 0) && idx > 0)
991 Warning_KeywordShadowsRequired (mc.Location, defined_names [idx]);
995 foreach (object o in remove_list)
998 remove_list.Clear ();
1001 static void Error_KeywordNotAllowed (Location loc)
1003 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1007 /// Populates our TypeBuilder with fields and methods
1009 public override bool DefineMembers (TypeContainer parent)
1011 MemberInfo [] defined_names = null;
1013 if (interface_order != null){
1014 foreach (Interface iface in interface_order)
1015 if ((iface.ModFlags & Modifiers.NEW) == 0)
1016 iface.DefineMembers (this);
1018 Error_KeywordNotAllowed (iface.Location);
1021 if (RootContext.WarningLevel > 1){
1025 // This code throws an exception in the comparer
1026 // I guess the string is not an object?
1028 ptype = TypeBuilder.BaseType;
1030 defined_names = (MemberInfo []) FindMembers (
1031 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1032 BindingFlags.Public | BindingFlags.Instance |
1033 BindingFlags.Static, null, null);
1035 Array.Sort (defined_names, mif_compare);
1039 if (constants != null)
1040 DefineMembers (constants, defined_names);
1043 DefineMembers (fields, defined_names);
1045 if (this is Class && (!(this is Interface))){
1046 if (instance_constructors == null){
1047 if (default_constructor == null)
1048 DefineDefaultConstructor (false);
1051 if (initialized_static_fields != null &&
1052 default_static_constructor == null)
1053 DefineDefaultConstructor (true);
1056 if (this is Struct){
1058 // Structs can not have initialized instance
1061 if (initialized_static_fields != null &&
1062 default_static_constructor == null)
1063 DefineDefaultConstructor (true);
1065 if (initialized_fields != null)
1066 ReportStructInitializedInstanceError ();
1069 if (!(this is Interface))
1070 Pending = PendingImplementation.GetPendingImplementations (this);
1072 // Constructors are not in the defined_names array
1074 if (instance_constructors != null)
1075 DefineMembers (instance_constructors, null);
1077 if (default_static_constructor != null)
1078 default_static_constructor.Define (this);
1080 if (methods != null)
1081 DefineMembers (methods, defined_names);
1083 if (properties != null)
1084 DefineMembers (properties, defined_names);
1087 DefineMembers (events, defined_names);
1090 DefineMembers (enums, defined_names);
1092 if (delegates != null)
1093 DefineMembers (delegates, defined_names);
1096 if (TypeBuilder.BaseType != null)
1097 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1099 member_cache = new MemberCache (this);
1105 public override bool Define (TypeContainer parent)
1107 if (interface_order != null){
1108 foreach (Interface iface in interface_order)
1109 if ((iface.ModFlags & Modifiers.NEW) == 0)
1110 iface.Define (this);
1117 /// This function is based by a delegate to the FindMembers routine
1119 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1125 /// This filter is used by FindMembers, and we just keep
1126 /// a global for the filter to `AlwaysAccept'
1128 static MemberFilter accepting_filter;
1132 /// A member comparission method based on name only
1134 static IComparer mif_compare;
1136 static TypeContainer ()
1138 accepting_filter = new MemberFilter (AlwaysAccept);
1139 mif_compare = new MemberInfoCompare ();
1143 /// This method returns the members of this type just like Type.FindMembers would
1144 /// Only, we need to use this for types which are _being_ defined because MS'
1145 /// implementation can't take care of that.
1148 // FIXME: return an empty static array instead of null, that cleans up
1149 // some code and is consistent with some coding conventions I just found
1153 // Notice that in various cases we check if our field is non-null,
1154 // something that would normally mean that there was a bug elsewhere.
1156 // The problem happens while we are defining p-invoke methods, as those
1157 // will trigger a FindMembers, but this happens before things are defined
1159 // Since the whole process is a no-op, it is fine to check for null here.
1161 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1162 MemberFilter filter, object criteria)
1164 ArrayList members = new ArrayList ();
1167 if ((bf & BindingFlags.Public) != 0)
1168 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1170 if ((bf & BindingFlags.NonPublic) != 0)
1171 modflags |= Modifiers.PRIVATE;
1173 int static_mask = 0, static_flags = 0;
1174 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1175 case BindingFlags.Static:
1176 static_mask = static_flags = Modifiers.STATIC;
1179 case BindingFlags.Instance:
1180 static_mask = Modifiers.STATIC;
1185 static_mask = static_flags = 0;
1189 Timer.StartTimer (TimerType.TcFindMembers);
1192 filter = accepting_filter;
1194 if ((mt & MemberTypes.Field) != 0) {
1195 if (fields != null) {
1196 foreach (Field f in fields) {
1197 if ((f.ModFlags & modflags) == 0)
1199 if ((f.ModFlags & static_mask) != static_flags)
1202 FieldBuilder fb = f.FieldBuilder;
1203 if (fb != null && filter (fb, criteria) == true)
1208 if (constants != null) {
1209 foreach (Const con in constants) {
1210 if ((con.ModFlags & modflags) == 0)
1212 if ((con.ModFlags & static_mask) != static_flags)
1215 FieldBuilder fb = con.FieldBuilder;
1216 if (fb != null && filter (fb, criteria) == true)
1222 if ((mt & MemberTypes.Method) != 0) {
1223 if (methods != null) {
1224 foreach (Method m in methods) {
1225 if ((m.ModFlags & modflags) == 0)
1227 if ((m.ModFlags & static_mask) != static_flags)
1230 MethodBuilder mb = m.MethodBuilder;
1232 if (mb != null && filter (mb, criteria) == true)
1237 if (properties != null){
1238 foreach (Property p in properties){
1239 if ((p.ModFlags & modflags) == 0)
1241 if ((p.ModFlags & static_mask) != static_flags)
1247 if (b != null && filter (b, criteria) == true)
1251 if (b != null && filter (b, criteria) == true)
1257 if ((mt & MemberTypes.Event) != 0) {
1259 foreach (Event e in events) {
1260 if ((e.ModFlags & modflags) == 0)
1262 if ((e.ModFlags & static_mask) != static_flags)
1265 MemberInfo eb = e.EventBuilder;
1266 if (eb != null && filter (eb, criteria) == true)
1267 members.Add (e.EventBuilder);
1271 if ((mt & MemberTypes.Property) != 0){
1272 if (properties != null)
1273 foreach (Property p in properties) {
1274 if ((p.ModFlags & modflags) == 0)
1276 if ((p.ModFlags & static_mask) != static_flags)
1279 MemberInfo pb = p.PropertyBuilder;
1281 if (pb != null && filter (pb, criteria) == true)
1282 members.Add (p.PropertyBuilder);
1286 if ((mt & MemberTypes.NestedType) != 0) {
1288 foreach (TypeContainer t in types) {
1289 if ((t.ModFlags & modflags) == 0)
1292 TypeBuilder tb = t.TypeBuilder;
1293 if (tb != null && (filter (tb, criteria) == true))
1299 foreach (Enum en in enums){
1300 if ((en.ModFlags & modflags) == 0)
1303 TypeBuilder tb = en.TypeBuilder;
1304 if (tb != null && (filter (tb, criteria) == true))
1309 if (delegates != null){
1310 foreach (Delegate d in delegates){
1311 if ((d.ModFlags & modflags) == 0)
1314 TypeBuilder tb = d.TypeBuilder;
1315 if (tb != null && (filter (tb, criteria) == true))
1320 if (interfaces != null){
1321 foreach (Interface iface in interfaces){
1322 if ((iface.ModFlags & modflags) == 0)
1325 TypeBuilder tb = iface.TypeBuilder;
1326 if (tb != null && (filter (tb, criteria) == true))
1332 if ((mt & MemberTypes.Constructor) != 0){
1333 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1334 foreach (Constructor c in instance_constructors){
1335 if ((c.ModFlags & modflags) == 0)
1338 ConstructorBuilder cb = c.ConstructorBuilder;
1340 if (filter (cb, criteria) == true)
1345 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null) &&
1346 ((default_static_constructor.ModFlags & modflags) != 0)){
1347 ConstructorBuilder cb =
1348 default_static_constructor.ConstructorBuilder;
1351 if (filter (cb, criteria) == true)
1357 // Lookup members in parent if requested.
1359 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1360 if ((mt & ~MemberTypes.Constructor) != 0) {
1361 MemberList list = FindMembers (TypeBuilder.BaseType, mt & ~MemberTypes.Constructor, bf, filter, criteria);
1362 members.AddRange (list);
1366 Timer.StopTimer (TimerType.TcFindMembers);
1368 return new MemberList (members);
1371 public override MemberCache MemberCache {
1373 return member_cache;
1377 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1378 MemberFilter filter, object criteria)
1380 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1383 return tc.FindMembers (mt, bf, filter, criteria);
1385 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1389 // FindMethods will look for methods not only in the type `t', but in
1390 // any interfaces implemented by the type.
1392 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1393 MemberFilter filter, object criteria)
1399 /// Emits the values for the constants
1401 public void EmitConstants ()
1403 if (constants != null)
1404 foreach (Const con in constants)
1405 con.EmitConstant (this);
1410 /// Emits the code, this step is performed after all
1411 /// the types, enumerations, constructors
1415 if (instance_constructors != null)
1416 foreach (Constructor c in instance_constructors)
1419 if (default_static_constructor != null)
1420 default_static_constructor.Emit (this);
1422 if (methods != null)
1423 foreach (Method m in methods)
1426 if (properties != null)
1427 foreach (Property p in properties)
1430 if (this.DefaultPropName != null) {
1431 CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { DefaultPropName });
1432 TypeBuilder.SetCustomAttribute (cb);
1436 foreach (Field f in fields)
1439 if (events != null){
1440 foreach (Event e in Events)
1444 if (Pending != null)
1445 if (Pending.VerifyPendingMethods ())
1448 if (OptAttributes != null)
1449 OptAttributes.Emit (ec, this);
1452 // Check for internal or private fields that were never assigned
1454 if (fields != null && RootContext.WarningLevel >= 3) {
1455 foreach (Field f in fields) {
1456 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1461 169, f.Location, "Private field " +
1462 MakeName (f.Name) + " is never used");
1467 // Only report 649 on level 4
1469 if (RootContext.WarningLevel < 4)
1472 if ((f.status & Field.Status.ASSIGNED) != 0)
1477 "Field " + MakeName (f.Name) + " is never assigned " +
1478 " to and will always have its default value");
1482 // if (types != null)
1483 // foreach (TypeContainer tc in types)
1487 public override void CloseType ()
1492 TypeBuilder.CreateType ();
1494 } catch (TypeLoadException){
1496 // This is fine, the code still created the type
1498 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1499 // Console.WriteLine (e.Message);
1501 Console.WriteLine ("In type: " + Name);
1506 foreach (Enum en in Enums)
1509 if (interface_order != null){
1510 foreach (Interface iface in interface_order)
1515 foreach (TypeContainer tc in Types)
1519 foreach (TypeContainer tc in Types)
1520 if (!(tc is Struct))
1524 if (Delegates != null)
1525 foreach (Delegate d in Delegates)
1529 public string MakeName (string n)
1531 return "`" + Name + "." + n + "'";
1534 public void Warning_KeywordShadowsRequired (Location l, MemberInfo mi)
1537 108, l, "The keyword 'Shadows' is required on " +
1538 MakeName (mi.Name) + " because it shadows `" +
1539 mi.ReflectedType.Name + "." + mi.Name + "'");
1542 public void Warning_KewywordShadowsNotRequired (Location l, MemberCore mc)
1545 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1546 "inherited member, the keyword shadows is not required");
1549 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1552 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1553 "inherited member, the keyword new is not required");
1556 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1562 // Performs the validation on a Method's modifiers (properties have
1563 // the same properties).
1565 public bool MethodModifiersValid (int flags, string n, Location loc)
1567 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1568 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1569 //const int nv = (Modifiers.SHADOWS | Modifiers.VIRTUAL);
1571 string name = MakeName (n);
1574 // At most one of static, virtual or override
1576 if ((flags & Modifiers.STATIC) != 0){
1577 if ((flags & vao) != 0){
1579 30501, loc, "Shared method " + name + " can not be " +
1580 "declared as Overridable");
1585 if (this is Struct){
1586 if ((flags & va) != 0){
1587 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1592 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.VIRTUAL) != 0)
1596 ": Methods marked as Overrides cannot be made Overridable");
1600 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & Modifiers.SHADOWS) != 0){
1603 ": Methods marked as Overrides cannot be marked as Shadows");
1608 // If the declaration includes the abstract modifier, then the
1609 // declaration does not include static, virtual or extern
1611 if ((flags & Modifiers.ABSTRACT) != 0){
1612 if ((flags & Modifiers.EXTERN) != 0){
1614 180, loc, name + " can not be both abstract and extern");
1618 if ((flags & Modifiers.VIRTUAL) != 0){
1620 503, loc, name + " can not be both abstract and virtual");
1624 if((ModFlags & Modifiers.SEALED) != 0){
1627 "Class declared as 'NotInheritable' " +
1628 "cannot have a 'MustOverride' member");
1631 else if ((ModFlags & Modifiers.ABSTRACT) == 0){
1634 " is declared as 'MustOverride', hence its container " +
1635 "class should be declared as 'MustInherit'");
1641 if ((flags & Modifiers.PRIVATE) != 0){
1642 if ((flags & vao) != 0){
1645 ": Members marked as Overridable or Overrides can not be Private");
1650 if ((flags & Modifiers.SEALED) != 0){
1651 if ((flags & Modifiers.OVERRIDE) == 0){
1654 ": cannot be sealed because it is not an override");
1658 if ((flags & Modifiers.NEW) != 0){
1659 if ((flags & Modifiers.SHADOWS) != 0){
1662 " 'Overloads' and 'Shadows' cannot be combined ");
1670 // Access level of a type.
1673 ProtectedInternal = 1,
1679 // Check whether `flags' denotes a more restricted access than `level'
1680 // and return the new level.
1681 static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
1683 //AccessLevel old_level = level;
1685 if ((flags & Modifiers.INTERNAL) != 0) {
1686 if ((flags & Modifiers.PROTECTED) != 0) {
1687 if ((int) level < (int) AccessLevel.ProtectedInternal)
1688 level = AccessLevel.ProtectedInternal;
1690 if ((int) level < (int) AccessLevel.Internal)
1691 level = AccessLevel.Internal;
1693 } else if ((flags & Modifiers.PROTECTED) != 0) {
1694 if ((int) level < (int) AccessLevel.Protected)
1695 level = AccessLevel.Protected;
1696 } else if ((flags & Modifiers.PRIVATE) != 0)
1697 level = AccessLevel.Private;
1702 // Return the access level for a new member which is defined in the current
1703 // TypeContainer with access modifiers `flags'.
1704 AccessLevel GetAccessLevel (int flags)
1706 if ((flags & Modifiers.PRIVATE) != 0)
1707 return AccessLevel.Private;
1710 if (!IsTopLevel && (Parent != null))
1711 level = Parent.GetAccessLevel (flags);
1713 level = AccessLevel.Public;
1715 return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
1718 // Return the access level for type `t', but don't give more access than `flags'.
1719 static AccessLevel GetAccessLevel (Type t, int flags)
1721 if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
1722 return AccessLevel.Private;
1725 if (TypeManager.IsBuiltinType (t))
1726 return AccessLevel.Public;
1727 else if ((t.DeclaringType != null) && (t != t.DeclaringType))
1728 level = GetAccessLevel (t.DeclaringType, flags);
1730 level = CheckAccessLevel (AccessLevel.Public, flags);
1733 if (t.IsNestedPublic)
1736 if (t.IsNestedAssembly || t.IsNotPublic) {
1737 if ((int) level < (int) AccessLevel.Internal)
1738 level = AccessLevel.Internal;
1741 if (t.IsNestedFamily) {
1742 if ((int) level < (int) AccessLevel.Protected)
1743 level = AccessLevel.Protected;
1746 if (t.IsNestedFamORAssem) {
1747 if ((int) level < (int) AccessLevel.ProtectedInternal)
1748 level = AccessLevel.ProtectedInternal;
1755 // Returns true if `parent' is as accessible as the flags `flags'
1756 // given for this member.
1758 public bool AsAccessible (Type parent, int flags)
1760 while (parent.IsArray || parent.IsPointer || parent.IsByRef)
1761 parent = parent.GetElementType ();
1763 AccessLevel level = GetAccessLevel (flags);
1764 AccessLevel level2 = GetAccessLevel (parent, flags);
1766 return (int) level >= (int) level2;
1769 Hashtable builder_and_args;
1771 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1773 if (builder_and_args == null)
1774 builder_and_args = new Hashtable ();
1779 /// Performs checks for an explicit interface implementation. First it
1780 /// checks whether the `interface_type' is a base inteface implementation.
1781 /// Then it checks whether `name' exists in the interface type.
1783 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1787 if (ifaces != null){
1788 foreach (Type t in ifaces){
1789 if (t == interface_type){
1797 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1804 public static void Error_NotInterfaceMember (Location loc, string member_name, string iface_name)
1806 Report.Error (30401, loc, "'" + member_name + "' is not a member of the interface '" + iface_name + "'");
1813 string IMemberContainer.Name {
1819 Type IMemberContainer.Type {
1825 IMemberContainer IMemberContainer.Parent {
1827 return parent_container;
1831 MemberCache IMemberContainer.MemberCache {
1833 return member_cache;
1837 bool IMemberContainer.IsInterface {
1839 return this is Interface;
1843 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1845 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1850 public class Class : TypeContainer {
1852 // Modifiers allowed in a class declaration
1854 public const int AllowedModifiers =
1857 Modifiers.PROTECTED |
1858 Modifiers.INTERNAL |
1860 Modifiers.ABSTRACT |
1863 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1864 : base (parent, name, attrs, l)
1868 if (parent.Parent == null)
1869 accmods = Modifiers.INTERNAL;
1871 accmods = Modifiers.PUBLIC;
1873 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1876 public override AttributeTargets AttributeTargets {
1878 return AttributeTargets.Class;
1882 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
1884 if (a.UsageAttribute != null) {
1885 if (base_class_type != TypeManager.attribute_type && !base_class_type.IsSubclassOf (TypeManager.attribute_type) &&
1886 TypeBuilder.FullName != "System.Attribute") {
1887 Report.Error (641, a.Location, "Attribute '" + a.Name + "' is only valid on classes derived from System.Attribute");
1889 AttributeUsage = a.UsageAttribute;
1891 base.ApplyAttributeBuilder (a, cb);
1895 // FIXME: How do we deal with the user specifying a different
1898 public override TypeAttributes TypeAttr {
1900 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1905 public class Struct : TypeContainer {
1907 // Modifiers allowed in a struct declaration
1909 public const int AllowedModifiers =
1912 Modifiers.PROTECTED |
1913 Modifiers.INTERNAL |
1917 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1918 : base (parent, name, attrs, l)
1922 if (parent.Parent == null)
1923 accmods = Modifiers.INTERNAL;
1925 accmods = Modifiers.PUBLIC;
1927 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1929 this.ModFlags |= Modifiers.SEALED;
1932 public override AttributeTargets AttributeTargets {
1934 return AttributeTargets.Struct;
1939 // FIXME: Allow the user to specify a different set of attributes
1940 // in some cases (Sealed for example is mandatory for a class,
1941 // but what SequentialLayout can be changed
1943 public override TypeAttributes TypeAttr {
1945 return base.TypeAttr |
1946 TypeAttributes.SequentialLayout |
1947 TypeAttributes.Sealed |
1948 TypeAttributes.BeforeFieldInit;
1953 public abstract class MethodCore : MemberBase {
1954 public /* readonly */ Parameters Parameters;
1958 // Parameters, cached for semantic analysis.
1960 protected InternalParameters parameter_info;
1961 protected Type [] parameter_types;
1963 // Whether this is an operator
1964 public bool IsOperator;
1966 public MethodCore (Expression type, int mod, int allowed_mod, string name,
1967 Attributes attrs, Parameters parameters, Location loc)
1968 : base (type, mod, allowed_mod, name, attrs, loc)
1970 Parameters = parameters;
1974 // Returns the System.Type array for the parameters of this method
1976 public Type [] ParameterTypes {
1978 return parameter_types;
1982 public InternalParameters ParameterInfo
1985 return parameter_info;
1989 public Block Block {
1999 protected virtual bool DoDefineParameters (TypeContainer parent)
2001 // Check if arguments were correct
2002 parameter_types = Parameters.GetParameterInfo (parent);
2003 if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
2006 parameter_info = new InternalParameters (parent, Parameters);
2011 public CallingConventions GetCallingConvention (bool is_class)
2013 CallingConventions cc = 0;
2015 cc = Parameters.GetCallingConvention ();
2018 if ((ModFlags & Modifiers.STATIC) == 0)
2019 cc |= CallingConventions.HasThis;
2021 // FIXME: How is `ExplicitThis' used in C#?
2027 public class Method : MethodCore {
2028 public MethodBuilder MethodBuilder;
2029 public MethodData MethodData;
2032 /// Modifiers allowed in a class declaration
2034 const int AllowedModifiers =
2037 Modifiers.PROTECTED |
2038 Modifiers.INTERNAL |
2042 Modifiers.NONVIRTUAL |
2043 Modifiers.OVERRIDE |
2044 Modifiers.ABSTRACT |
2050 // return_type can be "null" for VOID values.
2052 public Method (Expression return_type, int mod, string name, Parameters parameters,
2053 Attributes attrs, Location l)
2054 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2059 public Method (Expression return_type, int mod, string name, Parameters parameters,
2060 Attributes attrs, ArrayList impl_what, Location l)
2061 : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2063 Implements = impl_what;
2066 public override AttributeTargets AttributeTargets {
2068 return AttributeTargets.Method;
2073 // Returns the `System.Type' for the ReturnType of this
2074 // function. Provides a nice cache. (used between semantic analysis
2075 // and actual code generation
2077 public Type GetReturnType ()
2082 void DuplicateEntryPoint (MethodInfo b, Location location)
2086 "Program `" + CodeGen.FileName +
2087 "' has more than one entry point defined: `" +
2088 TypeManager.MonoBASIC_Signature(b) + "'");
2091 void Report28 (MethodInfo b)
2093 if (RootContext.WarningLevel < 4)
2098 "`" + TypeManager.MonoBASIC_Signature(b) +
2099 "' has the wrong signature to be an entry point");
2102 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2104 if (b.ReturnType != TypeManager.void_type &&
2105 b.ReturnType != TypeManager.int32_type)
2108 if (pinfo.Count == 0)
2111 if (pinfo.Count > 1)
2114 Type t = pinfo.ParameterType(0);
2116 (t.GetArrayRank() == 1) &&
2117 (t.GetElementType() == TypeManager.string_type) &&
2118 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2125 // Checks our base implementation if any
2127 protected override bool CheckBase (TypeContainer parent)
2129 // Check whether arguments were correct.
2130 if (!DoDefineParameters (parent))
2133 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2137 mi_this = TypeContainer.FindMembers (
2138 parent.TypeBuilder, MemberTypes.Method,
2139 BindingFlags.NonPublic | BindingFlags.Public |
2140 BindingFlags.Static | BindingFlags.Instance |
2141 BindingFlags.DeclaredOnly,
2142 MethodSignature.method_signature_filter, ms);
2144 if (mi_this.Count > 0) {
2145 Report.Error (111, Location, "Class `" + parent.Name + "' " +
2146 "already defines a member called `" + Name + "' " +
2147 "with the same parameter types");
2153 // Verify if the parent has a type with the same name, and then
2154 // check whether we have to create a new slot for it or not.
2156 Type ptype = parent.TypeBuilder.BaseType;
2158 // ptype is only null for System.Object while compiling corlib.
2160 MemberList mi, mi_static, mi_instance;
2162 mi_static = TypeContainer.FindMembers (
2163 ptype, MemberTypes.Method,
2164 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2165 MethodSignature.inheritable_method_signature_filter, ms);
2167 mi_instance = TypeContainer.FindMembers (
2168 ptype, MemberTypes.Method,
2169 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2170 MethodSignature.inheritable_method_signature_filter,
2173 if (mi_instance.Count > 0){
2175 } else if (mi_static.Count > 0)
2180 if (mi != null && mi.Count > 0){
2181 parent_method = (MethodInfo) mi [0];
2182 string name = parent_method.DeclaringType.Name + "." +
2185 if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
2188 if ((ModFlags & Modifiers.NEW) == 0) {
2189 Type parent_ret = TypeManager.TypeToCoreType (
2190 parent_method.ReturnType);
2192 if (parent_ret != MemberType) {
2194 508, parent.MakeName (Name) + ": cannot " +
2195 "change return type when overriding " +
2196 "inherited member " + name);
2201 /*if ((ModFlags & Modifiers.NEW) != 0)
2202 WarningNotHiding (parent);*/
2204 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2205 Report.Error (30398, Location,
2206 parent.MakeName (Name) +
2207 " : No suitable methods found to override");
2209 if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0)
2211 if ((ModFlags & Modifiers.NONVIRTUAL) != 0)
2213 Report.Error (31088, Location,
2214 parent.MakeName (Name) + " : Cannot " +
2215 "be declared NotOverridable since this method is " +
2216 "not maked as Overrides");
2219 // if a member of module is not inherited from Object class
2220 // can not be declared protected
2221 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
2222 Report.Error (31066, Location,
2223 "'Sub' or 'Function' inside a 'Module' can not be declared as " +
2224 "'Protected' or 'Protected Friend'");
2227 /* else if ((ModFlags & Modifiers.NEW) != 0)
2228 WarningNotHiding (parent);
2237 public override bool Define (TypeContainer parent)
2239 if (!DoDefine (parent))
2242 if (!CheckBase (parent))
2245 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
2246 Report.Error (31067, Location,
2247 "'Sub' or 'Function' inside a 'Structure' can not be declared as " +
2248 "'Protected' or 'Protected Friend'");
2250 CallingConventions cc = GetCallingConvention (parent is Class);
2252 MethodData = new MethodData (this, null, MemberType, ParameterTypes,
2253 ParameterInfo, cc, OptAttributes,
2254 ModFlags, flags, true);
2256 if (!MethodData.Define (parent))
2259 MethodBuilder = MethodData.MethodBuilder;
2262 // This is used to track the Entry Point,
2264 if (Name.ToUpper() == "MAIN" &&
2265 ((ModFlags & Modifiers.STATIC) != 0) &&
2266 (RootContext.MainClass == null ||
2267 RootContext.MainClass == parent.TypeBuilder.FullName ||
2268 (RootContext.RootNamespace != null &&
2269 RootContext.RootNamespace.Length > 0 &&
2270 (RootContext.RootNamespace + "." + RootContext.MainClass) == parent.TypeBuilder.FullName))) {
2271 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2272 if (RootContext.EntryPoint == null) {
2273 RootContext.EntryPoint = MethodBuilder;
2274 RootContext.EntryPointLocation = Location;
2276 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2277 DuplicateEntryPoint (MethodBuilder, Location);
2280 Report28(MethodBuilder);
2289 public void Emit (TypeContainer parent)
2291 MethodData.Emit (parent, Block, this);
2294 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2296 throw new Exception ("FIXME: I am just a placeholder implementation");
2300 public abstract class ConstructorInitializer {
2301 ArrayList argument_list;
2302 ConstructorInfo parent_constructor;
2303 Parameters parameters;
2305 public bool implicit_initialization;
2307 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2310 this.argument_list = argument_list;
2311 this.parameters = parameters;
2313 this.implicit_initialization = false;
2316 public ArrayList Arguments {
2318 return argument_list;
2322 public ConstructorInfo ParentConstructor
2326 return parent_constructor;
2330 public bool Resolve (EmitContext ec)
2332 Expression parent_constructor_group;
2335 ec.CurrentBlock = new Block (null, true, parameters);
2337 if (argument_list != null){
2338 foreach (Argument a in argument_list){
2339 if (!a.Resolve (ec, loc))
2344 ec.CurrentBlock = null;
2346 if (this is ConstructorBaseInitializer) {
2347 if (ec.ContainerType.BaseType == null)
2350 t = ec.ContainerType.BaseType;
2351 if (ec.ContainerType.IsValueType){
2352 Report.Error (522, loc,
2353 "structs cannot call base class constructors");
2358 t = ec.ContainerType;
2360 parent_constructor_group = Expression.MemberLookup (
2362 MemberTypes.Constructor,
2363 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2366 if (parent_constructor_group == null){
2367 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2371 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2372 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2374 if (parent_constructor == null) {
2375 if (this.implicit_initialization)
2376 Report.Error (30148, loc, "Must declare 'MyBase.New' in the constructor " +
2377 "of the class '" + ec.TypeContainer.Name + "' with appropriate arguments, since the base class '" +
2378 t.FullName + "' does not contain a definition of 'New' without any parameter");
2380 Report.Error (30455, loc, "Class '" + t + "' can not find a constructor for this argument list" );
2388 public void Emit (EmitContext ec)
2390 if (parent_constructor != null){
2392 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2394 Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
2401 public class ConstructorBaseInitializer : ConstructorInitializer {
2402 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2403 base (argument_list, pars, l)
2408 public class ConstructorThisInitializer : ConstructorInitializer {
2409 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2410 base (argument_list, pars, l)
2415 public class Constructor : MethodCore {
2416 public ConstructorBuilder ConstructorBuilder;
2417 public ConstructorInitializer Initializer;
2420 // Modifiers allowed for a constructor.
2422 public const int AllowedModifiers =
2424 Modifiers.PROTECTED |
2425 Modifiers.INTERNAL |
2432 // The spec claims that static is not permitted, but
2433 // my very own code has static constructors.
2435 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2436 : base (null, 0, AllowedModifiers, name, null, args, l)
2441 public Constructor (string name, int mod, Parameters args, ConstructorInitializer init, Location l)
2442 : base (null, mod, AllowedModifiers, name, null, args, l)
2447 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2449 ConstructorBuilder.SetCustomAttribute (cb);
2452 public override AttributeTargets AttributeTargets {
2454 return AttributeTargets.Constructor;
2459 // Returns true if this is a default constructor
2461 public bool IsDefault ()
2463 if ((ModFlags & Modifiers.STATIC) != 0)
2464 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2465 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2468 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2469 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2470 (Initializer is ConstructorBaseInitializer) &&
2471 (Initializer.Arguments == null);
2475 // Creates the ConstructorBuilder
2477 public override bool Define (TypeContainer parent)
2479 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2480 MethodAttributes.SpecialName);
2482 if (parent.EventHandlers != null) {
2483 ArrayList hdlrs = parent.EventHandlers;
2484 foreach(Statement stmt in hdlrs)
2485 this.Block.AddStatement (stmt);
2489 // Check if arguments were correct.
2490 if (!DoDefineParameters (parent))
2493 if ((ModFlags & Modifiers.STATIC) != 0) {
2494 ca |= MethodAttributes.Static;
2496 if (this.Parameters != Parameters.EmptyReadOnlyParameters)
2499 "Shared constructor can not have parameters");
2501 if ((ModFlags & Modifiers.Accessibility) != 0)
2504 "Shared constructor can not be declared " +
2505 "explicitly as public, private, friend or protected");
2507 if (this.Initializer != null)
2510 "Keywords like MyBase, MyClass, Me are not " +
2511 "valid inside a Shared Constructor");
2514 if (parent is Struct && ParameterTypes.Length == 0) {
2517 "Structs can not contain explicit parameterless " +
2521 ca |= MethodAttributes.HideBySig;
2523 if ((ModFlags & Modifiers.PUBLIC) != 0)
2524 ca |= MethodAttributes.Public;
2525 else if ((ModFlags & Modifiers.PROTECTED) != 0) {
2526 if ((ModFlags & Modifiers.INTERNAL) != 0)
2527 ca |= MethodAttributes.FamORAssem;
2529 ca |= MethodAttributes.Family;
2531 else if ((ModFlags & Modifiers.INTERNAL) != 0)
2532 ca |= MethodAttributes.Assembly;
2533 else if (IsDefault ())
2534 ca |= MethodAttributes.Public;
2536 ca |= MethodAttributes.Private;
2539 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2540 ca, GetCallingConvention (parent is Class), ParameterTypes);
2543 // HACK because System.Reflection.Emit is lame
2545 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2548 "Class `" +parent.Name+ "' already contains a definition with the " +
2549 "same return value and parameter types for constructor `" + Name
2560 public void Emit (TypeContainer parent)
2562 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2563 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2565 if ((ModFlags & Modifiers.STATIC) == 0){
2566 if (parent is Class && Initializer == null) {
2567 Initializer = new ConstructorBaseInitializer (
2568 null, Parameters.EmptyReadOnlyParameters, parent.Location);
2569 Initializer.implicit_initialization = true;
2573 // Spec mandates that Initializers will not have
2577 if (Initializer != null && !Initializer.Resolve (ec))
2579 ec.IsStatic = false;
2582 Parameters.LabelParameters (ec, ConstructorBuilder, Location);
2585 // Classes can have base initializers and instance field initializers.
2587 if (parent is Class){
2588 if ((ModFlags & Modifiers.STATIC) == 0)
2589 parent.EmitFieldInitializers (ec);
2592 if (Initializer != null) {
2593 if (this.ConstructorBuilder.Equals (Initializer.ParentConstructor))
2596 "A constructor can not call itself" );
2598 Initializer.Emit (ec);
2601 if ((ModFlags & Modifiers.STATIC) != 0)
2602 parent.EmitFieldInitializers (ec);
2604 if (OptAttributes != null)
2605 OptAttributes.Emit (ec, this);
2607 // If this is a non-static `struct' constructor and doesn't have any
2608 // initializer, it must initialize all of the struct's fields.
2609 if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
2610 (Initializer == null))
2611 Block.AddThisVariable (parent, Location);
2613 ec.EmitTopBlock (Block, ParameterInfo, Location);
2617 public class MethodData {
2619 // The return type of this method
2621 public readonly Type ReturnType;
2622 public readonly Type[] ParameterTypes;
2623 public readonly InternalParameters ParameterInfo;
2624 public readonly CallingConventions CallingConventions;
2625 public readonly Attributes OptAttributes;
2626 public readonly Location Location;
2629 // Are we implementing an interface ?
2631 public bool IsImplementing = false;
2636 readonly MemberBase member;
2637 readonly int modifiers;
2638 MethodAttributes flags;
2639 readonly bool is_method;
2640 readonly string accessor_name;
2641 ArrayList conditionals;
2643 MethodBuilder builder = null;
2644 public MethodBuilder MethodBuilder {
2650 public MethodData (MemberBase member, string name, Type return_type,
2651 Type [] parameter_types, InternalParameters parameters,
2652 CallingConventions cc, Attributes opt_attrs,
2653 int modifiers, MethodAttributes flags, bool is_method)
2655 this.member = member;
2656 this.accessor_name = name;
2657 this.ReturnType = return_type;
2658 this.ParameterTypes = parameter_types;
2659 this.ParameterInfo = parameters;
2660 this.CallingConventions = cc;
2661 this.OptAttributes = opt_attrs;
2662 this.modifiers = modifiers;
2664 this.is_method = is_method;
2665 this.Location = member.Location;
2666 this.conditionals = new ArrayList ();
2672 Attribute dllimport_attribute = null;
2673 string obsolete = null;
2674 bool obsolete_error = false;
2676 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2678 if ((opt_attrs == null) || (opt_attrs.Attrs == null))
2681 foreach (Attribute a in opt_attrs.Attrs) {
2682 if (a.Name == "Conditional") {
2683 if (!ApplyConditionalAttribute (a))
2685 } else if (a.Name == "Obsolete") {
2686 if (!ApplyObsoleteAttribute (a))
2688 } else if (a.Name.IndexOf ("DllImport") != -1) {
2690 a.Type = TypeManager.dllimport_type;
2691 Attribute.Error_AttributeNotValidForElement (a, Location);
2694 if (!ApplyDllImportAttribute (a))
2703 // Applies the `DllImport' attribute to the method.
2705 protected virtual bool ApplyDllImportAttribute (Attribute a)
2707 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
2708 if ((modifiers & extern_static) != extern_static) {
2709 Report.Error (601, Location,
2710 "The DllImport attribute must be specified on a method " +
2711 "marked `static' and `extern'.");
2715 flags |= MethodAttributes.PinvokeImpl;
2716 dllimport_attribute = a;
2721 // Applies the `Obsolete' attribute to the method.
2723 protected virtual bool ApplyObsoleteAttribute (Attribute a)
2725 if (obsolete != null) {
2726 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
2730 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
2731 return obsolete != null;
2735 // Applies the `Conditional' attribute to the method.
2737 protected virtual bool ApplyConditionalAttribute (Attribute a)
2739 // The Conditional attribute is only valid on methods.
2741 Attribute.Error_AttributeNotValidForElement (a, Location);
2745 string condition = a.Conditional_GetConditionName ();
2747 if (condition == null)
2750 if (ReturnType != TypeManager.void_type) {
2751 Report.Error (578, Location,
2752 "Conditional not valid on `" + member.Name + "' " +
2753 "because its return type is not void");
2757 if ((modifiers & Modifiers.OVERRIDE) != 0) {
2758 Report.Error (243, Location,
2759 "Conditional not valid on `" + member.Name + "' " +
2760 "because it is an override method");
2764 if (member.IsExplicitImpl) {
2765 Report.Error (577, Location,
2766 "Conditional not valid on `" + member.Name + "' " +
2767 "because it is an explicit interface implementation");
2771 if (IsImplementing) {
2772 Report.Error (623, Location,
2773 "Conditional not valid on `" + member.Name + "' " +
2774 "because it is an interface method");
2778 conditionals.Add (condition);
2784 // Checks whether this method should be ignored due to its Conditional attributes.
2786 bool ShouldIgnore (Location loc)
2788 // When we're overriding a virtual method, we implicitly inherit the
2789 // Conditional attributes from our parent.
2790 if (member.ParentMethod != null) {
2791 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
2792 member.ParentMethod, loc);
2794 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
2798 foreach (string condition in conditionals)
2799 if (RootContext.AllDefines [condition] == null)
2806 // Returns the TypeManager.MethodFlags for this method.
2807 // This emits an error 619 / warning 618 if the method is obsolete.
2808 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
2810 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
2812 TypeManager.MethodFlags flags = 0;
2814 if (obsolete != null) {
2815 if (obsolete_error) {
2816 Report.Error (619, loc, "Method `" + member.Name +
2817 "' is obsolete: `" + obsolete + "'");
2818 return TypeManager.MethodFlags.IsObsoleteError;
2820 Report.Warning (618, loc, "Method `" + member.Name +
2821 "' is obsolete: `" + obsolete + "'");
2823 flags |= TypeManager.MethodFlags.IsObsolete;
2826 if (ShouldIgnore (loc))
2827 flags |= TypeManager.MethodFlags.ShouldIgnore;
2833 // Search all the interface bases recursively for unimplemented methods
2835 bool SearchBasesForAbstractMethods (
2836 TypeContainer parent, Type iface_type,
2837 string method_name, ref ArrayList implementing_list,
2838 ref ArrayList implementing_iface)
2840 MethodInfo implementing = null;
2841 bool IsImplementing = false;
2842 Type current_iface_type = iface_type;
2844 implementing = parent.Pending.IsAbstractMethod (
2845 current_iface_type, method_name, ReturnType, ParameterTypes);
2847 if (implementing != null) {
2848 if (!implementing_list.Contains (implementing)) {
2849 implementing_list.Add (implementing);
2850 implementing_iface.Add(current_iface_type);
2852 IsImplementing = true;
2854 Type[] current_iface_types = current_iface_type.GetInterfaces();
2855 if (current_iface_types.Length == 0)
2858 foreach (Type curr_iface_type in current_iface_types) {
2859 IsImplementing = SearchBasesForAbstractMethods (
2860 parent, curr_iface_type, method_name,
2861 ref implementing_list, ref implementing_iface);
2868 return IsImplementing;
2871 public virtual bool Define (TypeContainer parent)
2873 MethodInfo implementing = null;
2874 ArrayList implementing_list = null;
2875 ArrayList implementing_iface = null;
2876 string method_name, name, prefix, impl_method_name;
2879 if (OptAttributes != null)
2880 if (!ApplyAttributes (OptAttributes, is_method))
2883 if (accessor_name != null)
2884 name = accessor_name + "_" + member.ShortName;
2886 name = member.ShortName;
2889 impl_method_name = name;
2891 if ((member.ModFlags & Modifiers.OVERRIDE) != 0) {
2892 if (parent.Pending == null)
2893 implementing = null;
2895 implementing = parent.Pending.IsAbstractMethod (
2896 (Type) parent.TypeBuilder.BaseType, name,
2897 ReturnType, ParameterTypes);
2899 if (implementing != null)
2900 IsImplementing = true;
2903 if (member.Implements != null) {
2904 implementing_list = new ArrayList();
2905 implementing_iface = new ArrayList();
2907 foreach (Expression Impl in member.Implements) {
2908 name = Impl.ToString();
2909 prefix = name.Substring(0, name.LastIndexOf("."));
2910 name = name.Substring(name.LastIndexOf(".") + 1);
2912 if (accessor_name != null)
2913 impl_method_name = accessor_name + "_" + name;
2915 impl_method_name = name;
2917 Type current_iface_type = (Type) member.InterfaceTypes[++pos];
2918 IsImplementing = SearchBasesForAbstractMethods (
2919 parent, current_iface_type, impl_method_name,
2920 ref implementing_list, ref implementing_iface);
2922 if (IsImplementing == false) {
2923 TypeContainer.Error_NotInterfaceMember (
2924 Location, name, prefix);
2931 // For implicit implementations, make sure we are public, for
2932 // explicit implementations, make sure we are private.
2934 //if (IsImplementing){
2936 // Setting null inside this block will trigger a more
2937 // verbose error reporting for missing interface implementations
2939 // The "candidate" function has been flagged already
2940 // but it wont get cleared
2942 /* if (!member.IsExplicitImpl){
2944 // We already catch different accessibility settings
2945 // so we just need to check that we are not private
2947 if ((modifiers & Modifiers.PRIVATE) != 0)
2948 implementing = null;
2951 // Static is not allowed
2953 if ((modifiers & Modifiers.STATIC) != 0)
2954 implementing = null;
2956 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2957 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2958 implementing = null;
2964 // If implementing is still valid, set flags
2966 if (IsImplementing){
2968 // When implementing interface methods, set NewSlot.
2970 if (implementing_list != null && implementing_list.Count != 0)
2971 flags |= MethodAttributes.NewSlot;
2974 MethodAttributes.Virtual |
2975 MethodAttributes.HideBySig;
2979 // Create the MethodBuilder for the method
2981 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2982 if ((modifiers & Modifiers.STATIC) == 0) {
2983 Report.Error (601, Location,
2984 "The DllImport attribute must be specified on " +
2985 "a method marked 'static' and 'extern'.");
2989 EmitContext ec = new EmitContext (
2990 parent, Location, null, ReturnType, modifiers);
2992 builder = dllimport_attribute.DefinePInvokeMethod (
2993 ec, parent.TypeBuilder, method_name, flags,
2994 ReturnType, ParameterTypes);
2996 builder = parent.TypeBuilder.DefineMethod (
2997 method_name, flags, CallingConventions,
2998 ReturnType, ParameterTypes);
3000 if (builder == null)
3003 if (IsImplementing) {
3005 // implement abstract methods from abstract classes
3007 if ((member.ModFlags & Modifiers.OVERRIDE) != 0) {
3009 if (member is Indexer)
3010 parent.Pending.ImplementIndexer (
3011 (Type) parent.TypeBuilder.BaseType,
3012 builder, ReturnType,
3013 ParameterTypes, true);
3016 parent.Pending.ImplementMethod (
3017 (Type) parent.TypeBuilder.BaseType,
3019 ParameterTypes, member.IsExplicitImpl);
3023 // implement abstract methods of interfaces
3025 if (member.Implements != null) {
3027 foreach (MethodInfo Impl in implementing_list) {
3030 if (member is Indexer)
3031 parent.Pending.ImplementIndexer (
3032 (Type) implementing_iface[pos++],
3033 builder, ReturnType,
3034 ParameterTypes, true);
3037 parent.Pending.ImplementMethod (
3038 (Type) implementing_iface[pos++],
3039 Impl.Name, ReturnType,
3040 ParameterTypes, member.IsExplicitImpl);
3042 parent.TypeBuilder.DefineMethodOverride (
3049 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3050 Report.Error (111, Location,
3051 "Class `" + parent.Name +
3052 "' already contains a definition with the " +
3053 "same return value and parameter types as the " +
3054 "'get' method of property `" + member.Name + "'");
3058 TypeManager.AddMethod (builder, this);
3065 public virtual void Emit (TypeContainer parent, Block block, object kind)
3070 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3071 ig = builder.GetILGenerator ();
3075 ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
3077 if (OptAttributes != null)
3078 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
3080 if (member is MethodCore)
3081 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, ((MethodCore) member).Location);
3084 // abstract or extern methods have no bodies
3086 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3091 // abstract or extern methods have no bodies.
3093 if ((modifiers & Modifiers.ABSTRACT) != 0)
3095 500, Location, "Abstract method `" +
3096 TypeManager.MonoBASIC_Signature (builder) +
3097 "' can not have a body");
3099 if ((modifiers & Modifiers.EXTERN) != 0)
3101 179, Location, "External method `" +
3102 TypeManager.MonoBASIC_Signature (builder) +
3103 "' can not have a body");
3109 // Methods must have a body unless they're extern or abstract
3111 if (block == null) {
3113 501, Location, "Method `" +
3114 TypeManager.MonoBASIC_Signature (builder) +
3115 "' must declare a body since it is not marked " +
3116 "abstract or extern");
3121 // Handle destructors specially
3123 // FIXME: This code generates buggy code
3125 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3126 EmitDestructor (ec, block);
3128 ISymbolWriter sw = CodeGen.SymbolWriter;
3130 if ((sw != null) && !Location.IsNull (Location) &&
3131 !Location.IsNull (block.EndLocation)) {
3132 Location end = block.EndLocation;
3133 MethodToken token = MethodBuilder.GetToken ();
3134 sw.OpenMethod (new SymbolToken (token.Token));
3135 // Avoid error if we don't support debugging for the platform
3137 sw.SetMethodSourceRange (Location.SymbolDocument,
3141 } catch (Exception) {
3144 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3148 ec.EmitTopBlock (block, member.Name, ParameterInfo, Location);
3152 void EmitDestructor (EmitContext ec, Block block)
3154 ILGenerator ig = ec.ig;
3156 Label finish = ig.DefineLabel ();
3157 bool old_in_try = ec.InTry;
3159 ig.BeginExceptionBlock ();
3161 ec.ReturnLabel = finish;
3162 ec.HasReturnLabel = true;
3163 ec.EmitTopBlock (block, null, Location);
3164 ec.InTry = old_in_try;
3166 // ig.MarkLabel (finish);
3167 bool old_in_finally = ec.InFinally;
3168 ec.InFinally = true;
3169 ig.BeginFinallyBlock ();
3171 if (ec.ContainerType.BaseType != null) {
3172 Expression member_lookup = Expression.MemberLookup (
3173 ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
3174 MemberTypes.Method, Expression.AllBindingFlags, Location);
3176 if (member_lookup != null){
3177 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3179 ig.Emit (OpCodes.Ldarg_0);
3180 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3183 ec.InFinally = old_in_finally;
3185 ig.EndExceptionBlock ();
3186 //ig.MarkLabel (ec.ReturnLabel);
3187 ig.Emit (OpCodes.Ret);
3191 abstract public class MemberBase : MemberCore {
3192 public Expression Type;
3193 public ArrayList Implements;
3195 protected MethodAttributes flags;
3198 // The "short" name of this property / indexer / event. This is the
3199 // name without the explicit interface.
3201 public string ShortName;
3204 // The type of this property / indexer / event
3206 public Type MemberType;
3209 // If true, this is an explicit interface implementation
3211 public bool IsExplicitImpl = false;
3214 // The name of the interface we are explicitly implementing
3216 public string ExplicitInterfaceName = null;
3219 // If true, the interface type we are explicitly implementing
3221 public Type InterfaceType = null;
3222 public ArrayList InterfaceTypes = null;
3225 // The method we're overriding if this is an override method.
3227 protected MethodInfo parent_method = null;
3228 public MethodInfo ParentMethod {
3230 return parent_method;
3235 // The constructor is only exposed to our children
3237 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
3238 Attributes attrs, Location loc)
3239 : base (name, attrs, loc)
3242 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PUBLIC, loc);
3245 protected virtual bool CheckBase (TypeContainer parent)
3250 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
3254 foreach (Type partype in parameters){
3255 if (partype.IsPointer && !UnsafeOK (parent))
3258 if (parent.AsAccessible (partype, ModFlags))
3261 Report.Error (51, Location,
3262 "Inconsistent accessibility: parameter type `" +
3263 TypeManager.MonoBASIC_Name (partype) + "' is less " +
3264 "accessible than method `" + Name + "'");
3271 protected virtual bool DoDefine (TypeContainer parent)
3276 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3279 flags = Modifiers.MethodAttr (ModFlags);
3281 // Lookup Type, verify validity
3282 MemberType = parent.ResolveType (Type, false, Location);
3283 if (MemberType == null)
3286 // check for whether the Interface is implemented by the class
3287 if (Implements != null) {
3288 InterfaceTypes = new ArrayList ();
3289 foreach (Expression Impls in Implements) {
3290 string iname = Impls.ToString();
3291 iname = iname.Substring(0, iname.LastIndexOf("."));
3292 bool iface_found = false;
3294 InterfaceType = RootContext.LookupType (
3295 parent, iname, false, Location);
3296 if (InterfaceType == null)
3299 InterfaceTypes.Add (InterfaceType);
3300 Type[] tbases = parent.TypeBuilder.GetInterfaces();
3302 if (tbases.Length != 0) {
3303 ArrayList bases = new ArrayList();
3304 TypeManager.ExpandAllInterfaces (tbases, ref bases);
3306 foreach (Type tbase in bases) {
3307 string bname = tbase.Name;
3308 if (bname.LastIndexOf(".") != -1)
3309 bname = bname.Substring(bname.LastIndexOf("."));
3311 if (bname == iname) {
3319 Report.Error (31035, Location,
3320 "Class '" + parent.Name + "' doesn't implement interface '" + iname + "'");
3326 // verify accessibility
3327 if (!parent.AsAccessible (MemberType, ModFlags)) {
3328 if (this is Property)
3329 Report.Error (53, Location,
3330 "Inconsistent accessibility: property type `" +
3331 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3332 "accessible than property `" + Name + "'");
3333 else if (this is Method)
3334 Report.Error (30508, Location,
3335 "Inconsistent accessibility: return type `" +
3336 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3337 "accessible than method `" + Name + "'");
3339 Report.Error (52, Location,
3340 "Inconsistent accessibility: field type `" +
3341 TypeManager.MonoBASIC_Name (MemberType) + "' is less " +
3342 "accessible than field `" + Name + "'");
3346 if (MemberType.IsPointer && !UnsafeOK (parent))
3350 // Check for explicit interface implementation
3352 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)) {
3353 int pos = Name.LastIndexOf (".");
3355 ExplicitInterfaceName = Name.Substring (0, pos);
3356 ShortName = Name.Substring (pos + 1);
3365 // Fields and Events both generate FieldBuilders, we use this to share
3366 // their common bits. This is also used to flag usage of the field
3368 abstract public class FieldBase : MemberBase {
3369 public FieldBuilder FieldBuilder;
3370 public Status status;
3373 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3376 // The constructor is only exposed to our children
3378 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3379 object init, Attributes attrs, Location loc)
3380 : base (type, mod, allowed_mod, name, attrs, loc)
3385 public override AttributeTargets AttributeTargets {
3387 return AttributeTargets.Field;
3393 // Whether this field has an initializer.
3395 public bool HasInitializer {
3397 return init != null;
3402 readonly Object init;
3403 Expression init_expr;
3404 bool init_expr_initialized = false;
3407 // Resolves and returns the field initializer.
3409 public Expression GetInitializerExpression (EmitContext ec)
3411 if (init_expr_initialized)
3415 if (init is Expression)
3416 e = (Expression) init;
3418 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3420 ec.IsFieldInitializer = true;
3421 e = e.DoResolve (ec);
3422 ec.IsFieldInitializer = false;
3425 init_expr_initialized = true;
3433 // The Field class is used to represents class/struct fields during parsing.
3435 public class Field : FieldBase {
3437 // Modifiers allowed in a class declaration
3439 const int AllowedModifiers =
3442 Modifiers.PROTECTED |
3443 Modifiers.INTERNAL |
3446 // Modifiers.VOLATILE |
3447 // Modifiers.UNSAFE |
3450 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3451 Attributes attrs, Location loc)
3452 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3456 public override AttributeTargets AttributeTargets {
3458 return AttributeTargets.Field;
3462 public override bool Define (TypeContainer parent)
3464 Type t = parent.ResolveType (Type, false, Location);
3469 if (!parent.AsAccessible (t, ModFlags)) {
3470 Report.Error (52, Location,
3471 "Inconsistent accessibility: field type `" +
3472 TypeManager.MonoBASIC_Name (t) + "' is less " +
3473 "accessible than field `" + Name + "'");
3477 if (t.IsPointer && !UnsafeOK (parent))
3480 Type ptype = parent.TypeBuilder.BaseType;
3482 // ptype is only null for System.Object while compiling corlib.
3484 MemberList list = TypeContainer.FindMembers (
3485 ptype, MemberTypes.Field,
3486 BindingFlags.Public |
3487 BindingFlags.Static | BindingFlags.Instance,
3488 System.Type.FilterName, Name);
3490 if (RootContext.WarningLevel > 1){
3491 if ((list.Count > 0) && ((ModFlags & Modifiers.SHADOWS) == 0))
3495 "Variable '" + Name + "' should be declared " +
3496 "Shadows since the base type '" + ptype.Name +
3497 "' has a variable with same name");
3499 ModFlags |= Modifiers.SHADOWS;
3502 if (list.Count == 0)
3503 // if a member of module is not inherited from Object class
3504 // can not be declared protected
3505 if ((parent is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
3506 Report.Error (30593, Location,
3507 "'Variable' inside a 'Module' can not be " +
3508 "declared as 'Protected'");
3511 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
3512 Report.Error (30435, Location,
3513 "'Variable' inside a 'Structure' can not be " +
3514 "declared as 'Protected'");
3516 if ((ModFlags & Modifiers.VOLATILE) != 0){
3518 if (TypeManager.IsEnumType (t))
3519 t = TypeManager.EnumToUnderlying (t);
3521 if (!((t == TypeManager.bool_type) ||
3522 (t == TypeManager.sbyte_type) ||
3523 (t == TypeManager.byte_type) ||
3524 (t == TypeManager.short_type) ||
3525 (t == TypeManager.ushort_type) ||
3526 (t == TypeManager.int32_type) ||
3527 (t == TypeManager.uint32_type) ||
3528 (t == TypeManager.char_type) ||
3529 (t == TypeManager.float_type))){
3531 677, Location, parent.MakeName (Name) +
3532 " A volatile field can not be of type `" +
3533 TypeManager.MonoBASIC_Name (t) + "'");
3539 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3541 if (parent is Struct &&
3542 ((fa & FieldAttributes.Static) == 0) &&
3543 t == parent.TypeBuilder &&
3544 !TypeManager.IsBuiltinType (t)){
3545 Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
3546 "' causes a cycle in the structure layout");
3549 FieldBuilder = parent.TypeBuilder.DefineField (
3550 Name, t, Modifiers.FieldAttr (ModFlags));
3552 TypeManager.RegisterFieldBase (FieldBuilder, this);
3556 public void Emit (TypeContainer tc)
3558 EmitContext ec = new EmitContext (tc, Location, null,
3559 FieldBuilder.FieldType, ModFlags);
3561 if (OptAttributes != null)
3562 OptAttributes.Emit (ec, this);
3565 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3567 FieldBuilder.SetCustomAttribute (cb);
3573 // `set' and `get' accessors are represented with an Accessor.
3575 public class Accessor {
3577 // Null if the accessor is empty, or a Block if not
3580 public Attributes OptAttributes;
3582 public Accessor (Block b, Attributes attrs)
3585 OptAttributes = attrs;
3589 public class GetMethod {
3590 private Accessor Get;
3591 public MethodData GetData;
3592 public MethodBuilder GetBuilder;
3594 Property parent_property;
3597 Parameters get_params;
3599 public GetMethod (Property parent_property, Accessor get_block, Attributes attrs, Parameters p_get, Location loc)
3601 this.parent_property = parent_property;
3607 public MethodBuilder Define (TypeContainer parent)
3609 Type [] g_parameters=null;
3610 Parameter [] g_parms;
3611 InternalParameters g_ip=null;
3613 if (get_params == Parameters.EmptyReadOnlyParameters) {
3614 g_parameters = TypeManager.NoTypes;
3615 g_ip = new InternalParameters (parent, Parameters.EmptyReadOnlyParameters);
3617 g_parameters = new Type [get_params.FixedParameters.Length];
3618 for (int i = 0; i < get_params.FixedParameters.Length; i ++) {
3619 g_parameters[i] = get_params.FixedParameters[i].ParameterType;
3621 g_parms = new Parameter [get_params.FixedParameters.Length];
3622 for (int i = 0; i < get_params.FixedParameters.Length; i ++) {
3623 Parameter tp = get_params.FixedParameters[i];
3624 g_parms[i] = new Parameter (tp.TypeName, tp.Name,
3625 Parameter.Modifier.NONE, null);
3627 g_ip = new InternalParameters (
3628 parent, new Parameters (g_parms, null, Location));
3631 GetData = new MethodData (parent_property, "get", parent_property.MemberType,
3632 g_parameters, g_ip, CallingConventions.Standard,
3633 Get.OptAttributes, parent_property.ModFlags, parent_property.MethodAttributeFlags, false);
3635 if (!GetData.Define (parent))
3638 GetBuilder = GetData.MethodBuilder;
3643 public void Emit (TypeContainer tc)
3645 if (GetData != null)
3647 parent_property.Parameters = get_params;
3648 GetData.Emit (tc, Get.Block, Get);
3653 public class SetMethod {
3656 MethodBuilder SetBuilder;
3658 Property parent_property;
3661 string set_parameter_name;
3662 Parameters set_params;
3664 public SetMethod (Property parent_property, Accessor set_block, string set_name,
3665 Parameters p_set, Location loc)
3667 this.parent_property = parent_property;
3670 set_parameter_name = set_name;
3671 this.Location = loc;
3674 public MethodBuilder Define (TypeContainer parent)
3676 Type [] s_parameters=null;
3677 Parameter [] s_parms;
3678 InternalParameters s_ip=null;
3680 if (set_params == Parameters.EmptyReadOnlyParameters)
3682 s_parameters = new Type [1];
3683 s_parameters [0] = parent_property.MemberType;
3685 s_parms = new Parameter [1];
3686 s_parms [0] = new Parameter (parent_property.Type, set_parameter_name,
3687 Parameter.Modifier.NONE, null);
3689 s_parameters = new Type [set_params.FixedParameters.Length];
3690 for (int i = 0; i < set_params.FixedParameters.Length; i ++) {
3691 s_parameters[i] = set_params.FixedParameters[i].ParameterType;
3694 s_parms = new Parameter [set_params.FixedParameters.Length];
3695 for (int i = 0; i < set_params.FixedParameters.Length; i ++) {
3696 Parameter tp = set_params.FixedParameters[i];
3697 s_parms[i] = new Parameter (tp.TypeName, tp.Name,
3698 Parameter.Modifier.NONE, null);
3702 s_ip = new InternalParameters (
3703 parent, new Parameters (s_parms, null, Location));
3705 SetData = new MethodData (parent_property, "set", TypeManager.void_type,
3706 s_parameters, s_ip, CallingConventions.Standard,
3707 Set.OptAttributes, parent_property.ModFlags, parent_property.MethodAttributeFlags, false);
3709 if (!SetData.Define (parent))
3712 SetBuilder = SetData.MethodBuilder;
3713 SetBuilder.DefineParameter (1, ParameterAttributes.None,
3714 set_parameter_name);
3719 public void Emit (TypeContainer tc)
3721 if (SetData != null)
3723 parent_property.Parameters = set_params;
3724 SetData.Emit (tc, Set.Block, Set);
3729 public class Property : MethodCore {
3730 GetMethod GetMethod;
3731 SetMethod SetMethod;
3733 public Accessor Set;
3734 public PropertyBuilder PropertyBuilder;
3735 public MethodBuilder GetBuilder;
3736 public MethodBuilder SetBuilder;
3737 public MethodData SetData;
3739 protected EmitContext ec;
3741 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3743 PropertyBuilder.SetCustomAttribute (cb);
3746 public override AttributeTargets AttributeTargets {
3748 return AttributeTargets.Property;
3752 protected override bool DoDefine (TypeContainer parent)
3754 if (!base.DoDefine (parent))
3757 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3763 // Checks our base implementation if any
3765 protected override bool CheckBase (TypeContainer container)
3767 base.CheckBase (container);
3769 // Check whether arguments were correct.
3770 if (!DoDefineParameters (container))
3776 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
3781 mi_this = TypeContainer.FindMembers (
3782 container.TypeBuilder, MemberTypes.Property,
3783 BindingFlags.NonPublic | BindingFlags.Public |
3784 BindingFlags.Static | BindingFlags.Instance |
3785 BindingFlags.DeclaredOnly,
3786 MethodSignature.method_signature_filter, ms);
3788 if (mi_this.Count > 0) {
3789 Report.Error (111, Location, "Class `" + container.Name + "' " +
3790 "already defines a member called `" + Name + "' " +
3791 "with the same parameter types");
3796 if (container is Interface)
3800 if ((ModFlags & Modifiers.READONLY) != 0)
3801 retval = MemberType;
3803 //string report_name;
3804 MethodSignature base_ms;
3807 if (this is Indexer) {
3808 string name, base_name;
3810 report_name = "this";
3811 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
3812 ms = new MethodSignature (name, null, ParameterTypes);
3813 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
3814 base_ms = new MethodSignature (base_name, retval, ParameterTypes);
3816 //report_name = Name;
3817 ms = base_ms = new MethodSignature (Name, retval, ParameterTypes);
3821 // Verify if the parent has a type with the same name, and then
3822 // check whether we have to create a new slot for it or not.
3824 Type ptype = container.TypeBuilder.BaseType;
3826 MemberInfo parent_member = null;
3827 MemberList mi, mi_static, mi_instance;
3830 // Find properties with the same name on the base class
3832 mi_static = TypeContainer.FindMembers (
3833 ptype, MemberTypes.Property,
3834 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
3835 MethodSignature.inheritable_property_signature_filter, base_ms);
3837 mi_instance = TypeContainer.FindMembers (
3838 ptype, MemberTypes.Property,
3839 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
3840 MethodSignature.inheritable_property_signature_filter,
3843 if (mi_instance.Count > 0)
3845 else if (mi_static.Count > 0)
3850 if (mi != null && mi.Count > 0)
3851 parent_member = (PropertyInfo) mi [0];
3853 if (parent_member is PropertyInfo) {
3854 PropertyInfo parent_property = (PropertyInfo)parent_member;
3856 string name = parent_property.DeclaringType.Name + "." +
3857 parent_property.Name;
3859 MethodInfo get, set, parent_method;
3860 get = parent_property.GetGetMethod (true);
3861 set = parent_property.GetSetMethod (true);
3864 parent_method = get;
3865 else if (set != null)
3866 parent_method = set;
3868 throw new Exception ("Internal error!");
3870 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
3873 if ((ModFlags & Modifiers.NEW) == 0) {
3874 Type parent_type = TypeManager.TypeToCoreType (
3875 parent_property.PropertyType);
3877 if (parent_type != MemberType) {
3879 508, Location, container.MakeName (Name) + ": cannot " +
3880 "change return type when overriding " +
3881 "inherited member " + name);
3885 } else if (parent_member == null) {
3886 /*if ((ModFlags & Modifiers.NEW) != 0)
3887 WarningNotHiding (container);
3889 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3892 if (this is Indexer)
3893 Report.Error (115, Location,
3894 container.MakeName (Name) +
3895 " no suitable indexers found to override");
3898 Report.Error (115, Location,
3899 container.MakeName (Name) +
3900 " no suitable properties found to override");
3904 if ((ModFlags & ( Modifiers.NEW | Modifiers.SHADOWS | Modifiers.OVERRIDE )) == 0) {
3905 if ((ModFlags & Modifiers.NONVIRTUAL) != 0) {
3906 Report.Error (31088, Location,
3907 container.MakeName (Name) + " : Cannot " +
3908 "be declared NotOverridable since this method is " +
3909 "not maked as Overrides");
3912 // if a member of module is not inherited from Object class
3913 // can not be declared protected
3914 if ((container is Module) && ((ModFlags & Modifiers.PROTECTED) != 0))
3915 Report.Error (31066, Location,
3916 "'Property' inside a 'Module' can not be declared as " +
3917 "'Protected' or 'Protected Friend'");
3923 const int AllowedModifiers =
3926 Modifiers.PROTECTED |
3927 Modifiers.INTERNAL |
3931 Modifiers.OVERRIDE |
3932 Modifiers.ABSTRACT |
3936 Modifiers.NONVIRTUAL |
3938 Modifiers.READONLY |
3939 Modifiers.WRITEONLY |
3942 string set_parameter_name;
3943 Parameters get_params;
3944 Parameters set_params;
3946 public Property (Expression type, string name, int mod_flags,
3947 Accessor get_block, Accessor set_block,
3948 Attributes attrs, Location loc, string set_name,
3949 Parameters p_get, Parameters p_set, ArrayList impl_what)
3950 : base (type, mod_flags, AllowedModifiers, name, attrs, p_set, loc)
3953 if (get_block != null)
3954 GetMethod = new GetMethod (this, get_block, attrs, p_get, loc);
3956 if (set_block != null)
3957 SetMethod = new SetMethod (this, set_block, set_name, p_set, loc);
3959 Implements = impl_what;
3962 public Property (Expression type, string name, int mod_flags,
3963 Accessor get_block, Accessor set_block,
3964 Attributes attrs, Location loc)
3965 : this (type, name, mod_flags, get_block, set_block, attrs, loc,
3966 "Value", Parameters.EmptyReadOnlyParameters, Parameters.EmptyReadOnlyParameters, null)
3970 public override bool Define (TypeContainer parent)
3972 /*Type [] s_parameters=null;
3973 Parameter [] s_parms;
3974 InternalParameters s_ip=null;*/
3976 if ((parent is Struct) && ((ModFlags & Modifiers.PROTECTED) != 0))
3977 Report.Error (30435, Location,
3978 "'Property' inside a 'Structure' can not be declared as " +
3979 "'Protected' or 'Protected Friend'");
3981 if (!DoDefine (parent))
3984 if (!CheckBase (parent))
3987 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
3989 if (GetMethod == null) {
3990 if ((ModFlags & Modifiers.WRITEONLY) == 0)
3993 "Property without 'Get' accessor must have a 'WriteOnly' modifier");
3995 GetBuilder = GetMethod.Define (parent);
3997 if (SetMethod== null) {
3998 if ((ModFlags & Modifiers.READONLY) == 0)
4001 "Property without 'Set' accessor must have a 'ReadOnly' modifier");
4005 SetBuilder = SetMethod.Define (parent);
4007 // FIXME - PropertyAttributes.HasDefault ?
4009 PropertyAttributes prop_attr =
4010 PropertyAttributes.RTSpecialName |
4011 PropertyAttributes.SpecialName;
4013 if (!IsExplicitImpl){
4014 PropertyBuilder = parent.TypeBuilder.DefineProperty (
4015 Name, prop_attr, MemberType, null);
4017 PropertyBuilder.SetGetMethod (GetBuilder);
4018 PropertyBuilder.SetSetMethod (SetBuilder);
4021 // HACK for the reasons exposed above
4023 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4026 "Class `" + parent.Name +
4027 "' already contains a definition for the property `" +
4035 public void Emit (TypeContainer tc)
4038 // The PropertyBuilder can be null for explicit implementations, in that
4039 // case, we do not actually emit the ".property", so there is nowhere to
4040 // put the attribute
4043 if (PropertyBuilder != null && OptAttributes != null)
4044 OptAttributes.Emit (ec, this);
4046 if (GetMethod != null)
4048 GetMethod.Emit (tc);
4051 if (SetMethod != null)
4053 SetMethod.Emit (tc);
4057 public MethodAttributes MethodAttributeFlags {
4066 /// Gigantic workaround for lameness in SRE follows :
4067 /// This class derives from EventInfo and attempts to basically
4068 /// wrap around the EventBuilder so that FindMembers can quickly
4069 /// return this in it search for members
4071 public class MyEventBuilder : EventInfo {
4074 // We use this to "point" to our Builder which is
4075 // not really a MemberInfo
4077 EventBuilder MyBuilder;
4080 // We "catch" and wrap these methods
4082 MethodInfo raise, remove, add;
4084 EventAttributes attributes;
4085 Type declaring_type, reflected_type, event_type;
4088 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4090 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4092 // And now store the values in our own fields.
4094 declaring_type = type_builder;
4096 reflected_type = type_builder;
4098 attributes = event_attr;
4100 this.event_type = event_type;
4104 // Methods that you have to override. Note that you only need
4105 // to "implement" the variants that take the argument (those are
4106 // the "abstract" methods, the others (GetAddMethod()) are
4109 public override MethodInfo GetAddMethod (bool nonPublic)
4114 public override MethodInfo GetRemoveMethod (bool nonPublic)
4119 public override MethodInfo GetRaiseMethod (bool nonPublic)
4125 // These methods make "MyEventInfo" look like a Builder
4127 public void SetRaiseMethod (MethodBuilder raiseMethod)
4129 raise = raiseMethod;
4130 MyBuilder.SetRaiseMethod (raiseMethod);
4133 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4135 remove = removeMethod;
4136 MyBuilder.SetRemoveOnMethod (removeMethod);
4139 public void SetAddOnMethod (MethodBuilder addMethod)
4142 MyBuilder.SetAddOnMethod (addMethod);
4145 public void SetCustomAttribute (CustomAttributeBuilder cb)
4147 MyBuilder.SetCustomAttribute (cb);
4150 public override object [] GetCustomAttributes (bool inherit)
4152 // FIXME : There's nothing which can be seemingly done here because
4153 // we have no way of getting at the custom attribute objects of the
4158 public override object [] GetCustomAttributes (Type t, bool inherit)
4160 // FIXME : Same here !
4164 public override bool IsDefined (Type t, bool b)
4169 public override EventAttributes Attributes {
4175 public override string Name {
4181 public override Type DeclaringType {
4183 return declaring_type;
4187 public override Type ReflectedType {
4189 return reflected_type;
4193 public Type EventType {
4201 public class AddDelegateMethod {
4202 MethodBuilder AddBuilder;
4207 public AddDelegateMethod (Event parent_event, Location loc)
4209 this.parent_event = parent_event;
4213 public MethodBuilder Define (TypeContainer parent)
4215 Type [] parameter_types = new Type [1];
4216 parameter_types [0] = parent_event.MemberType;
4218 Parameter [] parms = new Parameter [1];
4219 parms [0] = new Parameter (parent_event.Type, /* was "value" */ parent_event.Name, Parameter.Modifier.NONE, null);
4220 InternalParameters ip = new InternalParameters (
4221 parent, new Parameters (parms, null, Location));
4223 AddData = new MethodData (parent_event, "add", TypeManager.void_type,
4224 parameter_types, ip, CallingConventions.Standard, null,
4225 parent_event.ModFlags, parent_event.MethodAttributeFlags, false);
4227 if (!AddData.Define (parent))
4230 AddBuilder = AddData.MethodBuilder;
4231 AddBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ parent_event.Name);
4238 public void Emit (TypeContainer tc)
4240 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4241 EmitContext ec = new EmitContext (tc, Location, ig, TypeManager.void_type, parent_event.ModFlags);
4242 parent_event.EmitDefaultMethod (ec, true);
4246 public class RemoveDelegateMethod {
4247 MethodBuilder RemoveBuilder;
4248 MethodData RemoveData;
4252 public RemoveDelegateMethod (Event parent_event, Location loc)
4254 this.parent_event = parent_event;
4258 public MethodBuilder Define (TypeContainer parent)
4260 //EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4262 Type [] parameter_types = new Type [1];
4263 parameter_types [0] = parent_event.MemberType;
4265 Parameter [] parms = new Parameter [1];
4266 parms [0] = new Parameter (parent_event.Type, /* was "value" */ parent_event.Name, Parameter.Modifier.NONE, null);
4267 InternalParameters ip = new InternalParameters (
4268 parent, new Parameters (parms, null, Location));
4271 RemoveData = new MethodData (parent_event, "remove", TypeManager.void_type,
4272 parameter_types, ip, CallingConventions.Standard, null,
4273 parent_event.ModFlags, parent_event.MethodAttributeFlags, false);
4275 if (!RemoveData.Define (parent))
4278 RemoveBuilder = RemoveData.MethodBuilder;
4279 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, /* was "value" */ parent_event.Name);
4281 return RemoveBuilder;
4284 public void Emit (TypeContainer tc)
4286 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4287 EmitContext ec = new EmitContext (tc, Location, ig, TypeManager.void_type, parent_event.ModFlags);
4288 parent_event.EmitDefaultMethod (ec, false);
4292 public class Event : FieldBase {
4293 const int AllowedModifiers =
4296 Modifiers.PROTECTED |
4297 Modifiers.INTERNAL |
4302 Modifiers.OVERRIDE |
4306 public readonly AddDelegateMethod Add;
4307 public readonly RemoveDelegateMethod Remove;
4308 public MyEventBuilder EventBuilder;
4310 MethodBuilder AddBuilder, RemoveBuilder;
4312 public Event (Expression type, string name, Object init, int mod, Attributes attrs, Location loc)
4313 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4315 Add = new AddDelegateMethod (this, loc);
4316 Remove = new RemoveDelegateMethod (this, loc);
4321 public Event (Expression type, string name, Object init, int mod, Attributes attrs, ArrayList impl_what, Location loc)
4322 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4324 Add = new AddDelegateMethod (this, loc);
4325 Remove = new RemoveDelegateMethod (this, loc);
4327 Implements = impl_what;
4330 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4332 EventBuilder.SetCustomAttribute (cb);
4335 public override AttributeTargets AttributeTargets {
4337 return AttributeTargets.Event;
4341 public override bool Define (TypeContainer parent)
4343 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4345 if (!DoDefine (parent))
4348 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4349 Report.Error (31044, Location, "'" + parent.Name + "." + Name +
4350 "' : event must be of a delegate type");
4354 Type [] parameter_types = new Type [1];
4355 parameter_types [0] = MemberType;
4357 Parameter [] parms = new Parameter [1];
4358 parms [0] = new Parameter (Type, /* was "value" */ this.Name, Parameter.Modifier.NONE, null);
4359 /*InternalParameters ip = new InternalParameters (
4360 parent, new Parameters (parms, null, Location));
4363 if (!CheckBase (parent))
4366 AddBuilder = Add.Define (parent);
4367 RemoveBuilder = Remove.Define (parent);
4370 if (!IsExplicitImpl){
4371 EventBuilder = new MyEventBuilder (
4372 parent.TypeBuilder, Name, e_attr, MemberType);
4374 FieldBuilder = parent.TypeBuilder.DefineField (Name, MemberType,
4375 FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4376 TypeManager.RegisterPrivateFieldOfEvent ((EventInfo) EventBuilder, FieldBuilder);
4377 TypeManager.RegisterFieldBase (FieldBuilder, this);
4379 EventBuilder.SetAddOnMethod (AddBuilder);
4380 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4382 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4383 Report.Error (111, Location,
4384 "Class `" + parent.Name +
4385 "' already contains a definition for the event `" +
4394 public void EmitDefaultMethod (EmitContext ec, bool is_add)
4396 ILGenerator ig = ec.ig;
4397 MethodInfo method = null;
4400 method = TypeManager.delegate_combine_delegate_delegate;
4402 method = TypeManager.delegate_remove_delegate_delegate;
4404 if ((ModFlags & Modifiers.STATIC) != 0) {
4405 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4406 ig.Emit (OpCodes.Ldarg_0);
4407 ig.Emit (OpCodes.Call, method);
4408 ig.Emit (OpCodes.Castclass, MemberType);
4409 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4411 ig.Emit (OpCodes.Ldarg_0);
4412 ig.Emit (OpCodes.Ldarg_0);
4413 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4414 ig.Emit (OpCodes.Ldarg_1);
4415 ig.Emit (OpCodes.Call, method);
4416 ig.Emit (OpCodes.Castclass, MemberType);
4417 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4419 ig.Emit (OpCodes.Ret);
4422 public void Emit (TypeContainer tc)
4426 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4428 if (OptAttributes != null)
4429 OptAttributes.Emit (ec, this);
4435 public MethodAttributes MethodAttributeFlags {
4443 struct MethodSignature {
4445 public Type RetType;
4446 public Type [] Parameters;
4449 /// This delegate is used to extract methods which have the
4450 /// same signature as the argument
4452 public static MemberFilter method_signature_filter;
4455 /// This delegate is used to extract methods which have the
4456 /// same signature as the argument except for the name
4458 public static MemberFilter method_signature_noname_filter;
4461 /// This delegate is used to extract inheritable methods which
4462 /// have the same signature as the argument. By inheritable,
4463 /// this means that we have permissions to override the method
4464 /// from the current assembly and class
4466 public static MemberFilter inheritable_method_signature_filter;
4469 /// This delegate is used to extract inheritable methods which
4470 /// have the same signature as the argument. By inheritable,
4471 /// this means that we have permissions to override the method
4472 /// from the current assembly and class
4474 public static MemberFilter inheritable_property_signature_filter;
4476 static MethodSignature ()
4478 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4479 method_signature_noname_filter = new MemberFilter (MemberSignatureCompareNoName);
4480 inheritable_method_signature_filter = new MemberFilter (
4481 InheritableMemberSignatureCompare);
4482 inheritable_property_signature_filter = new MemberFilter (
4483 InheritablePropertySignatureCompare);
4486 public MethodSignature (string name, Type ret_type, Type [] parameters)
4491 if (parameters == null)
4492 Parameters = TypeManager.NoTypes;
4494 Parameters = parameters;
4497 public override int GetHashCode ()
4499 return Name.GetHashCode ();
4502 public override bool Equals (Object o)
4504 MethodSignature other = (MethodSignature) o;
4506 if (other.Name != Name)
4509 if (other.RetType != RetType)
4512 if (Parameters == null){
4513 if (other.Parameters == null)
4518 if (other.Parameters == null)
4521 int c = Parameters.Length;
4522 if (other.Parameters.Length != c)
4525 for (int i = 0; i < c; i++)
4526 if (other.Parameters [i] != Parameters [i])
4532 static bool MemberSignatureCompareNoName (MemberInfo m, object filter_criteria)
4534 return MemberSignatureCompare (m, filter_criteria, false);
4537 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4539 return MemberSignatureCompare (m, filter_criteria, true);
4542 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria, bool use_name)
4544 MethodSignature sig = (MethodSignature) filter_criteria;
4546 if (use_name && (m.Name != sig.Name))
4550 MethodInfo mi = m as MethodInfo;
4551 PropertyInfo pi = m as PropertyInfo;
4554 ReturnType = mi.ReturnType;
4555 else if (pi != null)
4556 ReturnType = pi.PropertyType;
4561 // we use sig.RetType == null to mean `do not check the
4562 // method return value.
4564 if (sig.RetType != null)
4565 if (ReturnType != sig.RetType)
4570 args = TypeManager.GetArgumentTypes (mi);
4572 args = TypeManager.GetArgumentTypes (pi);
4574 Type [] sigp = sig.Parameters;
4576 if (args.Length != sigp.Length)
4579 for (int i = args.Length; i > 0; ){
4581 if (args [i] != sigp [i])
4588 // This filter should be used when we are requesting methods that
4589 // we want to override.
4591 // This makes a number of assumptions, for example
4592 // that the methods being extracted are of a parent
4593 // class (this means we know implicitly that we are
4594 // being called to find out about members by a derived
4597 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4599 if (MemberSignatureCompare (m, filter_criteria)){
4600 MethodInfo mi = (MethodInfo) m;
4601 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4603 // If only accessible to the current class.
4604 if (prot == MethodAttributes.Private)
4607 // If only accessible to the defining assembly or
4608 if (prot == MethodAttributes.FamANDAssem ||
4609 prot == MethodAttributes.Assembly){
4610 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4616 // Anything else (FamOrAssembly and Public) is fine
4623 // This filter should be used when we are requesting properties that
4624 // we want to override.
4626 // This makes a number of assumptions, for example
4627 // that the methods being extracted are of a parent
4628 // class (this means we know implicitly that we are
4629 // being called to find out about members by a derived
4632 static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
4634 if (MemberSignatureCompare (m, filter_criteria)){
4635 PropertyInfo pi = (PropertyInfo) m;
4637 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
4638 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
4640 MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
4642 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4644 // If only accessible to the current class.
4645 if (prot == MethodAttributes.Private)
4648 // If only accessible to the defining assembly or
4649 if (prot == MethodAttributes.FamANDAssem ||
4650 prot == MethodAttributes.Assembly){
4651 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4657 // Anything else (FamOrAssembly and Public) is fine