2 // class.cs: Class and Struct handlers
4 // Author: Miguel de Icaza (miguel@gnu.org)
6 // Licensed under the terms of the GNU GPL
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
12 using System.Collections;
13 using System.Reflection;
14 using System.Reflection.Emit;
16 using System.Runtime.CompilerServices;
17 using System.Diagnostics.SymbolStore;
19 namespace Mono.CSharp {
22 /// This is the base class for structs and classes.
24 public class TypeContainer : DeclSpace {
25 // Holds a list of classes and structures
28 // Holds the list of properties
31 // Holds the list of enumerations
34 // Holds the list of delegates
37 // Holds the list of constructors
38 ArrayList instance_constructors;
40 // Holds the list of fields
43 // Holds a list of fields that have initializers
44 ArrayList initialized_fields;
46 // Holds a list of static fields that have initializers
47 ArrayList initialized_static_fields;
49 // Holds the list of constants
55 // Holds order in which interfaces must be closed
56 ArrayList interface_order;
67 // Holds the operators
71 // Pointers to the default constructor and the default static constructor
73 Constructor default_constructor;
74 Constructor default_static_constructor;
77 // Whether we have seen a static constructor for this class or not
79 bool have_static_constructor = false;
82 // This one is computed after we can distinguish interfaces
83 // from classes from the arraylist `type_bases'
85 string base_class_name;
89 // Attributes for this type
90 protected Attributes attributes;
92 // Information in the case we are an attribute type
94 public AttributeTargets Targets = AttributeTargets.All;
95 public bool AllowMultiple = false;
96 public bool Inherited;
99 public TypeContainer (TypeContainer parent, string name, Location l)
100 : base (parent, name, l)
103 types = new ArrayList ();
110 base_class_name = null;
112 //Console.WriteLine ("New class " + name + " inside " + n);
115 public AdditionResult AddConstant (Const constant)
118 string name = constant.Name;
120 if ((res = IsValid (name)) != AdditionResult.Success)
123 if (constants == null)
124 constants = new ArrayList ();
126 constants.Add (constant);
127 DefineName (name, constant);
129 return AdditionResult.Success;
132 public AdditionResult AddEnum (Mono.CSharp.Enum e)
135 string name = e.Name;
137 if ((res = IsValid (name)) != AdditionResult.Success)
141 enums = new ArrayList ();
144 DefineName (name, e);
146 return AdditionResult.Success;
149 public AdditionResult AddClass (Class c)
152 string name = c.Name;
155 if ((res = IsValid (name)) != AdditionResult.Success)
158 DefineName (name, c);
161 return AdditionResult.Success;
164 public AdditionResult AddStruct (Struct s)
167 string name = s.Name;
169 if ((res = IsValid (name)) != AdditionResult.Success)
172 DefineName (name, s);
175 return AdditionResult.Success;
178 public AdditionResult AddDelegate (Delegate d)
181 string name = d.Name;
183 if ((res = IsValid (name)) != AdditionResult.Success)
186 if (delegates == null)
187 delegates = new ArrayList ();
189 DefineName (name, d);
192 return AdditionResult.Success;
195 public AdditionResult AddMethod (Method method)
197 string name = method.Name;
198 Object value = defined_names [name];
200 if (value != null && (!(value is Method)))
201 return AdditionResult.NameExists;
204 methods = new ArrayList ();
206 methods.Add (method);
208 DefineName (name, method);
210 return AdditionResult.Success;
213 public AdditionResult AddConstructor (Constructor c)
215 if (c.Name != Basename)
216 return AdditionResult.NotAConstructor;
218 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
221 have_static_constructor = true;
222 if (default_static_constructor != null){
223 Console.WriteLine ("I have a static constructor already");
224 Console.WriteLine (" " + default_static_constructor);
225 return AdditionResult.MethodExists;
228 default_static_constructor = c;
231 if (default_constructor != null)
232 return AdditionResult.MethodExists;
233 default_constructor = c;
236 if (instance_constructors == null)
237 instance_constructors = new ArrayList ();
239 instance_constructors.Add (c);
242 return AdditionResult.Success;
245 public AdditionResult AddInterface (Interface iface)
248 string name = iface.Name;
250 if ((res = IsValid (name)) != AdditionResult.Success)
253 if (interfaces == null)
254 interfaces = new ArrayList ();
255 interfaces.Add (iface);
256 DefineName (name, iface);
258 return AdditionResult.Success;
261 public AdditionResult AddField (Field field)
264 string name = field.Name;
266 if ((res = IsValid (name)) != AdditionResult.Success)
270 fields = new ArrayList ();
274 if (field.Initializer != null){
275 if ((field.ModFlags & Modifiers.STATIC) != 0){
276 if (initialized_static_fields == null)
277 initialized_static_fields = new ArrayList ();
279 initialized_static_fields.Add (field);
282 // We have not seen a static constructor,
283 // but we will provide static initialization of fields
285 have_static_constructor = true;
287 if (initialized_fields == null)
288 initialized_fields = new ArrayList ();
290 initialized_fields.Add (field);
294 DefineName (name, field);
295 return AdditionResult.Success;
298 public AdditionResult AddProperty (Property prop)
301 string name = prop.Name;
303 if ((res = IsValid (name)) != AdditionResult.Success)
306 if (properties == null)
307 properties = new ArrayList ();
309 properties.Add (prop);
310 DefineName (name, prop);
312 return AdditionResult.Success;
315 public AdditionResult AddEvent (Event e)
318 string name = e.Name;
320 if ((res = IsValid (name)) != AdditionResult.Success)
324 events = new ArrayList ();
327 DefineName (name, e);
329 return AdditionResult.Success;
332 public AdditionResult AddIndexer (Indexer i)
334 if (indexers == null)
335 indexers = new ArrayList ();
339 return AdditionResult.Success;
342 public AdditionResult AddOperator (Operator op)
344 if (operators == null)
345 operators = new ArrayList ();
349 return AdditionResult.Success;
352 public void RegisterOrder (Interface iface)
354 if (interface_order == null)
355 interface_order = new ArrayList ();
357 interface_order.Add (iface);
360 public ArrayList Types {
366 public ArrayList Methods {
372 public ArrayList Constants {
378 public ArrayList Interfaces {
386 return base_class_name;
390 public ArrayList Bases {
400 public ArrayList Fields {
406 public ArrayList InstanceConstructors {
408 return instance_constructors;
412 public ArrayList Properties {
418 public ArrayList Events {
424 public ArrayList Enums {
430 public ArrayList Indexers {
436 public ArrayList Operators {
442 public ArrayList Delegates {
448 public Attributes OptAttributes {
454 public bool HaveStaticConstructor {
456 return have_static_constructor;
460 public virtual TypeAttributes TypeAttr {
462 return Modifiers.TypeAttr (ModFlags, this);
467 // Emits the instance field initializers
469 public bool EmitFieldInitializers (EmitContext ec)
472 ILGenerator ig = ec.ig;
473 Expression instance_expr;
476 fields = initialized_static_fields;
477 instance_expr = null;
479 fields = initialized_fields;
480 instance_expr = new This (Location.Null).Resolve (ec);
486 foreach (Field f in fields){
487 Object init = f.Initializer;
490 if (init is Expression)
491 e = (Expression) init;
493 string base_type = f.Type.Substring (0, f.Type.IndexOf ("["));
494 string rank = f.Type.Substring (f.Type.IndexOf ("["));
495 e = new ArrayCreation (base_type, rank, (ArrayList)init, f.Location);
498 Location l = f.Location;
499 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
500 fe.InstanceExpression = instance_expr;
501 Expression a = new Assign (fe, e, l);
507 if (a is ExpressionStatement)
508 ((ExpressionStatement) a).EmitStatement (ec);
510 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
518 // Defines the default constructors
520 void DefineDefaultConstructor (bool is_static)
525 c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
526 new ConstructorBaseInitializer (null, new Location (-1)),
530 mods = Modifiers.STATIC;
536 c.Block = new Block (null);
540 public void ReportStructInitializedInstanceError ()
542 string n = TypeBuilder.FullName;
544 foreach (Field f in initialized_fields){
547 "`" + n + "." + f.Name + "': can not have " +
548 "instance field initializers in structs");
552 struct TypeAndMethods {
554 public MethodInfo [] methods;
556 // Far from ideal, but we want to avoid creating a copy
558 public Type [][] args;
561 // This flag on the method says `We found a match, but
562 // because it was private, we could not use the match
564 public bool [] found;
568 // This array keeps track of the pending implementations
570 TypeAndMethods [] pending_implementations;
573 // Returns a list of the abstract methods that are exposed by all of our
574 // parents that we must implement. Notice that this `flattens' the
575 // method search space, and takes into account overrides.
577 ArrayList GetAbstractMethods (Type t)
579 ArrayList list = null;
580 bool searching = true;
581 Type current_type = t;
587 current_type, MemberTypes.Method,
588 BindingFlags.Public | BindingFlags.Instance |
589 BindingFlags.DeclaredOnly,
590 virtual_method_filter, null);
592 if (current_type == TypeManager.object_type)
595 current_type = current_type.BaseType;
596 if (!current_type.IsAbstract)
603 int count = mi.Length;
607 if (count == 1 && !(mi [0] is MethodBase))
610 list = TypeManager.CopyNewMethods (list, mi);
616 for (int i = 0; i < list.Count; i++){
617 while (list.Count > i && !((MethodInfo) list [i]).IsAbstract)
628 // Registers the required method implementations for this class
630 // Register method implementations are either abstract methods
631 // flagged as such on the base class or interface methods
633 public void RegisterRequiredImplementations ()
635 Type [] ifaces = TypeBuilder.GetInterfaces ();
636 Type b = TypeBuilder.BaseType;
641 Type x = TypeBuilder;
644 Type [] iff = x.GetInterfaces ();
645 Console.WriteLine ("Type: " + x.Name);
647 foreach (Type tt in iff){
648 Console.WriteLine (" Iface: " + tt.Name);
655 icount = ifaces.Length;
658 // If we are implementing an abstract class, and we are not
659 // ourselves abstract, and there are abstract methods (C# allows
660 // abstract classes that have no abstract methods), then allocate
663 // We also pre-compute the methods.
665 bool implementing_abstract = (b.IsAbstract && !TypeBuilder.IsAbstract);
666 ArrayList abstract_methods = null;
668 if (implementing_abstract){
669 abstract_methods = GetAbstractMethods (b);
671 if (abstract_methods == null)
672 implementing_abstract = false;
675 int total = icount + (implementing_abstract ? 1 : 0);
679 pending_implementations = new TypeAndMethods [total];
683 foreach (Type t in ifaces){
686 if (t is TypeBuilder){
689 iface = TypeManager.LookupInterface (t);
691 mi = iface.GetMethods ();
693 mi = t.GetMethods ();
695 int count = mi.Length;
696 pending_implementations [i].type = t;
697 pending_implementations [i].methods = mi;
698 pending_implementations [i].args = new Type [count][];
699 pending_implementations [i].found = new bool [count];
702 foreach (MethodInfo m in mi){
703 Type [] types = TypeManager.GetArgumentTypes (m);
705 pending_implementations [i].args [j] = types;
712 if (abstract_methods != null){
713 int count = abstract_methods.Count;
714 pending_implementations [i].methods = new MethodInfo [count];
716 abstract_methods.CopyTo (pending_implementations [i].methods, 0);
717 pending_implementations [i].found = new bool [count];
718 pending_implementations [i].args = new Type [count][];
719 pending_implementations [i].type = TypeBuilder;
722 foreach (MemberInfo m in abstract_methods){
723 MethodInfo mi = (MethodInfo) m;
725 Type [] types = TypeManager.GetArgumentTypes (mi);
727 pending_implementations [i].args [j] = types;
734 /// This function computes the Base class and also the
735 /// list of interfaces that the class or struct @c implements.
737 /// The return value is an array (might be null) of
738 /// interfaces implemented (as Types).
740 /// The @parent argument is set to the parent object or null
741 /// if this is `System.Object'.
743 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
745 ArrayList bases = Bases;
754 parent = TypeManager.value_type;
758 if (RootContext.StdLib)
759 parent = TypeManager.object_type;
760 else if (Name != "System.Object")
761 parent = TypeManager.object_type;
764 // If we are compiling our runtime,
765 // and we are defining ValueType, then our
766 // parent is `System.Object'.
768 if (!RootContext.StdLib && Name == "System.ValueType")
769 parent = TypeManager.object_type;
776 // Bases should be null if there are no bases at all
781 string name = (string) bases [0];
782 Type first = FindType (name);
793 parent = TypeManager.object_type;
801 Type [] ifaces = new Type [count-start];
803 for (i = start, j = 0; i < count; i++, j++){
804 string name = (string) bases [i];
805 Type t = FindType (name);
812 if (is_class == false && !t.IsInterface){
813 Report.Error (527, "In Struct `" + Name + "', type `"+
814 name +"' is not an interface");
823 detail = " (a class can not inherit from a struct/enum)";
825 Report.Error (509, "class `"+ Name +
826 "': Cannot inherit from sealed class `"+
827 bases [i]+"'"+detail);
834 Report.Error (527, "In Class `" + Name + "', type `"+
835 name+"' is not an interface");
848 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
850 public override TypeBuilder DefineType ()
857 if (TypeBuilder != null)
870 ifaces = GetClassBases (is_class, out parent, out error);
875 if (is_class && parent != null){
876 if (parent == TypeManager.enum_type ||
877 (parent == TypeManager.value_type && RootContext.StdLib) ||
878 parent == TypeManager.delegate_type ||
879 parent == TypeManager.array_type){
881 644, Location, "`" + Name + "' cannot inherit from " +
882 "special class `" + TypeManager.CSharpName (parent) + "'");
887 if (!is_class && TypeManager.value_type == null)
888 throw new Exception ();
890 // if (parent_builder is ModuleBuilder) {
892 ModuleBuilder builder = CodeGen.ModuleBuilder;
895 // Structs with no fields need to have a ".size 1"
899 if (!is_class && Fields == null)
900 TypeBuilder = builder.DefineType (Name,
903 PackingSize.Unspecified, 1);
906 // classes or structs with fields
908 TypeBuilder = builder.DefineType (Name,
913 TypeBuilder builder = Parent.TypeBuilder;
916 // Structs with no fields need to have a ".size 1"
919 if (!is_class && Fields == null)
920 TypeBuilder = builder.DefineNestedType (Basename,
923 PackingSize.Unspecified);
926 // classes or structs with fields
928 TypeBuilder = builder.DefineNestedType (Basename,
935 TypeManager.AddUserType (Name, TypeBuilder, this);
937 if (parent == TypeManager.attribute_type ||
938 parent.IsSubclassOf (TypeManager.attribute_type)) {
939 RootContext.RegisterAttribute (this);
940 TypeManager.RegisterAttrType (TypeBuilder, this);
942 RootContext.RegisterOrder (this);
944 if (Interfaces != null) {
945 foreach (Interface iface in Interfaces)
950 foreach (TypeContainer tc in Types)
954 if (Delegates != null) {
955 foreach (Delegate d in Delegates)
960 foreach (Enum en in Enums)
970 /// Defines the MemberCore objects that are in the `list' Arraylist
972 /// The `defined_names' array contains a list of members defined in
975 static ArrayList remove_list = new ArrayList ();
976 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
980 remove_list.Clear ();
982 foreach (MemberCore mc in list){
983 if (!mc.Define (this)){
984 remove_list.Add (mc);
988 if (defined_names == null)
991 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
994 if (RootContext.WarningLevel >= 4){
995 if ((mc.ModFlags & Modifiers.NEW) != 0)
996 Report109 (mc.Location, mc);
1001 if (defined_names [idx] is PropertyInfo &&
1002 ((mc.ModFlags & Modifiers.OVERRIDE) != 0)){
1006 #if WANT_TO_VERIFY_SIGNATURES_HERE
1007 if (defined_names [idx] is MethodBase && mc is MethodCore){
1008 MethodBase mb = (MethodBase) defined_names [idx];
1009 MethodCore met = (MethodCore) mc;
1011 if ((mb.IsVirtual || mb.IsAbstract) &&
1012 (mc.ModFlags & Modifiers.OVERRIDE) != 0)
1016 // FIXME: Compare the signatures here. If they differ,
1017 // then: `continue;'
1020 if ((mc.ModFlags & Modifiers.NEW) == 0)
1021 Report108 (mc.Location, defined_names [idx]);
1024 foreach (object o in remove_list)
1027 remove_list.Clear ();
1031 /// Populates our TypeBuilder with fields and methods
1033 public override bool Define (TypeContainer parent)
1035 MemberInfo [] defined_names = null;
1037 if (RootContext.WarningLevel > 1){
1041 // This code throws an exception in the comparer
1042 // I guess the string is not an object?
1044 ptype = TypeBuilder.BaseType;
1046 defined_names = FindMembers (
1047 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1048 BindingFlags.Public | BindingFlags.Instance |
1049 BindingFlags.Static, null, null);
1051 Array.Sort (defined_names, mif_compare);
1055 if (constants != null)
1056 DefineMembers (constants, defined_names);
1059 DefineMembers (fields, defined_names);
1062 if (instance_constructors == null){
1063 if (default_constructor == null)
1064 DefineDefaultConstructor (false);
1067 if (initialized_static_fields != null &&
1068 default_static_constructor == null)
1069 DefineDefaultConstructor (true);
1072 if (this is Struct){
1074 // Structs can not have initialized instance
1077 if (initialized_static_fields != null &&
1078 default_static_constructor == null)
1079 DefineDefaultConstructor (true);
1081 if (initialized_fields != null)
1082 ReportStructInitializedInstanceError ();
1085 RegisterRequiredImplementations ();
1088 // Constructors are not in the defined_names array
1090 if (instance_constructors != null)
1091 DefineMembers (instance_constructors, null);
1093 if (default_static_constructor != null)
1094 default_static_constructor.Define (this);
1096 if (methods != null)
1097 DefineMembers (methods, null);
1099 if (properties != null)
1100 DefineMembers (properties, defined_names);
1103 DefineMembers (events, defined_names);
1105 if (indexers != null) {
1106 foreach (Indexer i in Indexers)
1110 if (operators != null)
1111 DefineMembers (operators, null);
1114 DefineMembers (enums, defined_names);
1116 if (delegates != null)
1117 DefineMembers (delegates, defined_names);
1123 /// Looks up the alias for the name
1125 public string LookupAlias (string name)
1127 if (Namespace != null)
1128 return Namespace.LookupAlias (name);
1134 /// This function is based by a delegate to the FindMembers routine
1136 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1142 /// This filter is used by FindMembers, and we just keep
1143 /// a global for the filter to `AlwaysAccept'
1145 static MemberFilter accepting_filter;
1147 static bool IsVirtualFilter (MemberInfo m, object filterCriteria)
1149 if (!(m is MethodInfo))
1152 return ((MethodInfo) m).IsVirtual;
1156 /// This filter is used by FindMembers, and it is used to
1157 /// extract only virtual/abstract fields
1159 static MemberFilter virtual_method_filter;
1162 /// A member comparission method based on name only
1164 static IComparer mif_compare;
1166 static TypeContainer ()
1168 accepting_filter = new MemberFilter (AlwaysAccept);
1169 virtual_method_filter = new MemberFilter (IsVirtualFilter);
1170 mif_compare = new MemberInfoCompare ();
1174 /// This method returns the members of this type just like Type.FindMembers would
1175 /// Only, we need to use this for types which are _being_ defined because MS'
1176 /// implementation can't take care of that.
1179 // FIXME: return an empty static array instead of null, that cleans up
1180 // some code and is consistent with some coding conventions I just found
1184 // Notice that in various cases we check if our field is non-null,
1185 // something that would normally mean that there was a bug elsewhere.
1187 // The problem happens while we are defining p-invoke methods, as those
1188 // will trigger a FindMembers, but this happens before things are defined
1190 // Since the whole process is a no-op, it is fine to check for null here.
1192 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1193 MemberFilter filter, object criteria)
1195 ArrayList members = new ArrayList ();
1196 bool priv = (bf & BindingFlags.NonPublic) != 0;
1200 filter = accepting_filter;
1202 if ((mt & MemberTypes.Field) != 0) {
1203 if (fields != null) {
1204 foreach (Field f in fields) {
1205 if ((f.ModFlags & Modifiers.PRIVATE) != 0)
1209 FieldBuilder fb = f.FieldBuilder;
1210 if (fb != null && filter (fb, criteria) == true)
1215 if (constants != null) {
1216 foreach (Const con in constants) {
1217 if ((con.ModFlags & Modifiers.PRIVATE) != 0)
1221 FieldBuilder fb = con.FieldBuilder;
1222 if (fb != null && filter (fb, criteria) == true)
1228 if ((mt & MemberTypes.Method) != 0) {
1229 if (methods != null) {
1230 foreach (Method m in methods) {
1231 if ((m.ModFlags & Modifiers.PRIVATE) != 0)
1235 MethodBuilder mb = m.MethodBuilder;
1237 if (mb != null && filter (mb, criteria) == true)
1242 if (operators != null){
1243 foreach (Operator o in operators) {
1244 if ((o.ModFlags & Modifiers.PRIVATE) != 0)
1248 MethodBuilder ob = o.OperatorMethodBuilder;
1249 if (ob != null && filter (ob, criteria) == true)
1254 if (properties != null){
1255 foreach (Property p in properties){
1256 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1263 if (b != null && filter (b, criteria) == true)
1267 if (b != null && filter (b, criteria) == true)
1273 if ((mt & MemberTypes.Event) != 0) {
1275 foreach (Event e in events) {
1276 if ((e.ModFlags & Modifiers.PRIVATE) != 0)
1280 MemberInfo eb = e.EventBuilder;
1281 if (eb != null && filter (eb, criteria) == true)
1282 members.Add (e.EventBuilder);
1286 if ((mt & MemberTypes.Property) != 0){
1287 if (properties != null)
1288 foreach (Property p in properties) {
1289 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1293 MemberInfo pb = p.PropertyBuilder;
1294 if (pb != null && filter (pb, criteria) == true) {
1295 members.Add (p.PropertyBuilder);
1299 if (indexers != null)
1300 foreach (Indexer ix in indexers) {
1301 if ((ix.ModFlags & Modifiers.PRIVATE) != 0)
1305 MemberInfo ib = ix.PropertyBuilder;
1306 if (ib != null && filter (ib, criteria) == true) {
1307 members.Add (ix.PropertyBuilder);
1312 if ((mt & MemberTypes.NestedType) != 0) {
1315 foreach (TypeContainer t in Types)
1316 if (filter (t.TypeBuilder, criteria) == true)
1317 members.Add (t.TypeBuilder);
1320 foreach (Enum en in Enums)
1321 if (filter (en.TypeBuilder, criteria) == true)
1322 members.Add (en.TypeBuilder);
1326 if ((mt & MemberTypes.Constructor) != 0){
1327 if (instance_constructors != null){
1328 foreach (Constructor c in instance_constructors){
1329 ConstructorBuilder cb = c.ConstructorBuilder;
1332 if (filter (cb, criteria) == true)
1337 if (default_static_constructor != null){
1338 ConstructorBuilder cb =
1339 default_static_constructor.ConstructorBuilder;
1341 if (filter (cb, criteria) == true)
1347 // Lookup members in parent if requested.
1349 if ((bf & BindingFlags.DeclaredOnly) == 0){
1352 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1354 members.AddRange (mi);
1357 int count = members.Count;
1359 MemberInfo [] mi = new MemberInfo [count];
1360 members.CopyTo (mi);
1367 public MemberInfo GetFieldFromEvent (EventExpr event_expr)
1369 EventInfo ei = event_expr.EventInfo;
1371 foreach (Event e in events) {
1373 if (e.FieldBuilder == null)
1376 if (Type.FilterName (e.FieldBuilder, ei.Name))
1377 return e.FieldBuilder;
1383 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1384 MemberFilter filter, object criteria)
1386 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1389 return tc.FindMembers (mt, bf, filter, criteria);
1391 return t.FindMembers (mt, bf, filter, criteria);
1395 // FindMethods will look for methods not only in the type `t', but in
1396 // any interfaces implemented by the type.
1398 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1399 MemberFilter filter, object criteria)
1405 /// Whether the specified method is an interface method implementation
1409 /// If a method in Type `t' (or null to look in all interfaces
1410 /// and the base abstract class) with name `Name', return type `ret_type' and
1411 /// arguments `args' implements an interface, this method will
1412 /// return the MethodInfo that this method implements.
1414 /// This will remove the method from the list of "pending" methods
1415 /// that are required to be implemented for this class as a side effect.
1418 public MethodInfo IsInterfaceMethod (Type t, string Name, Type ret_type, Type [] args,
1421 int arg_len = args.Length;
1423 if (pending_implementations == null)
1426 foreach (TypeAndMethods tm in pending_implementations){
1427 if (!(t == null || tm.type == t))
1431 foreach (MethodInfo m in tm.methods){
1437 if (Name != m.Name){
1442 if (ret_type != m.ReturnType){
1443 if (!((ret_type == null && m.ReturnType == TypeManager.void_type) ||
1444 (m.ReturnType == null && ret_type == TypeManager.void_type)))
1452 // Check if we have the same parameters
1454 if (tm.args [i].Length != arg_len){
1459 int j, top = args.Length;
1462 for (j = 0; j < top; j++){
1463 if (tm.args [i][j] != args[j]){
1474 tm.methods [i] = null;
1475 tm.found [i] = true;
1479 // If a specific type was requested, we can stop now.
1487 /// C# allows this kind of scenarios:
1488 /// interface I { void M (); }
1489 /// class X { public void M (); }
1490 /// class Y : X, I { }
1492 /// For that case, we create an explicit implementation function
1495 void DefineProxy (Type iface, MethodInfo parent_method, MethodInfo iface_method,
1498 MethodBuilder proxy;
1500 string proxy_name = iface.Name + "." + iface_method.Name;
1502 proxy = TypeBuilder.DefineMethod (
1504 MethodAttributes.HideBySig |
1505 MethodAttributes.NewSlot |
1506 MethodAttributes.Virtual,
1507 CallingConventions.Standard | CallingConventions.HasThis,
1508 parent_method.ReturnType, args);
1510 int top = args.Length;
1511 ILGenerator ig = proxy.GetILGenerator ();
1513 ig.Emit (OpCodes.Ldarg_0);
1514 for (int i = 0; i < top; i++){
1517 ig.Emit (OpCodes.Ldarg_1); break;
1519 ig.Emit (OpCodes.Ldarg_2); break;
1521 ig.Emit (OpCodes.Ldarg_3); break;
1523 ig.Emit (OpCodes.Ldarg, i - 1); break;
1526 ig.Emit (OpCodes.Call, parent_method);
1527 ig.Emit (OpCodes.Ret);
1529 TypeBuilder.DefineMethodOverride (proxy, iface_method);
1533 /// This function tells whether one of our parent classes implements
1534 /// the given method (which turns out, it is valid to have an interface
1535 /// implementation in a parent
1537 bool ParentImplements (Type iface_type, MethodInfo mi)
1541 Type [] args = TypeManager.GetArgumentTypes (mi);
1542 ms = new MethodSignature (mi.Name, mi.ReturnType, args);
1543 MemberInfo [] list = FindMembers (
1544 TypeBuilder.BaseType, MemberTypes.Method | MemberTypes.Property,
1545 BindingFlags.Public | BindingFlags.Instance,
1546 MethodSignature.method_signature_filter, ms);
1548 if (list == null || list.Length == 0)
1551 DefineProxy (iface_type, (MethodInfo) list [0], mi, args);
1556 /// Verifies that any pending abstract methods or interface methods
1557 /// were implemented.
1559 bool VerifyPendingMethods ()
1561 int top = pending_implementations.Length;
1562 bool errors = false;
1565 for (i = 0; i < top; i++){
1566 Type type = pending_implementations [i].type;
1569 foreach (MethodInfo mi in pending_implementations [i].methods){
1573 if (type.IsInterface){
1574 if (ParentImplements (type, mi))
1579 if (pending_implementations [i].found [j])
1580 extra = ". (method might be private or static)";
1583 "`" + Name + "' does not implement " +
1584 "interface member `" +
1585 type.FullName + "." + mi.Name + "'" + extra);
1589 "`" + Name + "' does not implement " +
1590 "inherited abstract member `" +
1591 type.FullName + "." + mi.Name + "'");
1601 /// Emits the values for the constants
1603 public void EmitConstants ()
1605 if (constants != null)
1606 foreach (Const con in constants)
1607 con.EmitConstant (this);
1612 /// Emits the code, this step is performed after all
1613 /// the types, enumerations, constructors
1617 if (instance_constructors != null)
1618 foreach (Constructor c in instance_constructors)
1621 if (default_static_constructor != null)
1622 default_static_constructor.Emit (this);
1624 if (methods != null)
1625 foreach (Method m in methods)
1628 if (operators != null)
1629 foreach (Operator o in operators)
1632 if (properties != null)
1633 foreach (Property p in properties)
1636 if (indexers != null) {
1637 foreach (Indexer ix in indexers)
1640 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (this, ModFlags, Location);
1642 TypeBuilder.SetCustomAttribute (cb);
1646 foreach (Field f in fields)
1649 if (events != null){
1650 foreach (Event e in Events)
1654 if (pending_implementations != null)
1655 if (!VerifyPendingMethods ())
1658 EmitContext ec = new EmitContext (
1659 this, Mono.CSharp.Location.Null, null, null,
1662 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1665 // Check for internal or private fields that were never assigned
1667 if (fields != null && RootContext.WarningLevel >= 3) {
1668 foreach (Field f in fields) {
1669 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1674 169, f.Location, "Private field " +
1675 MakeName (f.Name) + " is never used");
1680 // Only report 649 on level 4
1682 if (RootContext.WarningLevel < 4)
1685 if ((f.status & Field.Status.ASSIGNED) != 0)
1690 "Field " + MakeName (f.Name) + " is never assigned " +
1691 " to and will always have its default value");
1695 // if (types != null)
1696 // foreach (TypeContainer tc in types)
1700 public override void CloseType ()
1705 TypeBuilder.CreateType ();
1707 } catch (TypeLoadException){
1709 // This is fine, the code still created the type
1711 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1712 // Console.WriteLine (e.Message);
1714 Console.WriteLine ("In type: " + Name);
1719 foreach (Enum en in Enums)
1722 if (interface_order != null){
1723 foreach (Interface iface in interface_order)
1728 foreach (TypeContainer tc in Types)
1732 foreach (TypeContainer tc in Types)
1733 if (!(tc is Struct))
1737 if (Delegates != null)
1738 foreach (Delegate d in Delegates)
1742 public string MakeName (string n)
1744 return "`" + Name + "." + n + "'";
1747 public void Report108 (Location l, MemberInfo mi)
1750 108, l, "The keyword new is required on " +
1751 MakeName (mi.Name) + " because it hides `" +
1752 mi.ReflectedType.Name + "." + mi.Name + "'");
1755 public void Report109 (Location l, MemberCore mc)
1758 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1759 "inherited member, the keyword new is not required");
1762 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1768 // Performs the validation on a Method's modifiers (properties have
1769 // the same properties).
1771 public bool MethodModifiersValid (int flags, string n, Location loc)
1773 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1774 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1776 string name = MakeName (n);
1779 // At most one of static, virtual or override
1781 if ((flags & Modifiers.STATIC) != 0){
1782 if ((flags & vao) != 0){
1784 112, loc, "static method " + name + "can not be marked " +
1785 "as virtual, abstract or override");
1790 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1793 " marked as override cannot be marked as new or virtual");
1798 // If the declaration includes the abstract modifier, then the
1799 // declaration does not include static, virtual or extern
1801 if ((flags & Modifiers.ABSTRACT) != 0){
1802 if ((flags & Modifiers.EXTERN) != 0){
1804 180, loc, name + " can not be both abstract and extern");
1808 if ((flags & Modifiers.VIRTUAL) != 0){
1810 503, loc, name + " can not be both abstract and virtual");
1814 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1817 " is abstract but its container class is not");
1823 if ((flags & Modifiers.PRIVATE) != 0){
1824 if ((flags & vao) != 0){
1827 " virtual or abstract members can not be private");
1832 if ((flags & Modifiers.SEALED) != 0){
1833 if ((flags & Modifiers.OVERRIDE) == 0){
1836 " cannot be sealed because it is not an override");
1845 // Returns true if `type' is as accessible as the flags `flags'
1846 // given for this member
1848 static public bool AsAccessible (Type type, int flags)
1853 Hashtable builder_and_args;
1855 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1857 if (builder_and_args == null)
1858 builder_and_args = new Hashtable ();
1863 public class Class : TypeContainer {
1865 // Modifiers allowed in a class declaration
1867 public const int AllowedModifiers =
1870 Modifiers.PROTECTED |
1871 Modifiers.INTERNAL |
1873 Modifiers.ABSTRACT |
1877 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1878 : base (parent, name, l)
1882 if (parent.Parent == null)
1883 accmods = Modifiers.INTERNAL;
1885 accmods = Modifiers.PRIVATE;
1887 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1888 this.attributes = attrs;
1892 // FIXME: How do we deal with the user specifying a different
1895 public override TypeAttributes TypeAttr {
1897 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1902 public class Struct : TypeContainer {
1904 // Modifiers allowed in a struct declaration
1906 public const int AllowedModifiers =
1909 Modifiers.PROTECTED |
1910 Modifiers.INTERNAL |
1914 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1915 : base (parent, name, l)
1919 if (parent.Parent == null)
1920 accmods = Modifiers.INTERNAL;
1922 accmods = Modifiers.PRIVATE;
1924 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1926 this.ModFlags |= Modifiers.SEALED;
1927 this.attributes = attrs;
1932 // FIXME: Allow the user to specify a different set of attributes
1933 // in some cases (Sealed for example is mandatory for a class,
1934 // but what SequentialLayout can be changed
1936 public override TypeAttributes TypeAttr {
1938 return base.TypeAttr |
1939 TypeAttributes.SequentialLayout |
1940 TypeAttributes.Sealed |
1941 TypeAttributes.BeforeFieldInit;
1946 public abstract class MethodCore : MemberCore {
1947 public readonly Parameters Parameters;
1951 // Parameters, cached for semantic analysis.
1953 InternalParameters parameter_info;
1955 public MethodCore (string name, Parameters parameters, Location l)
1959 Parameters = parameters;
1963 // Returns the System.Type array for the parameters of this method
1965 Type [] parameter_types;
1966 public Type [] ParameterTypes (TypeContainer parent)
1968 if (Parameters == null)
1969 return TypeManager.NoTypes;
1971 if (parameter_types == null)
1972 parameter_types = Parameters.GetParameterInfo (parent);
1974 return parameter_types;
1977 public InternalParameters ParameterInfo
1980 return parameter_info;
1984 parameter_info = value;
1988 public Block Block {
1998 public CallingConventions GetCallingConvention (bool is_class)
2000 CallingConventions cc = 0;
2002 cc = Parameters.GetCallingConvention ();
2005 if ((ModFlags & Modifiers.STATIC) == 0)
2006 cc |= CallingConventions.HasThis;
2008 // FIXME: How is `ExplicitThis' used in C#?
2013 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2016 // Define each type attribute (in/out/ref) and
2017 // the argument names.
2019 Parameter [] p = Parameters.FixedParameters;
2022 MethodBuilder mb = null;
2023 ConstructorBuilder cb = null;
2025 if (builder is MethodBuilder)
2026 mb = (MethodBuilder) builder;
2028 cb = (ConstructorBuilder) builder;
2031 for (i = 0; i < p.Length; i++) {
2032 ParameterBuilder pb;
2035 pb = cb.DefineParameter (
2036 i + 1, p [i].Attributes, p [i].Name);
2038 pb = mb.DefineParameter (
2039 i + 1, p [i].Attributes, p [i].Name);
2041 Attributes attr = p [i].OptAttributes;
2043 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2047 if (Parameters.ArrayParameter != null){
2048 ParameterBuilder pb;
2049 Parameter array_param = Parameters.ArrayParameter;
2052 pb = cb.DefineParameter (
2053 i + 1, array_param.Attributes,
2056 pb = mb.DefineParameter (
2057 i + 1, array_param.Attributes,
2060 CustomAttributeBuilder a = new CustomAttributeBuilder (
2061 TypeManager.cons_param_array_attribute, new object [0]);
2063 pb.SetCustomAttribute (a);
2068 public class Method : MethodCore {
2069 public readonly string ReturnType;
2070 public MethodBuilder MethodBuilder;
2071 public readonly Attributes OptAttributes;
2073 MethodAttributes flags;
2076 /// Modifiers allowed in a class declaration
2078 const int AllowedModifiers =
2081 Modifiers.PROTECTED |
2082 Modifiers.INTERNAL |
2087 Modifiers.OVERRIDE |
2088 Modifiers.ABSTRACT |
2093 // return_type can be "null" for VOID values.
2095 public Method (string return_type, int mod, string name, Parameters parameters,
2096 Attributes attrs, Location l)
2097 : base (name, parameters, l)
2099 ReturnType = return_type;
2100 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
2101 OptAttributes = attrs;
2105 // Returns the `System.Type' for the ReturnType of this
2106 // function. Provides a nice cache. (used between semantic analysis
2107 // and actual code generation
2109 Type type_return_type;
2111 public Type GetReturnType (TypeContainer parent)
2113 if (type_return_type == null)
2114 type_return_type = RootContext.LookupType (
2115 parent, ReturnType, false, Location);
2117 return type_return_type;
2120 void DuplicateEntryPoint (MethodInfo b, Location location)
2124 "Program `" + CodeGen.FileName +
2125 "' has more than one entry point defined: `" +
2126 TypeManager.CSharpSignature(b) + "'");
2129 void Report28 (MethodInfo b)
2131 if (RootContext.WarningLevel < 4)
2136 "`" + TypeManager.CSharpSignature(b) +
2137 "' has the wrong signature to be an entry point");
2140 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2142 if (b.ReturnType != TypeManager.void_type &&
2143 b.ReturnType != TypeManager.int32_type)
2146 if (pinfo.Count == 0)
2149 if (pinfo.Count > 1)
2152 Type t = pinfo.ParameterType(0);
2154 (t.GetArrayRank() == 1) &&
2155 (t.GetElementType() == TypeManager.string_type) &&
2156 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2165 public override bool Define (TypeContainer parent)
2167 Type ret_type = GetReturnType (parent);
2168 Type [] parameters = ParameterTypes (parent);
2170 MethodInfo implementing;
2171 Type iface_type = null;
2172 string iface = "", short_name;
2173 bool explicit_impl = false;
2175 // Check if the return type and arguments were correct
2176 if (ret_type == null || parameters == null)
2179 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2182 flags = Modifiers.MethodAttr (ModFlags);
2185 // verify accessibility
2187 if (!TypeContainer.AsAccessible (ret_type, ModFlags))
2190 if (ret_type.IsPointer && !UnsafeOK (parent))
2193 foreach (Type partype in parameters){
2194 if (!TypeContainer.AsAccessible (partype, ModFlags))
2196 if (partype.IsPointer && !UnsafeOK (parent))
2204 // Verify if the parent has a type with the same name, and then
2205 // check whether we have to create a new slot for it or not.
2207 Type ptype = parent.TypeBuilder.BaseType;
2209 // ptype is only null for System.Object while compiling corlib.
2211 MethodSignature ms = new MethodSignature (Name, ret_type, parameters);
2212 MemberInfo [] mi, mi_static, mi_instance;
2214 mi_static = TypeContainer.FindMembers (
2215 ptype, MemberTypes.Method,
2216 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2217 MethodSignature.inheritable_method_signature_filter, ms);
2219 mi_instance = TypeContainer.FindMembers (
2220 ptype, MemberTypes.Method,
2221 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2222 MethodSignature.inheritable_method_signature_filter,
2225 if (mi_instance != null && mi_instance.Length > 0){
2227 } else if (mi_static != null && mi_static.Length > 0)
2232 if (mi != null && mi.Length > 0){
2233 if (!CheckMethodAgainstBase (parent, flags, (MethodInfo) mi [0])){
2237 if ((ModFlags & Modifiers.NEW) != 0)
2238 WarningNotHiding (parent);
2240 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2241 Report.Error (115, Location,
2242 parent.MakeName (Name) +
2243 " no suitable methods found to override");
2246 } else if ((ModFlags & Modifiers.NEW) != 0)
2247 WarningNotHiding (parent);
2250 // If we implement an interface, extract the interface name.
2253 if (Name.IndexOf (".") != -1){
2254 int pos = Name.LastIndexOf (".");
2255 iface = Name.Substring (0, pos);
2257 iface_type = RootContext.LookupType (parent, iface, false, Location);
2258 short_name = Name.Substring (pos + 1);
2260 if (iface_type == null)
2263 // Compute the full name that we need to export
2264 Name = iface_type.FullName + "." + short_name;
2265 explicit_impl = true;
2270 // Check if we are an implementation of an interface method or
2273 implementing = parent.IsInterfaceMethod (
2274 iface_type, short_name, ret_type, parameters, false);
2277 // For implicit implementations, make sure we are public, for
2278 // explicit implementations, make sure we are private.
2280 if (implementing != null){
2282 // Setting null inside this block will trigger a more
2283 // verbose error reporting for missing interface implementations
2285 // The "candidate" function has been flagged already
2286 // but it wont get cleared
2288 if (iface_type == null){
2290 // We already catch different accessibility settings
2291 // so we just need to check that we are not private
2293 if ((ModFlags & Modifiers.PRIVATE) != 0)
2294 implementing = null;
2297 // Static is not allowed
2299 if ((ModFlags & Modifiers.STATIC) != 0)
2300 implementing = null;
2302 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2304 106, Location, "`public' or `abstract' modifiers "+
2305 "are not allowed in explicit interface declarations"
2307 implementing = null;
2313 // If implementing is still valid, set flags
2315 if (implementing != null){
2316 if (implementing.DeclaringType.IsInterface)
2317 flags |= MethodAttributes.NewSlot;
2320 MethodAttributes.Virtual |
2321 MethodAttributes.HideBySig;
2326 parent.IsInterfaceMethod (
2327 iface_type, short_name, ret_type, parameters, true);
2330 Attribute dllimport_attr = null;
2331 if (OptAttributes != null && OptAttributes.AttributeSections != null) {
2332 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2333 if (asec.Attributes == null)
2336 foreach (Attribute a in asec.Attributes)
2337 if (a.Name.IndexOf ("DllImport") != -1) {
2338 flags |= MethodAttributes.PinvokeImpl;
2345 // Finally, define the method
2348 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2350 if ((ModFlags & Modifiers.STATIC) == 0) {
2351 Report.Error (601, Location, "The DllImport attribute must be specified on " +
2352 "a method marked 'static' and 'extern'.");
2356 EmitContext ec = new EmitContext (
2357 parent, Location, null, GetReturnType (parent), ModFlags);
2359 MethodBuilder = dllimport_attr.DefinePInvokeMethod (
2360 ec, parent.TypeBuilder,
2361 Name, flags, ret_type, parameters);
2363 MethodBuilder = parent.TypeBuilder.DefineMethod (
2365 GetCallingConvention (parent is Class),
2366 ret_type, parameters);
2368 if (implementing != null && explicit_impl)
2369 parent.TypeBuilder.DefineMethodOverride (
2370 MethodBuilder, implementing);
2373 if (MethodBuilder == null)
2377 // HACK because System.Reflection.Emit is lame
2379 ParameterInfo = new InternalParameters (parent, Parameters);
2381 if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo,
2385 "Class `" + parent.Name + "' already contains a definition with " +
2386 " the same return value and parameter types for method `" +
2392 // This is used to track the Entry Point,
2394 if (Name == "Main" &&
2395 ((ModFlags & Modifiers.STATIC) != 0) &&
2396 (RootContext.MainClass == null ||
2397 RootContext.MainClass == parent.TypeBuilder.FullName)){
2398 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2399 if (RootContext.EntryPoint == null) {
2400 RootContext.EntryPoint = MethodBuilder;
2401 RootContext.EntryPointLocation = Location;
2403 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2404 DuplicateEntryPoint (MethodBuilder, Location);
2407 Report28(MethodBuilder);
2416 public void Emit (TypeContainer parent)
2421 if ((flags & MethodAttributes.PinvokeImpl) == 0)
2422 ig = MethodBuilder.GetILGenerator ();
2426 ec = new EmitContext (parent, Location, ig, GetReturnType (parent), ModFlags);
2428 if (OptAttributes != null)
2429 Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location);
2432 LabelParameters (ec, ParameterTypes (parent), MethodBuilder);
2435 // abstract or extern methods have no bodies
2437 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
2441 // Handle destructors specially
2443 // FIXME: This code generates buggy code
2445 if (Name == "Finalize" && type_return_type == TypeManager.void_type)
2446 EmitDestructor (ec);
2448 ISymbolWriter sw = CodeGen.SymbolWriter;
2450 if ((sw != null) && (!Location.IsNull (Location))) {
2451 MethodToken token = MethodBuilder.GetToken ();
2452 sw.OpenMethod (new SymbolToken (token.Token));
2453 sw.SetMethodSourceRange (Location.SymbolDocument,
2455 Block.EndLocation.SymbolDocument,
2456 Block.EndLocation.Row, 0);
2458 ec.EmitTopBlock (Block, Location);
2462 ec.EmitTopBlock (Block, Location);
2466 void EmitDestructor (EmitContext ec)
2468 ILGenerator ig = ec.ig;
2470 Label finish = ig.DefineLabel ();
2471 bool old_in_try = ec.InTry;
2472 Expression member_lookup;
2474 ig.BeginExceptionBlock ();
2476 ec.ReturnLabel = finish;
2477 ec.EmitTopBlock (Block, Location);
2478 ec.InTry = old_in_try;
2480 ig.MarkLabel (finish);
2481 bool old_in_finally = ec.InFinally;
2482 ec.InFinally = true;
2483 ig.BeginFinallyBlock ();
2485 member_lookup = Expression.MemberLookup (
2486 ec, ec.ContainerType.BaseType, "Finalize",
2487 MemberTypes.Method, Expression.AllBindingFlags, Location);
2489 if (member_lookup != null){
2490 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
2492 ig.Emit (OpCodes.Ldarg_0);
2493 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
2495 ec.InFinally = old_in_finally;
2497 ig.EndExceptionBlock ();
2498 //ig.MarkLabel (ec.ReturnLabel);
2499 ig.Emit (OpCodes.Ret);
2503 public abstract class ConstructorInitializer {
2504 ArrayList argument_list;
2505 ConstructorInfo parent_constructor;
2508 public ConstructorInitializer (ArrayList argument_list, Location location)
2510 this.argument_list = argument_list;
2511 this.location = location;
2514 public ArrayList Arguments {
2516 return argument_list;
2520 public bool Resolve (EmitContext ec)
2522 Expression parent_constructor_group;
2525 if (argument_list != null){
2526 foreach (Argument a in argument_list){
2527 if (!a.Resolve (ec, location))
2532 if (this is ConstructorBaseInitializer)
2533 t = ec.ContainerType.BaseType;
2535 t = ec.ContainerType;
2537 parent_constructor_group = Expression.MemberLookup (
2539 MemberTypes.Constructor,
2540 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2543 if (parent_constructor_group == null){
2544 Report.Error (1501, location,
2545 "Can not find a constructor for this argument list");
2549 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2550 (MethodGroupExpr) parent_constructor_group, argument_list, location);
2552 if (parent_constructor == null){
2553 Report.Error (1501, location,
2554 "Can not find a constructor for this argument list");
2561 public void Emit (EmitContext ec)
2563 ec.ig.Emit (OpCodes.Ldarg_0);
2564 if (argument_list != null)
2565 Invocation.EmitArguments (ec, null, argument_list);
2566 ec.ig.Emit (OpCodes.Call, parent_constructor);
2570 public class ConstructorBaseInitializer : ConstructorInitializer {
2571 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2576 public class ConstructorThisInitializer : ConstructorInitializer {
2577 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2582 public class Constructor : MethodCore {
2583 public ConstructorBuilder ConstructorBuilder;
2584 public ConstructorInitializer Initializer;
2585 public Attributes OptAttributes;
2588 // Modifiers allowed for a constructor.
2590 const int AllowedModifiers =
2592 Modifiers.PROTECTED |
2593 Modifiers.INTERNAL |
2599 // The spec claims that static is not permitted, but
2600 // my very own code has static constructors.
2602 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2603 : base (name, args, l)
2609 // Returns true if this is a default constructor
2611 public bool IsDefault ()
2613 if ((ModFlags & Modifiers.STATIC) != 0)
2614 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2615 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2618 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2619 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2620 (Initializer is ConstructorBaseInitializer) &&
2621 (Initializer.Arguments == null);
2625 // Creates the ConstructorBuilder
2627 public override bool Define (TypeContainer parent)
2629 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2630 MethodAttributes.SpecialName);
2632 Type [] parameters = ParameterTypes (parent);
2634 if ((ModFlags & Modifiers.STATIC) != 0)
2635 ca |= MethodAttributes.Static;
2637 if (parent is Struct && parameters.Length == 0){
2640 "Structs can not contain explicit parameterless " +
2644 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2647 foreach (Type partype in parameters)
2648 if (!TypeContainer.AsAccessible (partype, ModFlags))
2651 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2652 ca, GetCallingConvention (parent is Class), parameters);
2655 // HACK because System.Reflection.Emit is lame
2657 ParameterInfo = new InternalParameters (parent, Parameters);
2659 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
2662 "Class `" +parent.Name+ "' already contains a definition with the " +
2663 "same return value and parameter types for constructor `" + Name
2674 public void Emit (TypeContainer parent)
2676 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2677 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2679 if (parent is Class && ((ModFlags & Modifiers.STATIC) == 0)){
2680 if (Initializer == null)
2681 Initializer = new ConstructorBaseInitializer (null, parent.Location);
2685 // Spec mandates that Initializers will not have
2689 if (!Initializer.Resolve (ec))
2691 ec.IsStatic = false;
2694 LabelParameters (ec, ParameterTypes (parent), ConstructorBuilder);
2697 // Classes can have base initializers and instance field initializers.
2699 if (parent is Class){
2700 if ((ModFlags & Modifiers.STATIC) == 0){
2701 parent.EmitFieldInitializers (ec);
2703 Initializer.Emit (ec);
2707 if ((ModFlags & Modifiers.STATIC) != 0)
2708 parent.EmitFieldInitializers (ec);
2710 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2712 ec.EmitTopBlock (Block, Location);
2717 // Fields and Events both generate FieldBuilders, we use this to share
2718 // their common bits. This is also used to flag usage of the field
2720 abstract public class FieldBase : MemberCore {
2721 public readonly string Type;
2722 public readonly Object Initializer;
2723 public readonly Attributes OptAttributes;
2724 public FieldBuilder FieldBuilder;
2725 public Status status;
2728 public enum Status : byte { ASSIGNED = 1, USED = 2 }
2731 // The constructor is only exposed to our children
2733 protected FieldBase (string type, int mod, int allowed_mod, string name,
2734 object init, Attributes attrs, Location loc)
2738 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
2740 OptAttributes = attrs;
2745 // The Field class is used to represents class/struct fields during parsing.
2747 public class Field : FieldBase {
2749 // Modifiers allowed in a class declaration
2751 const int AllowedModifiers =
2754 Modifiers.PROTECTED |
2755 Modifiers.INTERNAL |
2758 Modifiers.VOLATILE |
2762 public Field (string type, int mod, string name, Object expr_or_array_init,
2763 Attributes attrs, Location loc)
2764 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
2768 public override bool Define (TypeContainer parent)
2770 Type t = RootContext.LookupType (parent, Type, false, Location);
2775 if (!TypeContainer.AsAccessible (t, ModFlags))
2778 if (t.IsPointer && !UnsafeOK (parent))
2781 if (RootContext.WarningLevel > 1){
2782 Type ptype = parent.TypeBuilder.BaseType;
2784 // ptype is only null for System.Object while compiling corlib.
2788 mi = TypeContainer.FindMembers (
2789 ptype, MemberTypes.Method,
2790 BindingFlags.Public |
2791 BindingFlags.Static | BindingFlags.Instance,
2792 System.Type.FilterName, Name);
2796 if ((ModFlags & Modifiers.VOLATILE) != 0){
2798 if (TypeManager.IsEnumType (t))
2799 t = TypeManager.EnumToUnderlying (t);
2801 if (!((t == TypeManager.bool_type) ||
2802 (t == TypeManager.sbyte_type) ||
2803 (t == TypeManager.byte_type) ||
2804 (t == TypeManager.short_type) ||
2805 (t == TypeManager.ushort_type) ||
2806 (t == TypeManager.int32_type) ||
2807 (t == TypeManager.uint32_type) ||
2808 (t == TypeManager.char_type) ||
2809 (t == TypeManager.float_type))){
2811 677, Location, parent.MakeName (Name) +
2812 " A volatile field can not be of type `" +
2813 TypeManager.CSharpName (t) + "'");
2819 FieldBuilder = parent.TypeBuilder.DefineField (
2820 Name, t, Modifiers.FieldAttr (ModFlags));
2822 TypeManager.RegisterFieldBase (FieldBuilder, this);
2826 public void Emit (TypeContainer tc)
2828 EmitContext ec = new EmitContext (tc, Location, null,
2829 FieldBuilder.FieldType, ModFlags);
2831 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
2836 // `set' and `get' accessors are represented with an Accessor.
2838 public class Accessor {
2840 // Null if the accessor is empty, or a Block if not
2844 public Accessor (Block b)
2850 public class Property : MemberCore {
2851 public readonly string Type;
2852 public Accessor Get, Set;
2853 public PropertyBuilder PropertyBuilder;
2854 public Attributes OptAttributes;
2855 public MethodBuilder GetBuilder, SetBuilder;
2858 // The type, once we compute it.
2862 const int AllowedModifiers =
2865 Modifiers.PROTECTED |
2866 Modifiers.INTERNAL |
2870 Modifiers.OVERRIDE |
2871 Modifiers.ABSTRACT |
2876 public Property (string type, string name, int mod_flags,
2877 Accessor get_block, Accessor set_block,
2878 Attributes attrs, Location loc)
2882 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
2885 OptAttributes = attrs;
2889 // Checks our base implementation if any
2891 bool CheckBase (MethodAttributes flags, TypeContainer parent)
2894 // Find properties with the same name on the base class
2897 MemberInfo [] props;
2898 MemberInfo [] props_static = TypeManager.MemberLookup (
2900 parent.TypeBuilder.BaseType,
2901 MemberTypes.Property, BindingFlags.Public | BindingFlags.Static,
2904 MemberInfo [] props_instance = TypeManager.MemberLookup (
2906 parent.TypeBuilder.BaseType,
2907 MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance,
2911 // Find if we have anything
2913 if (props_static != null && props_static.Length > 0)
2914 props = props_static;
2915 else if (props_instance != null && props_instance.Length > 0)
2916 props = props_instance;
2921 // If we have something on the base.
2922 if (props != null && props.Length > 0){
2923 if (props.Length > 1)
2924 throw new Exception ("Should not happen");
2926 PropertyInfo pi = (PropertyInfo) props [0];
2928 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
2929 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
2931 MethodInfo reference = inherited_get == null ?
2932 inherited_set : inherited_get;
2934 if (reference != null)
2935 if (!CheckMethodAgainstBase (parent, flags, reference))
2939 if ((ModFlags & Modifiers.NEW) != 0)
2940 WarningNotHiding (parent);
2942 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2943 Report.Error (115, Location,
2944 parent.MakeName (Name) +
2945 " no suitable properties found to override");
2952 bool DefineMethod (TypeContainer parent, Type iface_type, string short_name,
2953 MethodAttributes flags, bool is_get)
2955 Type [] parameters = TypeManager.NoTypes;
2956 MethodInfo implementing;
2961 fn_type = PropertyType;
2962 name = "get_" + short_name;
2964 name = "set_" + short_name;
2965 parameters = new Type [1];
2966 parameters [0] = PropertyType;
2967 fn_type = TypeManager.void_type;
2970 implementing = parent.IsInterfaceMethod (
2971 iface_type, name, fn_type, parameters, false);
2974 // For implicit implementations, make sure we are public, for
2975 // explicit implementations, make sure we are private.
2977 if (implementing != null){
2979 // Setting null inside this block will trigger a more
2980 // verbose error reporting for missing interface implementations
2982 // The "candidate" function has been flagged already
2983 // but it wont get cleared
2985 if (iface_type == null){
2987 // We already catch different accessibility settings
2988 // so we just need to check that we are not private
2990 if ((ModFlags & Modifiers.PRIVATE) != 0)
2991 implementing = null;
2994 // Static is not allowed
2996 if ((ModFlags & Modifiers.STATIC) != 0)
2997 implementing = null;
2999 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
3001 106, Location, "`public' or `abstract' modifiers "+
3002 "are not allowed in explicit interface declarations"
3004 implementing = null;
3010 // If implementing is still valid, set flags
3012 if (implementing != null){
3014 // When implementing interface methods, set NewSlot.
3016 if (implementing.DeclaringType.IsInterface)
3017 flags |= MethodAttributes.NewSlot;
3020 MethodAttributes.Virtual |
3021 MethodAttributes.HideBySig;
3024 // clear the pending flag
3026 parent.IsInterfaceMethod (
3027 iface_type, name, fn_type, parameters, true);
3031 // If this is not an explicit interface implementation,
3032 // clear implementing, as it is only used for explicit
3033 // interface implementation
3035 if (Name.IndexOf (".") == -1)
3036 implementing = null;
3039 GetBuilder = parent.TypeBuilder.DefineMethod (
3040 name, flags, PropertyType, null);
3041 PropertyBuilder.SetGetMethod (GetBuilder);
3043 if (implementing != null)
3044 parent.TypeBuilder.DefineMethodOverride (
3045 GetBuilder, implementing);
3048 // HACK because System.Reflection.Emit is lame
3050 InternalParameters ip = new InternalParameters (
3051 parent, Parameters.GetEmptyReadOnlyParameters ());
3053 if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) {
3054 Report.Error (111, Location,
3055 "Class `" + parent.Name +
3056 "' already contains a definition with the " +
3057 "same return value and parameter types as the " +
3058 "'get' method of property `" + Name + "'");
3062 SetBuilder = parent.TypeBuilder.DefineMethod (
3063 name, flags, null, parameters);
3065 if (implementing != null)
3066 parent.TypeBuilder.DefineMethodOverride (
3067 SetBuilder, implementing);
3069 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3070 PropertyBuilder.SetSetMethod (SetBuilder);
3073 // HACK because System.Reflection.Emit is lame
3075 Parameter [] parms = new Parameter [1];
3076 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3077 InternalParameters ip = new InternalParameters (
3078 parent, new Parameters (parms, null, Location));
3080 if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) {
3083 "Class `" + parent.Name +
3084 "' already contains a definition with the " +
3085 "same return value and parameter types as the " +
3086 "'set' method of property `" + Name + "'");
3094 public override bool Define (TypeContainer parent)
3096 Type iface_type = null;
3099 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3102 MethodAttributes flags = Modifiers.MethodAttr (ModFlags);
3104 flags |= MethodAttributes.HideBySig |
3105 MethodAttributes.SpecialName;
3107 // Lookup Type, verify validity
3108 PropertyType = RootContext.LookupType (parent, Type, false, Location);
3109 if (PropertyType == null)
3112 // verify accessibility
3113 if (!TypeContainer.AsAccessible (PropertyType, ModFlags))
3116 if (PropertyType.IsPointer && !UnsafeOK (parent))
3119 if (!CheckBase (flags, parent))
3123 // Check for explicit interface implementation
3125 if (Name.IndexOf (".") != -1){
3126 int pos = Name.LastIndexOf (".");
3127 string iface = Name.Substring (0, pos);
3129 iface_type = RootContext.LookupType (parent, iface, false, Location);
3130 if (iface_type == null)
3133 short_name = Name.Substring (pos + 1);
3135 // Compute the full name that we need to export.
3136 Name = iface_type.FullName + "." + short_name;
3140 // FIXME - PropertyAttributes.HasDefault ?
3142 PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
3143 PropertyAttributes.SpecialName;
3145 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3146 Name, prop_attr, PropertyType, null);
3149 if (!DefineMethod (parent, iface_type, short_name, flags, true))
3153 if (!DefineMethod (parent, iface_type, short_name, flags, false))
3157 // HACK for the reasons exposed above
3159 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3162 "Class `" + parent.Name +
3163 "' already contains a definition for the property `" +
3171 public void Emit (TypeContainer tc)
3176 ec = new EmitContext (tc, Location, null, PropertyType, ModFlags);
3177 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3181 // abstract or extern properties have no bodies
3183 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3187 ig = GetBuilder.GetILGenerator ();
3188 ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags);
3190 ec.EmitTopBlock (Get.Block, Location);
3194 ig = SetBuilder.GetILGenerator ();
3195 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3197 ec.EmitTopBlock (Set.Block, Location);
3204 /// Gigantic workaround for lameness in SRE follows :
3205 /// This class derives from EventInfo and attempts to basically
3206 /// wrap around the EventBuilder so that FindMembers can quickly
3207 /// return this in it search for members
3209 public class MyEventBuilder : EventInfo {
3212 // We use this to "point" to our Builder which is
3213 // not really a MemberInfo
3215 EventBuilder MyBuilder;
3218 // We "catch" and wrap these methods
3220 MethodInfo raise, remove, add;
3222 EventAttributes attributes;
3223 Type declaring_type, reflected_type, event_type;
3226 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3228 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3230 // And now store the values in our own fields.
3232 declaring_type = type_builder;
3234 reflected_type = type_builder;
3236 attributes = event_attr;
3238 this.event_type = event_type;
3242 // Methods that you have to override. Note that you only need
3243 // to "implement" the variants that take the argument (those are
3244 // the "abstract" methods, the others (GetAddMethod()) are
3247 public override MethodInfo GetAddMethod (bool nonPublic)
3252 public override MethodInfo GetRemoveMethod (bool nonPublic)
3257 public override MethodInfo GetRaiseMethod (bool nonPublic)
3263 // These methods make "MyEventInfo" look like a Builder
3265 public void SetRaiseMethod (MethodBuilder raiseMethod)
3267 raise = raiseMethod;
3268 MyBuilder.SetRaiseMethod (raiseMethod);
3271 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3273 remove = removeMethod;
3274 MyBuilder.SetRemoveOnMethod (removeMethod);
3277 public void SetAddOnMethod (MethodBuilder addMethod)
3280 MyBuilder.SetAddOnMethod (addMethod);
3283 public void SetCustomAttribute (CustomAttributeBuilder cb)
3285 MyBuilder.SetCustomAttribute (cb);
3288 public override object [] GetCustomAttributes (bool inherit)
3290 // FIXME : There's nothing which can be seemingly done here because
3291 // we have no way of getting at the custom attribute objects of the
3296 public override object [] GetCustomAttributes (Type t, bool inherit)
3298 // FIXME : Same here !
3302 public override bool IsDefined (Type t, bool b)
3307 public override EventAttributes Attributes {
3313 public override string Name {
3319 public override Type DeclaringType {
3321 return declaring_type;
3325 public override Type ReflectedType {
3327 return reflected_type;
3331 public Type EventType {
3338 public class Event : FieldBase {
3339 const int AllowedModifiers =
3342 Modifiers.PROTECTED |
3343 Modifiers.INTERNAL |
3348 Modifiers.OVERRIDE |
3352 public readonly Block Add;
3353 public readonly Block Remove;
3354 public MyEventBuilder EventBuilder;
3357 MethodBuilder AddBuilder, RemoveBuilder;
3359 public Event (string type, string name, Object init, int mod, Block add_block,
3360 Block rem_block, Attributes attrs, Location loc)
3361 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
3367 public override bool Define (TypeContainer parent)
3369 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3372 MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
3373 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3375 EventType = RootContext.LookupType (parent, Type, false, Location);
3376 if (EventType == null)
3379 if (!TypeContainer.AsAccessible (EventType, ModFlags))
3382 if (EventType.IsPointer && !UnsafeOK (parent))
3385 if (!EventType.IsSubclassOf (TypeManager.delegate_type)) {
3386 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3387 "' : event must be of a delegate type");
3391 Type [] parameters = new Type [1];
3392 parameters [0] = EventType;
3394 EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType);
3396 if (Add == null && Remove == null){
3397 FieldBuilder = parent.TypeBuilder.DefineField (
3398 Name, EventType, FieldAttributes.Private);
3399 TypeManager.RegisterFieldBase (FieldBuilder, this);
3403 // Now define the accessors
3406 AddBuilder = parent.TypeBuilder.DefineMethod (
3407 "add_" + Name, m_attr, null, parameters);
3408 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3409 EventBuilder.SetAddOnMethod (AddBuilder);
3412 // HACK because System.Reflection.Emit is lame
3414 Parameter [] parms = new Parameter [1];
3415 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3416 InternalParameters ip = new InternalParameters (
3417 parent, new Parameters (parms, null, Location));
3419 if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) {
3420 Report.Error (111, Location,
3421 "Class `" + parent.Name + "' already contains a definition with the " +
3422 "same return value and parameter types for the " +
3423 "'add' method of event `" + Name + "'");
3427 RemoveBuilder = parent.TypeBuilder.DefineMethod (
3428 "remove_" + Name, m_attr, null, parameters);
3429 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3430 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3433 // HACK because System.Reflection.Emit is lame
3436 if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) {
3437 Report.Error (111, Location,
3438 "Class `" + parent.Name + "' already contains a definition with the " +
3439 "same return value and parameter types for the " +
3440 "'remove' method of event `" + Name + "'");
3444 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3445 Report.Error (111, Location,
3446 "Class `" + parent.Name +
3447 "' already contains a definition for the event `" +
3455 void EmitDefaultMethod (EmitContext ec, bool is_add)
3457 ILGenerator ig = ec.ig;
3458 MethodInfo method = null;
3461 method = TypeManager.delegate_combine_delegate_delegate;
3463 method = TypeManager.delegate_remove_delegate_delegate;
3465 ig.Emit (OpCodes.Ldarg_0);
3466 ig.Emit (OpCodes.Ldarg_0);
3467 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3468 ig.Emit (OpCodes.Ldarg_1);
3469 ig.Emit (OpCodes.Call, method);
3470 ig.Emit (OpCodes.Castclass, EventType);
3471 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3472 ig.Emit (OpCodes.Ret);
3475 public void Emit (TypeContainer tc)
3480 ig = AddBuilder.GetILGenerator ();
3481 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3484 ec.EmitTopBlock (Add, Location);
3486 EmitDefaultMethod (ec, true);
3488 ig = RemoveBuilder.GetILGenerator ();
3489 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3492 ec.EmitTopBlock (Remove, Location);
3494 EmitDefaultMethod (ec, false);
3496 ec = new EmitContext (tc, Location, null, EventType, ModFlags);
3497 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3504 // FIXME: This does not handle:
3506 // int INTERFACENAME [ args ]
3510 // int this [ args ]
3512 public class Indexer : MemberCore {
3514 const int AllowedModifiers =
3517 Modifiers.PROTECTED |
3518 Modifiers.INTERNAL |
3522 Modifiers.OVERRIDE |
3527 public readonly string Type;
3528 public readonly string InterfaceType;
3529 public readonly Parameters FormalParameters;
3530 public readonly Accessor Get, Set;
3531 public Attributes OptAttributes;
3532 public MethodBuilder GetBuilder;
3533 public MethodBuilder SetBuilder;
3534 public PropertyBuilder PropertyBuilder;
3535 public Type IndexerType;
3537 public Indexer (string type, string int_type, int flags, Parameters parms,
3538 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
3543 InterfaceType = int_type;
3544 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
3545 FormalParameters = parms;
3548 OptAttributes = attrs;
3551 void DefineMethod (TypeContainer parent, Type iface_type,
3552 Type ret_type, string name,
3553 Type [] parameters, MethodAttributes attr, bool is_get)
3555 MethodInfo implementing;
3557 implementing = parent.IsInterfaceMethod (
3558 iface_type, name, ret_type, parameters, false);
3561 // Setting null inside this block will trigger a more
3562 // verbose error reporting for missing interface implementations
3564 // The "candidate" function has been flagged already
3565 // but it wont get cleared
3567 if (implementing != null){
3568 if (iface_type == null){
3570 // We already catch different accessibility settings
3571 // so we just need to check that we are not private
3573 if ((ModFlags & Modifiers.PRIVATE) != 0)
3574 implementing = null;
3577 // Static is not allowed
3579 if ((ModFlags & Modifiers.STATIC) != 0)
3580 implementing = null;
3582 if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
3585 "`public' or `abstract' modifiers are not "+
3586 "allowed in explicit interface declarations"
3588 implementing = null;
3592 if (implementing != null){
3594 // When implementing interface methods, set NewSlot.
3596 if (implementing.DeclaringType.IsInterface)
3597 attr |= MethodAttributes.NewSlot;
3600 MethodAttributes.Virtual |
3601 MethodAttributes.HideBySig;
3604 // clear the pending flag
3606 parent.IsInterfaceMethod (
3607 iface_type, name, ret_type, parameters, true);
3611 // If this is not an explicit interface implementation,
3612 // clear implementing, as it is only used for explicit
3613 // interface implementation
3615 if (Name.IndexOf (".") == -1)
3616 implementing = null;
3620 string meth_name = "get_Item";
3621 if (iface_type != null)
3622 meth_name = iface_type + ".get_Item";
3624 GetBuilder = parent.TypeBuilder.DefineMethod (
3625 meth_name, attr, IndexerType, parameters);
3627 if (implementing != null)
3628 parent.TypeBuilder.DefineMethodOverride (
3629 GetBuilder, implementing);
3632 PropertyBuilder.SetGetMethod (GetBuilder);
3635 string meth_name = "set_Item";
3637 if (iface_type != null)
3638 meth_name = iface_type + ".set_Item";
3640 SetBuilder = parent.TypeBuilder.DefineMethod (
3641 meth_name, attr, null, parameters);
3642 if (implementing != null)
3643 parent.TypeBuilder.DefineMethodOverride (
3644 SetBuilder, implementing);
3646 PropertyBuilder.SetSetMethod (SetBuilder);
3650 public override bool Define (TypeContainer parent)
3652 PropertyAttributes prop_attr =
3653 PropertyAttributes.RTSpecialName |
3654 PropertyAttributes.SpecialName;
3657 IndexerType = RootContext.LookupType (parent, Type, false, Location);
3658 Type [] parameters = FormalParameters.GetParameterInfo (parent);
3660 // Check if the return type and arguments were correct
3661 if (IndexerType == null || parameters == null)
3664 if (!parent.MethodModifiersValid (ModFlags, InterfaceType == null ?
3665 "this" : InterfaceType, Location))
3669 // verify accessibility and unsafe pointers
3671 if (!TypeContainer.AsAccessible (IndexerType, ModFlags))
3674 if (IndexerType.IsPointer && !UnsafeOK (parent))
3677 foreach (Type partype in parameters){
3678 if (!TypeContainer.AsAccessible (partype, ModFlags))
3680 if (partype.IsPointer && !UnsafeOK (parent))
3687 Type iface_type = null;
3689 if (InterfaceType != null){
3690 iface_type = RootContext.LookupType (parent, InterfaceType, false, Location);
3691 if (iface_type == null)
3696 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3697 TypeManager.IndexerPropertyName (parent.TypeBuilder),
3698 prop_attr, IndexerType, parameters);
3700 MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
3703 DefineMethod (parent, iface_type, IndexerType, "get_Item",
3704 parameters, attr, true);
3705 InternalParameters pi = new InternalParameters (parent, FormalParameters);
3706 if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) {
3707 Report.Error (111, Location,
3708 "Class `" + parent.Name +
3709 "' already contains a definition with the " +
3710 "same return value and parameter types for the " +
3717 int top = parameters.Length;
3718 Type [] set_pars = new Type [top + 1];
3719 parameters.CopyTo (set_pars, 0);
3720 set_pars [top] = IndexerType;
3722 Parameter [] fixed_parms = FormalParameters.FixedParameters;
3724 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3726 fixed_parms.CopyTo (tmp, 0);
3727 tmp [fixed_parms.Length] = new Parameter (
3728 Type, "value", Parameter.Modifier.NONE, null);
3730 Parameters set_formal_params = new Parameters (tmp, null, Location);
3733 parent, iface_type, TypeManager.void_type,
3734 "set_Item", set_pars, attr, false);
3736 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3738 if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) {
3741 "Class `" + parent.Name + "' already contains a " +
3742 "definition with the " +
3743 "same return value and parameter types for the " +
3750 // Now name the parameters
3752 Parameter [] p = FormalParameters.FixedParameters;
3756 for (i = 0; i < p.Length; ++i) {
3758 GetBuilder.DefineParameter (
3759 i + 1, p [i].Attributes, p [i].Name);
3762 SetBuilder.DefineParameter (
3763 i + 1, p [i].Attributes, p [i].Name);
3767 SetBuilder.DefineParameter (
3768 i + 1, ParameterAttributes.None, "value");
3770 if (i != parameters.Length) {
3771 Parameter array_param = FormalParameters.ArrayParameter;
3772 SetBuilder.DefineParameter (i + 1, array_param.Attributes,
3777 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
3782 public void Emit (TypeContainer tc)
3787 ec = new EmitContext (tc, Location, null, IndexerType, ModFlags);
3788 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3790 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3794 ig = GetBuilder.GetILGenerator ();
3795 ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags);
3797 ec.EmitTopBlock (Get.Block, Location);
3801 ig = SetBuilder.GetILGenerator ();
3802 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3804 ec.EmitTopBlock (Set.Block, Location);
3809 public class Operator : MemberCore {
3811 const int AllowedModifiers =
3817 const int RequiredModifiers =
3821 public enum OpType : byte {
3831 // Unary and Binary operators
3854 // Implicit and Explicit
3859 public readonly OpType OperatorType;
3860 public readonly string ReturnType;
3861 public readonly string FirstArgType;
3862 public readonly string FirstArgName;
3863 public readonly string SecondArgType;
3864 public readonly string SecondArgName;
3865 public readonly Block Block;
3866 public Attributes OptAttributes;
3867 public MethodBuilder OperatorMethodBuilder;
3869 public string MethodName;
3870 public Method OperatorMethod;
3872 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
3873 string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
3876 OperatorType = type;
3877 ReturnType = ret_type;
3878 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
3879 FirstArgType = arg1type;
3880 FirstArgName = arg1name;
3881 SecondArgType = arg2type;
3882 SecondArgName = arg2name;
3884 OptAttributes = attrs;
3887 string Prototype (TypeContainer parent)
3889 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
3890 SecondArgType + ")";
3893 public override bool Define (TypeContainer parent)
3896 MethodName = "op_" + OperatorType;
3898 if (SecondArgType != null)
3901 Parameter [] param_list = new Parameter [length];
3903 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
3906 "User defined operators `" +
3907 Prototype (parent) +
3908 "' must be declared static and public");
3912 param_list[0] = new Parameter (FirstArgType, FirstArgName,
3913 Parameter.Modifier.NONE, null);
3914 if (SecondArgType != null)
3915 param_list[1] = new Parameter (SecondArgType, SecondArgName,
3916 Parameter.Modifier.NONE, null);
3918 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
3919 new Parameters (param_list, null, Location),
3920 OptAttributes, Mono.CSharp.Location.Null);
3922 OperatorMethod.Define (parent);
3924 if (OperatorMethod.MethodBuilder == null)
3927 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
3929 Type [] param_types = OperatorMethod.ParameterTypes (parent);
3930 Type declaring_type = OperatorMethodBuilder.DeclaringType;
3931 Type return_type = OperatorMethod.GetReturnType (parent);
3932 Type first_arg_type = param_types [0];
3934 // Rules for conversion operators
3936 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
3937 if (first_arg_type == return_type && first_arg_type == declaring_type){
3940 "User-defined conversion cannot take an object of the " +
3941 "enclosing type and convert to an object of the enclosing" +
3946 if (first_arg_type != declaring_type && return_type != declaring_type){
3949 "User-defined conversion must convert to or from the " +
3954 if (first_arg_type == TypeManager.object_type ||
3955 return_type == TypeManager.object_type){
3958 "User-defined conversion cannot convert to or from " +
3963 if (first_arg_type.IsInterface || return_type.IsInterface){
3966 "User-defined conversion cannot convert to or from an " +
3971 if (first_arg_type.IsSubclassOf (return_type) ||
3972 return_type.IsSubclassOf (first_arg_type)){
3975 "User-defined conversion cannot convert between types " +
3976 "that derive from each other");
3979 } else if (SecondArgType == null) {
3980 // Checks for Unary operators
3982 if (first_arg_type != declaring_type){
3985 "The parameter of a unary operator must be the " +
3990 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
3991 if (return_type != declaring_type){
3994 "The parameter and return type for ++ and -- " +
3995 "must be the containing type");
4001 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4002 if (return_type != TypeManager.bool_type){
4005 "The return type of operator True or False " +
4012 // Checks for Binary operators
4014 if (first_arg_type != declaring_type &&
4015 param_types [1] != declaring_type){
4018 "One of the parameters of a binary operator must " +
4019 "be the containing type");
4027 public void Emit (TypeContainer parent)
4029 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4030 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4033 // abstract or extern methods have no bodies
4035 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4038 OperatorMethod.Block = Block;
4039 OperatorMethod.Emit (parent);
4044 // This is used to compare method signatures
4046 struct MethodSignature {
4048 public Type RetType;
4049 public Type [] Parameters;
4052 /// This delegate is used to extract methods which have the
4053 /// same signature as the argument
4055 public static MemberFilter method_signature_filter;
4058 /// This delegate is used to extract inheritable methods which
4059 /// have the same signature as the argument. By inheritable,
4060 /// this means that we have permissions to override the method
4061 /// from the current assembly and class
4063 public static MemberFilter inheritable_method_signature_filter;
4065 static MethodSignature ()
4067 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4068 inheritable_method_signature_filter = new MemberFilter (
4069 InheritableMemberSignatureCompare);
4072 public MethodSignature (string name, Type ret_type, Type [] parameters)
4077 if (parameters == null)
4078 Parameters = TypeManager.NoTypes;
4080 Parameters = parameters;
4083 public override int GetHashCode ()
4085 return Name.GetHashCode ();
4088 public override bool Equals (Object o)
4090 MethodSignature other = (MethodSignature) o;
4092 if (other.Name != Name)
4095 if (other.RetType != RetType)
4098 if (Parameters == null){
4099 if (other.Parameters == null)
4104 if (other.Parameters == null)
4107 int c = Parameters.Length;
4108 if (other.Parameters.Length != c)
4111 for (int i = 0; i < c; i++)
4112 if (other.Parameters [i] != Parameters [i])
4118 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4122 if (! (m is MethodInfo))
4125 MethodSignature sig = (MethodSignature) filter_criteria;
4127 if (m.Name != sig.Name)
4130 mi = (MethodInfo) m;
4132 if (mi.ReturnType != sig.RetType)
4135 Type [] args = TypeManager.GetArgumentTypes (mi);
4136 Type [] sigp = sig.Parameters;
4138 if (args.Length != sigp.Length)
4141 for (int i = args.Length; i > 0; ){
4143 if (args [i] != sigp [i])
4150 // This filter should be used when we are requesting methods that
4151 // we want to override.
4153 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4155 if (MemberSignatureCompare (m, filter_criteria)){
4156 MethodInfo mi = (MethodInfo) m;
4157 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4159 // If only accessible to the current class.
4160 if (prot == MethodAttributes.Private)
4163 // If only accessible to the defining assembly or
4164 if (prot == MethodAttributes.FamANDAssem ||
4165 prot == MethodAttributes.Assembly){
4166 if (m is MethodBuilder)
4172 // Anything else (FamOrAssembly and Public) is fine