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 Assign a = new Assign (fe, e, l);
503 a = (Assign) a.Resolve (ec);
507 a.EmitStatement (ec);
514 // Defines the default constructors
516 void DefineDefaultConstructor (bool is_static)
521 c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
522 new ConstructorBaseInitializer (null, new Location (-1)),
526 mods = Modifiers.STATIC;
532 c.Block = new Block (null);
536 public void ReportStructInitializedInstanceError ()
538 string n = TypeBuilder.FullName;
540 foreach (Field f in initialized_fields){
543 "`" + n + "." + f.Name + "': can not have " +
544 "instance field initializers in structs");
548 struct TypeAndMethods {
550 public MethodInfo [] methods;
552 // Far from ideal, but we want to avoid creating a copy
554 public Type [][] args;
557 // This flag on the method says `We found a match, but
558 // because it was private, we could not use the match
560 public bool [] found;
564 // This array keeps track of the pending implementations
566 TypeAndMethods [] pending_implementations;
569 // Returns a list of the abstract methods that are exposed by all of our
570 // parents that we must implement. Notice that this `flattens' the
571 // method search space, and takes into account overrides.
573 ArrayList GetAbstractMethods (Type t)
575 ArrayList list = null;
576 bool searching = true;
577 Type current_type = t;
583 current_type, MemberTypes.Method,
584 BindingFlags.Public | BindingFlags.Instance |
585 BindingFlags.DeclaredOnly,
586 virtual_method_filter, null);
588 if (current_type == TypeManager.object_type)
591 current_type = current_type.BaseType;
592 if (!current_type.IsAbstract)
599 int count = mi.Length;
603 if (count == 1 && !(mi [0] is MethodBase))
606 list = TypeManager.CopyNewMethods (list, mi);
612 for (int i = 0; i < list.Count; i++){
613 while (list.Count > i && !((MethodInfo) list [i]).IsAbstract)
624 // Registers the required method implementations for this class
626 // Register method implementations are either abstract methods
627 // flagged as such on the base class or interface methods
629 public void RegisterRequiredImplementations ()
631 Type [] ifaces = TypeBuilder.GetInterfaces ();
632 Type b = TypeBuilder.BaseType;
637 Type x = TypeBuilder;
640 Type [] iff = x.GetInterfaces ();
641 Console.WriteLine ("Type: " + x.Name);
643 foreach (Type tt in iff){
644 Console.WriteLine (" Iface: " + tt.Name);
651 icount = ifaces.Length;
654 // If we are implementing an abstract class, and we are not
655 // ourselves abstract, and there are abstract methods (C# allows
656 // abstract classes that have no abstract methods), then allocate
659 // We also pre-compute the methods.
661 bool implementing_abstract = (b.IsAbstract && !TypeBuilder.IsAbstract);
662 ArrayList abstract_methods = null;
664 if (implementing_abstract){
665 abstract_methods = GetAbstractMethods (b);
667 if (abstract_methods == null)
668 implementing_abstract = false;
671 int total = icount + (implementing_abstract ? 1 : 0);
675 pending_implementations = new TypeAndMethods [total];
679 foreach (Type t in ifaces){
682 if (t is TypeBuilder){
685 iface = TypeManager.LookupInterface (t);
687 mi = iface.GetMethods ();
689 mi = t.GetMethods ();
691 int count = mi.Length;
692 pending_implementations [i].type = t;
693 pending_implementations [i].methods = mi;
694 pending_implementations [i].args = new Type [count][];
695 pending_implementations [i].found = new bool [count];
698 foreach (MethodInfo m in mi){
699 Type [] types = TypeManager.GetArgumentTypes (m);
701 pending_implementations [i].args [j] = types;
708 if (abstract_methods != null){
709 int count = abstract_methods.Count;
710 pending_implementations [i].methods = new MethodInfo [count];
712 abstract_methods.CopyTo (pending_implementations [i].methods, 0);
713 pending_implementations [i].found = new bool [count];
714 pending_implementations [i].args = new Type [count][];
715 pending_implementations [i].type = TypeBuilder;
718 foreach (MemberInfo m in abstract_methods){
719 MethodInfo mi = (MethodInfo) m;
721 Type [] types = TypeManager.GetArgumentTypes (mi);
723 pending_implementations [i].args [j] = types;
730 /// This function computes the Base class and also the
731 /// list of interfaces that the class or struct @c implements.
733 /// The return value is an array (might be null) of
734 /// interfaces implemented (as Types).
736 /// The @parent argument is set to the parent object or null
737 /// if this is `System.Object'.
739 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
741 ArrayList bases = Bases;
750 parent = TypeManager.value_type;
754 if (RootContext.StdLib)
755 parent = TypeManager.object_type;
756 else if (Name != "System.Object")
757 parent = TypeManager.object_type;
760 // If we are compiling our runtime,
761 // and we are defining ValueType, then our
762 // parent is `System.Object'.
764 if (!RootContext.StdLib && Name == "System.ValueType")
765 parent = TypeManager.object_type;
772 // Bases should be null if there are no bases at all
777 string name = (string) bases [0];
778 Type first = FindType (name);
789 parent = TypeManager.object_type;
797 Type [] ifaces = new Type [count-start];
799 for (i = start, j = 0; i < count; i++, j++){
800 string name = (string) bases [i];
801 Type t = FindType (name);
808 if (is_class == false && !t.IsInterface){
809 Report.Error (527, "In Struct `" + Name + "', type `"+
810 name +"' is not an interface");
819 detail = " (a class can not inherit from a struct/enum)";
821 Report.Error (509, "class `"+ Name +
822 "': Cannot inherit from sealed class `"+
823 bases [i]+"'"+detail);
830 Report.Error (527, "In Class `" + Name + "', type `"+
831 name+"' is not an interface");
844 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
846 public override TypeBuilder DefineType ()
853 if (TypeBuilder != null)
866 ifaces = GetClassBases (is_class, out parent, out error);
871 if (is_class && parent != null){
872 if (parent == TypeManager.enum_type ||
873 (parent == TypeManager.value_type && RootContext.StdLib) ||
874 parent == TypeManager.delegate_type ||
875 parent == TypeManager.array_type){
877 644, Location, "`" + Name + "' cannot inherit from " +
878 "special class `" + TypeManager.CSharpName (parent) + "'");
883 if (!is_class && TypeManager.value_type == null)
884 throw new Exception ();
886 // if (parent_builder is ModuleBuilder) {
888 ModuleBuilder builder = CodeGen.ModuleBuilder;
891 // Structs with no fields need to have a ".size 1"
895 if (!is_class && Fields == null)
896 TypeBuilder = builder.DefineType (Name,
899 PackingSize.Unspecified, 1);
902 // classes or structs with fields
904 TypeBuilder = builder.DefineType (Name,
909 TypeBuilder builder = Parent.TypeBuilder;
912 // Structs with no fields need to have a ".size 1"
915 if (!is_class && Fields == null)
916 TypeBuilder = builder.DefineNestedType (Basename,
919 PackingSize.Unspecified);
922 // classes or structs with fields
924 TypeBuilder = builder.DefineNestedType (Basename,
931 TypeManager.AddUserType (Name, TypeBuilder, this);
933 if (parent == TypeManager.attribute_type ||
934 parent.IsSubclassOf (TypeManager.attribute_type)) {
935 RootContext.RegisterAttribute (this);
936 TypeManager.RegisterAttrType (TypeBuilder, this);
938 RootContext.RegisterOrder (this);
940 if (Interfaces != null) {
941 foreach (Interface iface in Interfaces)
946 foreach (TypeContainer tc in Types)
950 if (Delegates != null) {
951 foreach (Delegate d in Delegates)
956 foreach (Enum en in Enums)
966 /// Defines the MemberCore objects that are in the `list' Arraylist
968 /// The `defined_names' array contains a list of members defined in
971 static ArrayList remove_list = new ArrayList ();
972 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
976 remove_list.Clear ();
978 foreach (MemberCore mc in list){
979 if (!mc.Define (this)){
980 remove_list.Add (mc);
984 if (defined_names == null)
987 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
990 if (RootContext.WarningLevel >= 4){
991 if ((mc.ModFlags & Modifiers.NEW) != 0)
992 Report109 (mc.Location, mc);
997 if (defined_names [idx] is PropertyInfo &&
998 ((mc.ModFlags & Modifiers.OVERRIDE) != 0)){
1002 #if WANT_TO_VERIFY_SIGNATURES_HERE
1003 if (defined_names [idx] is MethodBase && mc is MethodCore){
1004 MethodBase mb = (MethodBase) defined_names [idx];
1005 MethodCore met = (MethodCore) mc;
1007 if ((mb.IsVirtual || mb.IsAbstract) &&
1008 (mc.ModFlags & Modifiers.OVERRIDE) != 0)
1012 // FIXME: Compare the signatures here. If they differ,
1013 // then: `continue;'
1016 if ((mc.ModFlags & Modifiers.NEW) == 0)
1017 Report108 (mc.Location, defined_names [idx]);
1020 foreach (object o in remove_list)
1023 remove_list.Clear ();
1027 /// Populates our TypeBuilder with fields and methods
1029 public override bool Define (TypeContainer parent)
1031 MemberInfo [] defined_names = null;
1033 if (RootContext.WarningLevel > 1){
1037 // This code throws an exception in the comparer
1038 // I guess the string is not an object?
1040 ptype = TypeBuilder.BaseType;
1042 defined_names = FindMembers (
1043 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1044 BindingFlags.Public | BindingFlags.Instance |
1045 BindingFlags.Static, null, null);
1047 Array.Sort (defined_names, mif_compare);
1051 if (constants != null)
1052 DefineMembers (constants, defined_names);
1055 DefineMembers (fields, defined_names);
1058 if (instance_constructors == null){
1059 if (default_constructor == null)
1060 DefineDefaultConstructor (false);
1063 if (initialized_static_fields != null &&
1064 default_static_constructor == null)
1065 DefineDefaultConstructor (true);
1068 if (this is Struct){
1070 // Structs can not have initialized instance
1073 if (initialized_static_fields != null &&
1074 default_static_constructor == null)
1075 DefineDefaultConstructor (true);
1077 if (initialized_fields != null)
1078 ReportStructInitializedInstanceError ();
1081 RegisterRequiredImplementations ();
1084 // Constructors are not in the defined_names array
1086 if (instance_constructors != null)
1087 DefineMembers (instance_constructors, null);
1089 if (default_static_constructor != null)
1090 default_static_constructor.Define (this);
1092 if (methods != null)
1093 DefineMembers (methods, null);
1095 if (properties != null)
1096 DefineMembers (properties, defined_names);
1099 DefineMembers (events, defined_names);
1101 if (indexers != null) {
1102 foreach (Indexer i in Indexers)
1106 if (operators != null)
1107 DefineMembers (operators, null);
1110 DefineMembers (enums, defined_names);
1112 if (delegates != null)
1113 DefineMembers (delegates, defined_names);
1119 /// Looks up the alias for the name
1121 public string LookupAlias (string name)
1123 if (Namespace != null)
1124 return Namespace.LookupAlias (name);
1130 /// This function is based by a delegate to the FindMembers routine
1132 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1138 /// This filter is used by FindMembers, and we just keep
1139 /// a global for the filter to `AlwaysAccept'
1141 static MemberFilter accepting_filter;
1143 static bool IsVirtualFilter (MemberInfo m, object filterCriteria)
1145 if (!(m is MethodInfo))
1148 return ((MethodInfo) m).IsVirtual;
1152 /// This filter is used by FindMembers, and it is used to
1153 /// extract only virtual/abstract fields
1155 static MemberFilter virtual_method_filter;
1158 /// A member comparission method based on name only
1160 static IComparer mif_compare;
1162 static TypeContainer ()
1164 accepting_filter = new MemberFilter (AlwaysAccept);
1165 virtual_method_filter = new MemberFilter (IsVirtualFilter);
1166 mif_compare = new MemberInfoCompare ();
1170 /// This method returns the members of this type just like Type.FindMembers would
1171 /// Only, we need to use this for types which are _being_ defined because MS'
1172 /// implementation can't take care of that.
1175 // FIXME: return an empty static array instead of null, that cleans up
1176 // some code and is consistent with some coding conventions I just found
1180 // Notice that in various cases we check if our field is non-null,
1181 // something that would normally mean that there was a bug elsewhere.
1183 // The problem happens while we are defining p-invoke methods, as those
1184 // will trigger a FindMembers, but this happens before things are defined
1186 // Since the whole process is a no-op, it is fine to check for null here.
1188 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1189 MemberFilter filter, object criteria)
1191 ArrayList members = new ArrayList ();
1192 bool priv = (bf & BindingFlags.NonPublic) != 0;
1196 filter = accepting_filter;
1198 if ((mt & MemberTypes.Field) != 0) {
1199 if (fields != null) {
1200 foreach (Field f in fields) {
1201 if ((f.ModFlags & Modifiers.PRIVATE) != 0)
1205 FieldBuilder fb = f.FieldBuilder;
1206 if (fb != null && filter (fb, criteria) == true)
1211 if (constants != null) {
1212 foreach (Const con in constants) {
1213 if ((con.ModFlags & Modifiers.PRIVATE) != 0)
1217 FieldBuilder fb = con.FieldBuilder;
1218 if (fb != null && filter (fb, criteria) == true)
1224 if ((mt & MemberTypes.Method) != 0) {
1225 if (methods != null) {
1226 foreach (Method m in methods) {
1227 if ((m.ModFlags & Modifiers.PRIVATE) != 0)
1231 MethodBuilder mb = m.MethodBuilder;
1233 if (mb != null && filter (mb, criteria) == true)
1238 if (operators != null){
1239 foreach (Operator o in operators) {
1240 if ((o.ModFlags & Modifiers.PRIVATE) != 0)
1244 MethodBuilder ob = o.OperatorMethodBuilder;
1245 if (ob != null && filter (ob, criteria) == true)
1250 if (properties != null){
1251 foreach (Property p in properties){
1252 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1259 if (b != null && filter (b, criteria) == true)
1263 if (b != null && filter (b, criteria) == true)
1269 if ((mt & MemberTypes.Event) != 0) {
1271 foreach (Event e in events) {
1272 if ((e.ModFlags & Modifiers.PRIVATE) != 0)
1276 MemberInfo eb = e.EventBuilder;
1277 if (eb != null && filter (eb, criteria) == true)
1278 members.Add (e.EventBuilder);
1282 if ((mt & MemberTypes.Property) != 0){
1283 if (properties != null)
1284 foreach (Property p in properties) {
1285 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1289 MemberInfo pb = p.PropertyBuilder;
1290 if (pb != null && filter (pb, criteria) == true) {
1291 members.Add (p.PropertyBuilder);
1295 if (indexers != null)
1296 foreach (Indexer ix in indexers) {
1297 if ((ix.ModFlags & Modifiers.PRIVATE) != 0)
1301 MemberInfo ib = ix.PropertyBuilder;
1302 if (ib != null && filter (ib, criteria) == true) {
1303 members.Add (ix.PropertyBuilder);
1308 if ((mt & MemberTypes.NestedType) != 0) {
1311 foreach (TypeContainer t in Types)
1312 if (filter (t.TypeBuilder, criteria) == true)
1313 members.Add (t.TypeBuilder);
1316 foreach (Enum en in Enums)
1317 if (filter (en.TypeBuilder, criteria) == true)
1318 members.Add (en.TypeBuilder);
1322 if ((mt & MemberTypes.Constructor) != 0){
1323 if (instance_constructors != null){
1324 foreach (Constructor c in instance_constructors){
1325 ConstructorBuilder cb = c.ConstructorBuilder;
1328 if (filter (cb, criteria) == true)
1333 if (default_static_constructor != null){
1334 ConstructorBuilder cb =
1335 default_static_constructor.ConstructorBuilder;
1337 if (filter (cb, criteria) == true)
1343 // Lookup members in parent if requested.
1345 if ((bf & BindingFlags.DeclaredOnly) == 0){
1348 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1350 members.AddRange (mi);
1353 int count = members.Count;
1355 MemberInfo [] mi = new MemberInfo [count];
1356 members.CopyTo (mi);
1363 public MemberInfo GetFieldFromEvent (EventExpr event_expr)
1365 EventInfo ei = event_expr.EventInfo;
1367 foreach (Event e in events) {
1369 if (e.FieldBuilder == null)
1372 if (Type.FilterName (e.FieldBuilder, ei.Name))
1373 return e.FieldBuilder;
1379 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1380 MemberFilter filter, object criteria)
1382 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1385 return tc.FindMembers (mt, bf, filter, criteria);
1387 return t.FindMembers (mt, bf, filter, criteria);
1391 // FindMethods will look for methods not only in the type `t', but in
1392 // any interfaces implemented by the type.
1394 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1395 MemberFilter filter, object criteria)
1401 /// Whether the specified method is an interface method implementation
1405 /// If a method in Type `t' (or null to look in all interfaces
1406 /// and the base abstract class) with name `Name', return type `ret_type' and
1407 /// arguments `args' implements an interface, this method will
1408 /// return the MethodInfo that this method implements.
1410 /// This will remove the method from the list of "pending" methods
1411 /// that are required to be implemented for this class as a side effect.
1414 public MethodInfo IsInterfaceMethod (Type t, string Name, Type ret_type, Type [] args,
1417 int arg_len = args.Length;
1419 if (pending_implementations == null)
1422 foreach (TypeAndMethods tm in pending_implementations){
1423 if (!(t == null || tm.type == t))
1427 foreach (MethodInfo m in tm.methods){
1433 if (Name != m.Name){
1438 if (ret_type != m.ReturnType){
1439 if (!((ret_type == null && m.ReturnType == TypeManager.void_type) ||
1440 (m.ReturnType == null && ret_type == TypeManager.void_type)))
1448 // Check if we have the same parameters
1450 if (tm.args [i].Length != arg_len){
1455 int j, top = args.Length;
1458 for (j = 0; j < top; j++){
1459 if (tm.args [i][j] != args[j]){
1470 tm.methods [i] = null;
1471 tm.found [i] = true;
1475 // If a specific type was requested, we can stop now.
1483 /// C# allows this kind of scenarios:
1484 /// interface I { void M (); }
1485 /// class X { public void M (); }
1486 /// class Y : X, I { }
1488 /// For that case, we create an explicit implementation function
1491 void DefineProxy (Type iface, MethodInfo parent_method, MethodInfo iface_method,
1494 MethodBuilder proxy;
1496 string proxy_name = iface.Name + "." + iface_method.Name;
1498 proxy = TypeBuilder.DefineMethod (
1500 MethodAttributes.HideBySig |
1501 MethodAttributes.NewSlot |
1502 MethodAttributes.Virtual,
1503 CallingConventions.Standard | CallingConventions.HasThis,
1504 parent_method.ReturnType, args);
1506 int top = args.Length;
1507 ILGenerator ig = proxy.GetILGenerator ();
1509 ig.Emit (OpCodes.Ldarg_0);
1510 for (int i = 0; i < top; i++){
1513 ig.Emit (OpCodes.Ldarg_1); break;
1515 ig.Emit (OpCodes.Ldarg_2); break;
1517 ig.Emit (OpCodes.Ldarg_3); break;
1519 ig.Emit (OpCodes.Ldarg, i - 1); break;
1522 ig.Emit (OpCodes.Call, parent_method);
1523 ig.Emit (OpCodes.Ret);
1525 TypeBuilder.DefineMethodOverride (proxy, iface_method);
1529 /// This function tells whether one of our parent classes implements
1530 /// the given method (which turns out, it is valid to have an interface
1531 /// implementation in a parent
1533 bool ParentImplements (Type iface_type, MethodInfo mi)
1537 Type [] args = TypeManager.GetArgumentTypes (mi);
1538 ms = new MethodSignature (mi.Name, mi.ReturnType, args);
1539 MemberInfo [] list = FindMembers (
1540 TypeBuilder.BaseType, MemberTypes.Method | MemberTypes.Property,
1541 BindingFlags.Public | BindingFlags.Instance,
1542 MethodSignature.method_signature_filter, ms);
1544 if (list == null || list.Length == 0)
1547 DefineProxy (iface_type, (MethodInfo) list [0], mi, args);
1552 /// Verifies that any pending abstract methods or interface methods
1553 /// were implemented.
1555 bool VerifyPendingMethods ()
1557 int top = pending_implementations.Length;
1558 bool errors = false;
1561 for (i = 0; i < top; i++){
1562 Type type = pending_implementations [i].type;
1565 foreach (MethodInfo mi in pending_implementations [i].methods){
1569 if (type.IsInterface){
1570 if (ParentImplements (type, mi))
1575 if (pending_implementations [i].found [j])
1576 extra = ". (method might be private or static)";
1579 "`" + Name + "' does not implement " +
1580 "interface member `" +
1581 type.FullName + "." + mi.Name + "'" + extra);
1585 "`" + Name + "' does not implement " +
1586 "inherited abstract member `" +
1587 type.FullName + "." + mi.Name + "'");
1597 /// Emits the values for the constants
1599 public void EmitConstants ()
1601 if (constants != null)
1602 foreach (Const con in constants)
1603 con.EmitConstant (this);
1608 /// Emits the code, this step is performed after all
1609 /// the types, enumerations, constructors
1613 if (instance_constructors != null)
1614 foreach (Constructor c in instance_constructors)
1617 if (default_static_constructor != null)
1618 default_static_constructor.Emit (this);
1620 if (methods != null)
1621 foreach (Method m in methods)
1624 if (operators != null)
1625 foreach (Operator o in operators)
1628 if (properties != null)
1629 foreach (Property p in properties)
1632 if (indexers != null) {
1633 foreach (Indexer ix in indexers)
1636 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (this, ModFlags, Location);
1638 TypeBuilder.SetCustomAttribute (cb);
1642 foreach (Field f in fields)
1645 if (events != null){
1646 foreach (Event e in Events)
1650 if (pending_implementations != null)
1651 if (!VerifyPendingMethods ())
1654 EmitContext ec = new EmitContext (
1655 this, Mono.CSharp.Location.Null, null, null,
1658 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1661 // Check for internal or private fields that were never assigned
1663 if (RootContext.WarningLevel >= 3){
1664 foreach (Field f in fields){
1665 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1670 169, f.Location, "Private field " +
1671 MakeName (f.Name) + " is never used");
1676 // Only report 649 on level 4
1678 if (RootContext.WarningLevel < 4)
1681 if ((f.status & Field.Status.ASSIGNED) != 0)
1686 "Field " + MakeName (f.Name) + " is never assigned " +
1687 " to and will always have its default value");
1691 // if (types != null)
1692 // foreach (TypeContainer tc in types)
1696 public override void CloseType ()
1701 TypeBuilder.CreateType ();
1703 } catch (TypeLoadException){
1705 // This is fine, the code still created the type
1707 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1708 // Console.WriteLine (e.Message);
1710 Console.WriteLine ("In type: " + Name);
1715 foreach (Enum en in Enums)
1718 if (interface_order != null){
1719 foreach (Interface iface in interface_order)
1724 foreach (TypeContainer tc in Types)
1728 foreach (TypeContainer tc in Types)
1729 if (!(tc is Struct))
1733 if (Delegates != null)
1734 foreach (Delegate d in Delegates)
1738 public string MakeName (string n)
1740 return "`" + Name + "." + n + "'";
1743 public void Report108 (Location l, MemberInfo mi)
1746 108, l, "The keyword new is required on " +
1747 MakeName (mi.Name) + " because it hides `" +
1748 mi.ReflectedType.Name + "." + mi.Name + "'");
1751 public void Report109 (Location l, MemberCore mc)
1754 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1755 "inherited member, the keyword new is not required");
1758 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1764 // Performs the validation on a Method's modifiers (properties have
1765 // the same properties).
1767 public bool MethodModifiersValid (int flags, string n, Location loc)
1769 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1770 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1772 string name = MakeName (n);
1775 // At most one of static, virtual or override
1777 if ((flags & Modifiers.STATIC) != 0){
1778 if ((flags & vao) != 0){
1780 112, loc, "static method " + name + "can not be marked " +
1781 "as virtual, abstract or override");
1786 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1789 " marked as override cannot be marked as new or virtual");
1794 // If the declaration includes the abstract modifier, then the
1795 // declaration does not include static, virtual or extern
1797 if ((flags & Modifiers.ABSTRACT) != 0){
1798 if ((flags & Modifiers.EXTERN) != 0){
1800 180, loc, name + " can not be both abstract and extern");
1804 if ((flags & Modifiers.VIRTUAL) != 0){
1806 503, loc, name + " can not be both abstract and virtual");
1810 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1813 " is abstract but its container class is not");
1819 if ((flags & Modifiers.PRIVATE) != 0){
1820 if ((flags & vao) != 0){
1823 " virtual or abstract members can not be private");
1828 if ((flags & Modifiers.SEALED) != 0){
1829 if ((flags & Modifiers.OVERRIDE) == 0){
1832 " cannot be sealed because it is not an override");
1841 // Returns true if `type' is as accessible as the flags `flags'
1842 // given for this member
1844 static public bool AsAccessible (Type type, int flags)
1849 Hashtable builder_and_args;
1851 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1853 if (builder_and_args == null)
1854 builder_and_args = new Hashtable ();
1859 public class Class : TypeContainer {
1861 // Modifiers allowed in a class declaration
1863 public const int AllowedModifiers =
1866 Modifiers.PROTECTED |
1867 Modifiers.INTERNAL |
1869 Modifiers.ABSTRACT |
1873 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1874 : base (parent, name, l)
1878 if (parent.Parent == null)
1879 accmods = Modifiers.INTERNAL;
1881 accmods = Modifiers.PRIVATE;
1883 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1884 this.attributes = attrs;
1888 // FIXME: How do we deal with the user specifying a different
1891 public override TypeAttributes TypeAttr {
1893 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1898 public class Struct : TypeContainer {
1900 // Modifiers allowed in a struct declaration
1902 public const int AllowedModifiers =
1905 Modifiers.PROTECTED |
1906 Modifiers.INTERNAL |
1910 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1911 : base (parent, name, l)
1915 if (parent.Parent == null)
1916 accmods = Modifiers.INTERNAL;
1918 accmods = Modifiers.PRIVATE;
1920 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1922 this.ModFlags |= Modifiers.SEALED;
1923 this.attributes = attrs;
1928 // FIXME: Allow the user to specify a different set of attributes
1929 // in some cases (Sealed for example is mandatory for a class,
1930 // but what SequentialLayout can be changed
1932 public override TypeAttributes TypeAttr {
1934 return base.TypeAttr |
1935 TypeAttributes.SequentialLayout |
1936 TypeAttributes.Sealed |
1937 TypeAttributes.BeforeFieldInit;
1942 public abstract class MethodCore : MemberCore {
1943 public readonly Parameters Parameters;
1947 // Parameters, cached for semantic analysis.
1949 InternalParameters parameter_info;
1951 public MethodCore (string name, Parameters parameters, Location l)
1955 Parameters = parameters;
1959 // Returns the System.Type array for the parameters of this method
1961 Type [] parameter_types;
1962 public Type [] ParameterTypes (TypeContainer parent)
1964 if (Parameters == null)
1965 return TypeManager.NoTypes;
1967 if (parameter_types == null)
1968 parameter_types = Parameters.GetParameterInfo (parent);
1970 return parameter_types;
1973 public InternalParameters ParameterInfo
1976 return parameter_info;
1980 parameter_info = value;
1984 public Block Block {
1994 public CallingConventions GetCallingConvention (bool is_class)
1996 CallingConventions cc = 0;
1998 cc = Parameters.GetCallingConvention ();
2001 if ((ModFlags & Modifiers.STATIC) == 0)
2002 cc |= CallingConventions.HasThis;
2004 // FIXME: How is `ExplicitThis' used in C#?
2009 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2012 // Define each type attribute (in/out/ref) and
2013 // the argument names.
2015 Parameter [] p = Parameters.FixedParameters;
2018 MethodBuilder mb = null;
2019 ConstructorBuilder cb = null;
2021 if (builder is MethodBuilder)
2022 mb = (MethodBuilder) builder;
2024 cb = (ConstructorBuilder) builder;
2027 for (i = 0; i < p.Length; i++) {
2028 ParameterBuilder pb;
2031 pb = cb.DefineParameter (
2032 i + 1, p [i].Attributes, p [i].Name);
2034 pb = mb.DefineParameter (
2035 i + 1, p [i].Attributes, p [i].Name);
2037 Attributes attr = p [i].OptAttributes;
2039 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2043 if (Parameters.ArrayParameter != null){
2044 ParameterBuilder pb;
2045 Parameter array_param = Parameters.ArrayParameter;
2048 pb = cb.DefineParameter (
2049 i + 1, array_param.Attributes,
2052 pb = mb.DefineParameter (
2053 i + 1, array_param.Attributes,
2056 CustomAttributeBuilder a = new CustomAttributeBuilder (
2057 TypeManager.cons_param_array_attribute, new object [0]);
2059 pb.SetCustomAttribute (a);
2064 public class Method : MethodCore {
2065 public readonly string ReturnType;
2066 public MethodBuilder MethodBuilder;
2067 public readonly Attributes OptAttributes;
2069 MethodAttributes flags;
2072 /// Modifiers allowed in a class declaration
2074 const int AllowedModifiers =
2077 Modifiers.PROTECTED |
2078 Modifiers.INTERNAL |
2083 Modifiers.OVERRIDE |
2084 Modifiers.ABSTRACT |
2089 // return_type can be "null" for VOID values.
2091 public Method (string return_type, int mod, string name, Parameters parameters,
2092 Attributes attrs, Location l)
2093 : base (name, parameters, l)
2095 ReturnType = return_type;
2096 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
2097 OptAttributes = attrs;
2101 // Returns the `System.Type' for the ReturnType of this
2102 // function. Provides a nice cache. (used between semantic analysis
2103 // and actual code generation
2105 Type type_return_type;
2107 public Type GetReturnType (TypeContainer parent)
2109 if (type_return_type == null)
2110 type_return_type = RootContext.LookupType (
2111 parent, ReturnType, false, Location);
2113 return type_return_type;
2116 void DuplicateEntryPoint (MethodInfo b, Location location)
2120 "Program `" + CodeGen.FileName +
2121 "' has more than one entry point defined: `" +
2122 TypeManager.CSharpSignature(b) + "'");
2125 void Report28 (MethodInfo b)
2127 if (RootContext.WarningLevel < 4)
2132 "`" + TypeManager.CSharpSignature(b) +
2133 "' has the wrong signature to be an entry point");
2136 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2138 if (b.ReturnType != TypeManager.void_type &&
2139 b.ReturnType != TypeManager.int32_type)
2142 if (pinfo.Count == 0)
2145 if (pinfo.Count > 1)
2148 Type t = pinfo.ParameterType(0);
2150 (t.GetArrayRank() == 1) &&
2151 (t.GetElementType() == TypeManager.string_type) &&
2152 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2161 public override bool Define (TypeContainer parent)
2163 Type ret_type = GetReturnType (parent);
2164 Type [] parameters = ParameterTypes (parent);
2166 MethodInfo implementing;
2167 Type iface_type = null;
2168 string iface = "", short_name;
2169 bool explicit_impl = false;
2171 // Check if the return type and arguments were correct
2172 if (ret_type == null || parameters == null)
2175 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2178 flags = Modifiers.MethodAttr (ModFlags);
2181 // verify accessibility
2183 if (!TypeContainer.AsAccessible (ret_type, ModFlags))
2186 if (ret_type.IsPointer && !UnsafeOK (parent))
2189 foreach (Type partype in parameters){
2190 if (!TypeContainer.AsAccessible (partype, ModFlags))
2192 if (partype.IsPointer && !UnsafeOK (parent))
2200 // Verify if the parent has a type with the same name, and then
2201 // check whether we have to create a new slot for it or not.
2203 Type ptype = parent.TypeBuilder.BaseType;
2205 // ptype is only null for System.Object while compiling corlib.
2207 MethodSignature ms = new MethodSignature (Name, ret_type, parameters);
2208 MemberInfo [] mi, mi_static, mi_instance;
2210 mi_static = TypeContainer.FindMembers (
2211 ptype, MemberTypes.Method,
2212 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2213 MethodSignature.inheritable_method_signature_filter, ms);
2215 mi_instance = TypeContainer.FindMembers (
2216 ptype, MemberTypes.Method,
2217 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2218 MethodSignature.inheritable_method_signature_filter,
2221 if (mi_instance != null && mi_instance.Length > 0){
2223 } else if (mi_static != null && mi_static.Length > 0)
2228 if (mi != null && mi.Length > 0){
2229 if (!CheckMethodAgainstBase (parent, flags, (MethodInfo) mi [0])){
2233 if ((ModFlags & Modifiers.NEW) != 0)
2234 WarningNotHiding (parent);
2236 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2237 Report.Error (115, Location,
2238 parent.MakeName (Name) +
2239 " no suitable methods found to override");
2242 } else if ((ModFlags & Modifiers.NEW) != 0)
2243 WarningNotHiding (parent);
2246 // If we implement an interface, extract the interface name.
2249 if (Name.IndexOf (".") != -1){
2250 int pos = Name.LastIndexOf (".");
2251 iface = Name.Substring (0, pos);
2253 iface_type = RootContext.LookupType (parent, iface, false, Location);
2254 short_name = Name.Substring (pos + 1);
2256 if (iface_type == null)
2259 // Compute the full name that we need to export
2260 Name = iface_type.FullName + "." + short_name;
2261 explicit_impl = true;
2266 // Check if we are an implementation of an interface method or
2269 implementing = parent.IsInterfaceMethod (
2270 iface_type, short_name, ret_type, parameters, false);
2273 // For implicit implementations, make sure we are public, for
2274 // explicit implementations, make sure we are private.
2276 if (implementing != null){
2278 // Setting null inside this block will trigger a more
2279 // verbose error reporting for missing interface implementations
2281 // The "candidate" function has been flagged already
2282 // but it wont get cleared
2284 if (iface_type == null){
2286 // We already catch different accessibility settings
2287 // so we just need to check that we are not private
2289 if ((ModFlags & Modifiers.PRIVATE) != 0)
2290 implementing = null;
2293 // Static is not allowed
2295 if ((ModFlags & Modifiers.STATIC) != 0)
2296 implementing = null;
2298 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2300 106, Location, "`public' or `abstract' modifiers "+
2301 "are not allowed in explicit interface declarations"
2303 implementing = null;
2309 // If implementing is still valid, set flags
2311 if (implementing != null){
2312 if (implementing.DeclaringType.IsInterface)
2313 flags |= MethodAttributes.NewSlot;
2316 MethodAttributes.Virtual |
2317 MethodAttributes.HideBySig;
2322 parent.IsInterfaceMethod (
2323 iface_type, short_name, ret_type, parameters, true);
2326 Attribute dllimport_attr = null;
2327 if (OptAttributes != null && OptAttributes.AttributeSections != null) {
2328 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2329 if (asec.Attributes == null)
2332 foreach (Attribute a in asec.Attributes)
2333 if (a.Name.IndexOf ("DllImport") != -1) {
2334 flags |= MethodAttributes.PinvokeImpl;
2341 // Finally, define the method
2344 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2346 if ((ModFlags & Modifiers.STATIC) == 0) {
2347 Report.Error (601, Location, "The DllImport attribute must be specified on " +
2348 "a method marked 'static' and 'extern'.");
2352 EmitContext ec = new EmitContext (
2353 parent, Location, null, GetReturnType (parent), ModFlags);
2355 MethodBuilder = dllimport_attr.DefinePInvokeMethod (
2356 ec, parent.TypeBuilder,
2357 Name, flags, ret_type, parameters);
2359 MethodBuilder = parent.TypeBuilder.DefineMethod (
2361 GetCallingConvention (parent is Class),
2362 ret_type, parameters);
2364 if (implementing != null && explicit_impl)
2365 parent.TypeBuilder.DefineMethodOverride (
2366 MethodBuilder, implementing);
2369 if (MethodBuilder == null)
2373 // HACK because System.Reflection.Emit is lame
2375 ParameterInfo = new InternalParameters (parent, Parameters);
2377 if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo,
2381 "Class `" + parent.Name + "' already contains a definition with " +
2382 " the same return value and parameter types for method `" +
2388 // This is used to track the Entry Point,
2390 if (Name == "Main" &&
2391 ((ModFlags & Modifiers.STATIC) != 0) &&
2392 (RootContext.MainClass == null ||
2393 RootContext.MainClass == parent.TypeBuilder.FullName)){
2394 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2395 if (RootContext.EntryPoint == null) {
2396 RootContext.EntryPoint = MethodBuilder;
2397 RootContext.EntryPointLocation = Location;
2399 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2400 DuplicateEntryPoint (MethodBuilder, Location);
2403 Report28(MethodBuilder);
2412 public void Emit (TypeContainer parent)
2417 if ((flags & MethodAttributes.PinvokeImpl) == 0)
2418 ig = MethodBuilder.GetILGenerator ();
2422 ec = new EmitContext (parent, Location, ig, GetReturnType (parent), ModFlags);
2424 if (OptAttributes != null)
2425 Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location);
2428 LabelParameters (ec, ParameterTypes (parent), MethodBuilder);
2431 // abstract or extern methods have no bodies
2433 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
2437 // Handle destructors specially
2439 // FIXME: This code generates buggy code
2441 if (Name == "Finalize" && type_return_type == TypeManager.void_type)
2442 EmitDestructor (ec);
2444 ISymbolWriter sw = CodeGen.SymbolWriter;
2446 if ((sw != null) && (!Location.IsNull (Location))) {
2447 MethodToken token = MethodBuilder.GetToken ();
2448 sw.OpenMethod (new SymbolToken (token.Token));
2449 sw.SetMethodSourceRange (Location.SymbolDocument,
2451 Block.EndLocation.SymbolDocument,
2452 Block.EndLocation.Row, 0);
2454 ec.EmitTopBlock (Block, Location);
2458 ec.EmitTopBlock (Block, Location);
2462 void EmitDestructor (EmitContext ec)
2464 ILGenerator ig = ec.ig;
2466 Label finish = ig.DefineLabel ();
2467 bool old_in_try = ec.InTry;
2468 Expression member_lookup;
2470 ig.BeginExceptionBlock ();
2472 ec.ReturnLabel = finish;
2473 ec.EmitTopBlock (Block, Location);
2474 ec.InTry = old_in_try;
2476 ig.MarkLabel (finish);
2477 bool old_in_finally = ec.InFinally;
2478 ec.InFinally = true;
2479 ig.BeginFinallyBlock ();
2481 member_lookup = Expression.MemberLookup (
2482 ec, ec.ContainerType.BaseType, "Finalize",
2483 MemberTypes.Method, Expression.AllBindingFlags, Location);
2485 if (member_lookup != null){
2486 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
2488 ig.Emit (OpCodes.Ldarg_0);
2489 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
2491 ec.InFinally = old_in_finally;
2493 ig.EndExceptionBlock ();
2494 //ig.MarkLabel (ec.ReturnLabel);
2495 ig.Emit (OpCodes.Ret);
2499 public abstract class ConstructorInitializer {
2500 ArrayList argument_list;
2501 ConstructorInfo parent_constructor;
2504 public ConstructorInitializer (ArrayList argument_list, Location location)
2506 this.argument_list = argument_list;
2507 this.location = location;
2510 public ArrayList Arguments {
2512 return argument_list;
2516 public bool Resolve (EmitContext ec)
2518 Expression parent_constructor_group;
2521 if (argument_list != null){
2522 for (int i = argument_list.Count; i > 0; ){
2525 Argument a = (Argument) argument_list [i];
2526 if (!a.Resolve (ec, location))
2531 if (this is ConstructorBaseInitializer)
2532 t = ec.ContainerType.BaseType;
2534 t = ec.ContainerType;
2536 parent_constructor_group = Expression.MemberLookup (
2538 MemberTypes.Constructor,
2539 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2542 if (parent_constructor_group == null){
2543 Report.Error (1501, location,
2544 "Can not find a constructor for this argument list");
2548 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2549 (MethodGroupExpr) parent_constructor_group, argument_list, location);
2551 if (parent_constructor == null){
2552 Report.Error (1501, location,
2553 "Can not find a constructor for this argument list");
2560 public void Emit (EmitContext ec)
2562 ec.ig.Emit (OpCodes.Ldarg_0);
2563 if (argument_list != null)
2564 Invocation.EmitArguments (ec, null, argument_list);
2565 ec.ig.Emit (OpCodes.Call, parent_constructor);
2569 public class ConstructorBaseInitializer : ConstructorInitializer {
2570 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2575 public class ConstructorThisInitializer : ConstructorInitializer {
2576 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2581 public class Constructor : MethodCore {
2582 public ConstructorBuilder ConstructorBuilder;
2583 public ConstructorInitializer Initializer;
2584 public Attributes OptAttributes;
2587 // Modifiers allowed for a constructor.
2589 const int AllowedModifiers =
2591 Modifiers.PROTECTED |
2592 Modifiers.INTERNAL |
2598 // The spec claims that static is not permitted, but
2599 // my very own code has static constructors.
2601 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2602 : base (name, args, l)
2608 // Returns true if this is a default constructor
2610 public bool IsDefault ()
2612 if ((ModFlags & Modifiers.STATIC) != 0)
2613 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2614 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2617 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2618 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2619 (Initializer is ConstructorBaseInitializer) &&
2620 (Initializer.Arguments == null);
2624 // Creates the ConstructorBuilder
2626 public override bool Define (TypeContainer parent)
2628 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2629 MethodAttributes.SpecialName);
2631 Type [] parameters = ParameterTypes (parent);
2633 if ((ModFlags & Modifiers.STATIC) != 0)
2634 ca |= MethodAttributes.Static;
2636 if (parent is Struct && parameters.Length == 0){
2639 "Structs can not contain explicit parameterless " +
2643 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2646 foreach (Type partype in parameters)
2647 if (!TypeContainer.AsAccessible (partype, ModFlags))
2650 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2651 ca, GetCallingConvention (parent is Class), parameters);
2654 // HACK because System.Reflection.Emit is lame
2656 ParameterInfo = new InternalParameters (parent, Parameters);
2658 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
2661 "Class `" +parent.Name+ "' already contains a definition with the " +
2662 "same return value and parameter types for constructor `" + Name
2673 public void Emit (TypeContainer parent)
2675 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2676 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2678 if (parent is Class && ((ModFlags & Modifiers.STATIC) == 0)){
2679 if (Initializer == null)
2680 Initializer = new ConstructorBaseInitializer (null, parent.Location);
2682 if (!Initializer.Resolve (ec))
2686 LabelParameters (ec, ParameterTypes (parent), ConstructorBuilder);
2689 // Classes can have base initializers and instance field initializers.
2691 if (parent is Class){
2692 if ((ModFlags & Modifiers.STATIC) == 0){
2693 parent.EmitFieldInitializers (ec);
2694 Initializer.Emit (ec);
2698 if ((ModFlags & Modifiers.STATIC) != 0)
2699 parent.EmitFieldInitializers (ec);
2701 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2703 ec.EmitTopBlock (Block, Location);
2707 public class Field : MemberCore {
2708 public readonly string Type;
2709 public readonly Object Initializer;
2710 public readonly Attributes OptAttributes;
2711 public FieldBuilder FieldBuilder;
2712 public Status status;
2715 public enum Status : byte { ASSIGNED = 1, USED = 2 }
2719 // Modifiers allowed in a class declaration
2721 const int AllowedModifiers =
2724 Modifiers.PROTECTED |
2725 Modifiers.INTERNAL |
2728 Modifiers.VOLATILE |
2732 public Field (string type, int mod, string name, Object expr_or_array_init,
2733 Attributes attrs, Location loc)
2737 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, loc);
2738 Initializer = expr_or_array_init;
2739 OptAttributes = attrs;
2742 public override bool Define (TypeContainer parent)
2744 Type t = RootContext.LookupType (parent, Type, false, Location);
2749 if (!TypeContainer.AsAccessible (t, ModFlags))
2752 if (t.IsPointer && !UnsafeOK (parent))
2755 if (RootContext.WarningLevel > 1){
2756 Type ptype = parent.TypeBuilder.BaseType;
2758 // ptype is only null for System.Object while compiling corlib.
2762 mi = TypeContainer.FindMembers (
2763 ptype, MemberTypes.Method,
2764 BindingFlags.Public |
2765 BindingFlags.Static | BindingFlags.Instance,
2766 System.Type.FilterName, Name);
2770 if ((ModFlags & Modifiers.VOLATILE) != 0){
2772 if (TypeManager.IsEnumType (t))
2773 t = TypeManager.EnumToUnderlying (t);
2775 if (!((t == TypeManager.bool_type) ||
2776 (t == TypeManager.sbyte_type) ||
2777 (t == TypeManager.byte_type) ||
2778 (t == TypeManager.short_type) ||
2779 (t == TypeManager.ushort_type) ||
2780 (t == TypeManager.int32_type) ||
2781 (t == TypeManager.uint32_type) ||
2782 (t == TypeManager.char_type) ||
2783 (t == TypeManager.float_type))){
2785 677, Location, parent.MakeName (Name) +
2786 " A volatile field can not be of type `" +
2787 TypeManager.CSharpName (t) + "'");
2793 FieldBuilder = parent.TypeBuilder.DefineField (
2794 Name, t, Modifiers.FieldAttr (ModFlags));
2796 TypeManager.RegisterField (FieldBuilder, this);
2800 public void Emit (TypeContainer tc)
2802 EmitContext ec = new EmitContext (tc, Location, null,
2803 FieldBuilder.FieldType, ModFlags);
2805 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
2809 public class Property : MemberCore {
2810 public readonly string Type;
2811 public Block Get, Set;
2812 public PropertyBuilder PropertyBuilder;
2813 public Attributes OptAttributes;
2814 public MethodBuilder GetBuilder, SetBuilder;
2817 // The type, once we compute it.
2821 const int AllowedModifiers =
2824 Modifiers.PROTECTED |
2825 Modifiers.INTERNAL |
2829 Modifiers.OVERRIDE |
2830 Modifiers.ABSTRACT |
2835 public Property (string type, string name, int mod_flags, Block get_block, Block set_block,
2836 Attributes attrs, Location loc)
2840 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
2843 OptAttributes = attrs;
2847 // Checks our base implementation if any
2849 bool CheckBase (MethodAttributes flags, TypeContainer parent)
2852 // Find properties with the same name on the base class
2855 MemberInfo [] props;
2856 MemberInfo [] props_static = TypeManager.MemberLookup (
2858 parent.TypeBuilder.BaseType,
2859 MemberTypes.Property, BindingFlags.Public | BindingFlags.Static,
2862 MemberInfo [] props_instance = TypeManager.MemberLookup (
2864 parent.TypeBuilder.BaseType,
2865 MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance,
2869 // Find if we have anything
2871 if (props_static != null && props_static.Length > 0)
2872 props = props_static;
2873 else if (props_instance != null && props_instance.Length > 0)
2874 props = props_instance;
2879 // If we have something on the base.
2880 if (props != null && props.Length > 0){
2881 if (props.Length > 1)
2882 throw new Exception ("Should not happen");
2884 PropertyInfo pi = (PropertyInfo) props [0];
2886 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
2887 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
2889 MethodInfo reference = inherited_get == null ?
2890 inherited_set : inherited_get;
2892 if (reference != null)
2893 if (!CheckMethodAgainstBase (parent, flags, reference))
2897 if ((ModFlags & Modifiers.NEW) != 0)
2898 WarningNotHiding (parent);
2900 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2901 Report.Error (115, Location,
2902 parent.MakeName (Name) +
2903 " no suitable properties found to override");
2910 bool DefineMethod (TypeContainer parent, Type iface_type, string short_name,
2911 MethodAttributes flags, bool is_get)
2913 Type [] parameters = TypeManager.NoTypes;
2914 MethodInfo implementing;
2919 fn_type = PropertyType;
2920 name = "get_" + short_name;
2922 name = "set_" + short_name;
2923 parameters = new Type [1];
2924 parameters [0] = PropertyType;
2925 fn_type = TypeManager.void_type;
2928 implementing = parent.IsInterfaceMethod (
2929 iface_type, name, fn_type, parameters, false);
2932 // For implicit implementations, make sure we are public, for
2933 // explicit implementations, make sure we are private.
2935 if (implementing != null){
2937 // Setting null inside this block will trigger a more
2938 // verbose error reporting for missing interface implementations
2940 // The "candidate" function has been flagged already
2941 // but it wont get cleared
2943 if (iface_type == null){
2945 // We already catch different accessibility settings
2946 // so we just need to check that we are not private
2948 if ((ModFlags & Modifiers.PRIVATE) != 0)
2949 implementing = null;
2952 // Static is not allowed
2954 if ((ModFlags & Modifiers.STATIC) != 0)
2955 implementing = null;
2957 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2959 106, Location, "`public' or `abstract' modifiers "+
2960 "are not allowed in explicit interface declarations"
2962 implementing = null;
2968 // If implementing is still valid, set flags
2970 if (implementing != null){
2972 // When implementing interface methods, set NewSlot.
2974 if (implementing.DeclaringType.IsInterface)
2975 flags |= MethodAttributes.NewSlot;
2978 MethodAttributes.Virtual |
2979 MethodAttributes.HideBySig;
2982 // clear the pending flag
2984 parent.IsInterfaceMethod (
2985 iface_type, name, fn_type, parameters, true);
2989 // If this is not an explicit interface implementation,
2990 // clear implementing, as it is only used for explicit
2991 // interface implementation
2993 if (Name.IndexOf (".") == -1)
2994 implementing = null;
2997 GetBuilder = parent.TypeBuilder.DefineMethod (
2998 name, flags, PropertyType, null);
2999 PropertyBuilder.SetGetMethod (GetBuilder);
3001 if (implementing != null)
3002 parent.TypeBuilder.DefineMethodOverride (
3003 GetBuilder, implementing);
3006 // HACK because System.Reflection.Emit is lame
3008 InternalParameters ip = new InternalParameters (
3009 parent, Parameters.GetEmptyReadOnlyParameters ());
3011 if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) {
3012 Report.Error (111, Location,
3013 "Class `" + parent.Name +
3014 "' already contains a definition with the " +
3015 "same return value and parameter types as the " +
3016 "'get' method of property `" + Name + "'");
3020 SetBuilder = parent.TypeBuilder.DefineMethod (
3021 name, flags, null, parameters);
3023 if (implementing != null)
3024 parent.TypeBuilder.DefineMethodOverride (
3025 SetBuilder, implementing);
3027 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3028 PropertyBuilder.SetSetMethod (SetBuilder);
3031 // HACK because System.Reflection.Emit is lame
3033 Parameter [] parms = new Parameter [1];
3034 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3035 InternalParameters ip = new InternalParameters (
3036 parent, new Parameters (parms, null, Location));
3038 if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) {
3041 "Class `" + parent.Name +
3042 "' already contains a definition with the " +
3043 "same return value and parameter types as the " +
3044 "'set' method of property `" + Name + "'");
3052 public override bool Define (TypeContainer parent)
3054 Type iface_type = null;
3057 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3060 MethodAttributes flags = Modifiers.MethodAttr (ModFlags);
3062 flags |= MethodAttributes.HideBySig |
3063 MethodAttributes.SpecialName;
3065 // Lookup Type, verify validity
3066 PropertyType = RootContext.LookupType (parent, Type, false, Location);
3067 if (PropertyType == null)
3070 // verify accessibility
3071 if (!TypeContainer.AsAccessible (PropertyType, ModFlags))
3074 if (PropertyType.IsPointer && !UnsafeOK (parent))
3077 if (!CheckBase (flags, parent))
3081 // Check for explicit interface implementation
3083 if (Name.IndexOf (".") != -1){
3084 int pos = Name.LastIndexOf (".");
3085 string iface = Name.Substring (0, pos);
3087 iface_type = RootContext.LookupType (parent, iface, false, Location);
3088 if (iface_type == null)
3091 short_name = Name.Substring (pos + 1);
3093 // Compute the full name that we need to export.
3094 Name = iface_type.FullName + "." + short_name;
3098 // FIXME - PropertyAttributes.HasDefault ?
3100 PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
3101 PropertyAttributes.SpecialName;
3103 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3104 Name, prop_attr, PropertyType, null);
3107 if (!DefineMethod (parent, iface_type, short_name, flags, true))
3111 if (!DefineMethod (parent, iface_type, short_name, flags, false))
3115 // HACK for the reasons exposed above
3117 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3120 "Class `" + parent.Name +
3121 "' already contains a definition for the property `" +
3129 public void Emit (TypeContainer tc)
3134 ec = new EmitContext (tc, Location, null, PropertyType, ModFlags);
3135 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3139 // abstract or extern properties have no bodies
3141 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3145 ig = GetBuilder.GetILGenerator ();
3146 ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags);
3148 ec.EmitTopBlock (Get, Location);
3152 ig = SetBuilder.GetILGenerator ();
3153 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3155 ec.EmitTopBlock (Set, Location);
3162 /// Gigantic workaround for lameness in SRE follows :
3163 /// This class derives from EventInfo and attempts to basically
3164 /// wrap around the EventBuilder so that FindMembers can quickly
3165 /// return this in it search for members
3167 public class MyEventBuilder : EventInfo {
3170 // We use this to "point" to our Builder which is
3171 // not really a MemberInfo
3173 EventBuilder MyBuilder;
3176 // We "catch" and wrap these methods
3178 MethodInfo raise, remove, add;
3180 EventAttributes attributes;
3181 Type declaring_type, reflected_type, event_type;
3184 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3186 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3188 // And now store the values in our own fields.
3190 declaring_type = type_builder;
3192 // FIXME : This is supposed to be MyBuilder but since that doesn't
3193 // derive from Type, I have no clue what to do with this.
3194 reflected_type = null;
3196 attributes = event_attr;
3198 this.event_type = event_type;
3202 // Methods that you have to override. Note that you only need
3203 // to "implement" the variants that take the argument (those are
3204 // the "abstract" methods, the others (GetAddMethod()) are
3207 public override MethodInfo GetAddMethod (bool nonPublic)
3212 public override MethodInfo GetRemoveMethod (bool nonPublic)
3217 public override MethodInfo GetRaiseMethod (bool nonPublic)
3223 // These methods make "MyEventInfo" look like a Builder
3225 public void SetRaiseMethod (MethodBuilder raiseMethod)
3227 raise = raiseMethod;
3228 MyBuilder.SetRaiseMethod (raiseMethod);
3231 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3233 remove = removeMethod;
3234 MyBuilder.SetRemoveOnMethod (removeMethod);
3237 public void SetAddOnMethod (MethodBuilder addMethod)
3240 MyBuilder.SetAddOnMethod (addMethod);
3243 public void SetCustomAttribute (CustomAttributeBuilder cb)
3245 MyBuilder.SetCustomAttribute (cb);
3248 public override object [] GetCustomAttributes (bool inherit)
3250 // FIXME : There's nothing which can be seemingly done here because
3251 // we have no way of getting at the custom attribute objects of the
3256 public override object [] GetCustomAttributes (Type t, bool inherit)
3258 // FIXME : Same here !
3262 public override bool IsDefined (Type t, bool b)
3267 public override EventAttributes Attributes {
3273 public override string Name {
3279 public override Type DeclaringType {
3281 return declaring_type;
3285 public override Type ReflectedType {
3287 return reflected_type;
3291 public Type EventType {
3298 public class Event : MemberCore {
3300 const int AllowedModifiers =
3303 Modifiers.PROTECTED |
3304 Modifiers.INTERNAL |
3309 Modifiers.OVERRIDE |
3313 public readonly string Type;
3314 public readonly Object Initializer;
3315 public readonly Block Add;
3316 public readonly Block Remove;
3317 public MyEventBuilder EventBuilder;
3318 public FieldBuilder FieldBuilder;
3319 public Attributes OptAttributes;
3322 MethodBuilder AddBuilder, RemoveBuilder;
3325 public Event (string type, string name, Object init, int flags, Block add_block,
3326 Block rem_block, Attributes attrs, Location loc)
3331 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
3334 OptAttributes = attrs;
3337 public override bool Define (TypeContainer parent)
3339 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3342 MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
3343 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3345 EventType = RootContext.LookupType (parent, Type, false, Location);
3346 if (EventType == null)
3349 if (!TypeContainer.AsAccessible (EventType, ModFlags))
3352 if (EventType.IsPointer && !UnsafeOK (parent))
3355 if (!EventType.IsSubclassOf (TypeManager.delegate_type)) {
3356 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3357 "' : event must be of a delegate type");
3361 Type [] parameters = new Type [1];
3362 parameters [0] = EventType;
3364 EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType);
3366 if (Add == null && Remove == null)
3367 FieldBuilder = parent.TypeBuilder.DefineField (Name, EventType, FieldAttributes.Private);
3370 // Now define the accessors
3373 AddBuilder = parent.TypeBuilder.DefineMethod (
3374 "add_" + Name, m_attr, null, parameters);
3375 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3376 EventBuilder.SetAddOnMethod (AddBuilder);
3379 // HACK because System.Reflection.Emit is lame
3381 Parameter [] parms = new Parameter [1];
3382 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3383 InternalParameters ip = new InternalParameters (
3384 parent, new Parameters (parms, null, Location));
3386 if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) {
3387 Report.Error (111, Location,
3388 "Class `" + parent.Name + "' already contains a definition with the " +
3389 "same return value and parameter types for the " +
3390 "'add' method of event `" + Name + "'");
3394 RemoveBuilder = parent.TypeBuilder.DefineMethod (
3395 "remove_" + Name, m_attr, null, parameters);
3396 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3397 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3400 // HACK because System.Reflection.Emit is lame
3403 if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) {
3404 Report.Error (111, Location,
3405 "Class `" + parent.Name + "' already contains a definition with the " +
3406 "same return value and parameter types for the " +
3407 "'remove' method of event `" + Name + "'");
3411 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3412 Report.Error (111, Location,
3413 "Class `" + parent.Name +
3414 "' already contains a definition for the event `" +
3422 void EmitDefaultMethod (EmitContext ec, bool is_add)
3424 ILGenerator ig = ec.ig;
3425 MethodInfo method = null;
3428 method = TypeManager.delegate_combine_delegate_delegate;
3430 method = TypeManager.delegate_remove_delegate_delegate;
3432 ig.Emit (OpCodes.Ldarg_0);
3433 ig.Emit (OpCodes.Ldarg_0);
3434 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3435 ig.Emit (OpCodes.Ldarg_1);
3436 ig.Emit (OpCodes.Call, method);
3437 ig.Emit (OpCodes.Castclass, EventType);
3438 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3439 ig.Emit (OpCodes.Ret);
3442 public void Emit (TypeContainer tc)
3447 ig = AddBuilder.GetILGenerator ();
3448 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3451 ec.EmitTopBlock (Add, Location);
3453 EmitDefaultMethod (ec, true);
3455 ig = RemoveBuilder.GetILGenerator ();
3456 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3459 ec.EmitTopBlock (Remove, Location);
3461 EmitDefaultMethod (ec, false);
3463 ec = new EmitContext (tc, Location, null, EventType, ModFlags);
3464 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3471 // FIXME: This does not handle:
3473 // int INTERFACENAME [ args ]
3477 // int this [ args ]
3479 public class Indexer : MemberCore {
3481 const int AllowedModifiers =
3484 Modifiers.PROTECTED |
3485 Modifiers.INTERNAL |
3489 Modifiers.OVERRIDE |
3494 public readonly string Type;
3495 public readonly string InterfaceType;
3496 public readonly Parameters FormalParameters;
3497 public readonly Block Get;
3498 public readonly Block Set;
3499 public Attributes OptAttributes;
3500 public MethodBuilder GetBuilder;
3501 public MethodBuilder SetBuilder;
3502 public PropertyBuilder PropertyBuilder;
3503 public Type IndexerType;
3505 public Indexer (string type, string int_type, int flags, Parameters parms,
3506 Block get_block, Block set_block, Attributes attrs, Location loc)
3511 InterfaceType = int_type;
3512 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
3513 FormalParameters = parms;
3516 OptAttributes = attrs;
3519 void DefineMethod (TypeContainer parent, Type iface_type,
3520 Type ret_type, string name,
3521 Type [] parameters, MethodAttributes attr, bool is_get)
3523 MethodInfo implementing;
3525 implementing = parent.IsInterfaceMethod (
3526 iface_type, name, ret_type, parameters, false);
3529 // Setting null inside this block will trigger a more
3530 // verbose error reporting for missing interface implementations
3532 // The "candidate" function has been flagged already
3533 // but it wont get cleared
3535 if (implementing != null){
3536 if (iface_type == null){
3538 // We already catch different accessibility settings
3539 // so we just need to check that we are not private
3541 if ((ModFlags & Modifiers.PRIVATE) != 0)
3542 implementing = null;
3545 // Static is not allowed
3547 if ((ModFlags & Modifiers.STATIC) != 0)
3548 implementing = null;
3550 if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
3553 "`public' or `abstract' modifiers are not "+
3554 "allowed in explicit interface declarations"
3556 implementing = null;
3560 if (implementing != null){
3562 // When implementing interface methods, set NewSlot.
3564 if (implementing.DeclaringType.IsInterface)
3565 attr |= MethodAttributes.NewSlot;
3568 MethodAttributes.Virtual |
3569 MethodAttributes.HideBySig;
3572 // clear the pending flag
3574 parent.IsInterfaceMethod (
3575 iface_type, name, ret_type, parameters, true);
3579 // If this is not an explicit interface implementation,
3580 // clear implementing, as it is only used for explicit
3581 // interface implementation
3583 if (Name.IndexOf (".") == -1)
3584 implementing = null;
3588 string meth_name = "get_Item";
3589 if (iface_type != null)
3590 meth_name = iface_type + ".get_Item";
3592 GetBuilder = parent.TypeBuilder.DefineMethod (
3593 meth_name, attr, IndexerType, parameters);
3595 if (implementing != null)
3596 parent.TypeBuilder.DefineMethodOverride (
3597 GetBuilder, implementing);
3600 PropertyBuilder.SetGetMethod (GetBuilder);
3603 string meth_name = "set_Item";
3605 if (iface_type != null)
3606 meth_name = iface_type + ".set_Item";
3608 SetBuilder = parent.TypeBuilder.DefineMethod (
3609 meth_name, attr, null, parameters);
3610 if (implementing != null)
3611 parent.TypeBuilder.DefineMethodOverride (
3612 SetBuilder, implementing);
3614 PropertyBuilder.SetSetMethod (SetBuilder);
3618 public override bool Define (TypeContainer parent)
3620 PropertyAttributes prop_attr =
3621 PropertyAttributes.RTSpecialName |
3622 PropertyAttributes.SpecialName;
3625 IndexerType = RootContext.LookupType (parent, Type, false, Location);
3626 Type [] parameters = FormalParameters.GetParameterInfo (parent);
3628 // Check if the return type and arguments were correct
3629 if (IndexerType == null || parameters == null)
3632 if (!parent.MethodModifiersValid (ModFlags, InterfaceType == null ?
3633 "this" : InterfaceType, Location))
3637 // verify accessibility and unsafe pointers
3639 if (!TypeContainer.AsAccessible (IndexerType, ModFlags))
3642 if (IndexerType.IsPointer && !UnsafeOK (parent))
3645 foreach (Type partype in parameters){
3646 if (!TypeContainer.AsAccessible (partype, ModFlags))
3648 if (partype.IsPointer && !UnsafeOK (parent))
3655 Type iface_type = null;
3657 if (InterfaceType != null){
3658 iface_type = RootContext.LookupType (parent, InterfaceType, false, Location);
3659 if (iface_type == null)
3664 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3665 TypeManager.IndexerPropertyName (parent.TypeBuilder),
3666 prop_attr, IndexerType, parameters);
3668 MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
3671 DefineMethod (parent, iface_type, IndexerType, "get_Item",
3672 parameters, attr, true);
3673 InternalParameters pi = new InternalParameters (parent, FormalParameters);
3674 if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) {
3675 Report.Error (111, Location,
3676 "Class `" + parent.Name +
3677 "' already contains a definition with the " +
3678 "same return value and parameter types for the " +
3685 int top = parameters.Length;
3686 Type [] set_pars = new Type [top + 1];
3687 parameters.CopyTo (set_pars, 0);
3688 set_pars [top] = IndexerType;
3690 Parameter [] fixed_parms = FormalParameters.FixedParameters;
3692 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3694 fixed_parms.CopyTo (tmp, 0);
3695 tmp [fixed_parms.Length] = new Parameter (
3696 Type, "value", Parameter.Modifier.NONE, null);
3698 Parameters set_formal_params = new Parameters (tmp, null, Location);
3701 parent, iface_type, TypeManager.void_type,
3702 "set_Item", set_pars, attr, false);
3704 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3706 if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) {
3709 "Class `" + parent.Name + "' already contains a " +
3710 "definition with the " +
3711 "same return value and parameter types for the " +
3718 // Now name the parameters
3720 Parameter [] p = FormalParameters.FixedParameters;
3724 for (i = 0; i < p.Length; ++i) {
3726 GetBuilder.DefineParameter (
3727 i + 1, p [i].Attributes, p [i].Name);
3730 SetBuilder.DefineParameter (
3731 i + 1, p [i].Attributes, p [i].Name);
3735 SetBuilder.DefineParameter (
3736 i + 1, ParameterAttributes.None, "value");
3738 if (i != parameters.Length) {
3739 Parameter array_param = FormalParameters.ArrayParameter;
3740 SetBuilder.DefineParameter (i + 1, array_param.Attributes,
3745 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
3750 public void Emit (TypeContainer tc)
3755 ec = new EmitContext (tc, Location, null, IndexerType, ModFlags);
3756 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3759 ig = GetBuilder.GetILGenerator ();
3760 ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags);
3762 ec.EmitTopBlock (Get, Location);
3766 ig = SetBuilder.GetILGenerator ();
3767 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3769 ec.EmitTopBlock (Set, Location);
3774 public class Operator : MemberCore {
3776 const int AllowedModifiers =
3782 const int RequiredModifiers =
3786 public enum OpType : byte {
3796 // Unary and Binary operators
3819 // Implicit and Explicit
3824 public readonly OpType OperatorType;
3825 public readonly string ReturnType;
3826 public readonly string FirstArgType;
3827 public readonly string FirstArgName;
3828 public readonly string SecondArgType;
3829 public readonly string SecondArgName;
3830 public readonly Block Block;
3831 public Attributes OptAttributes;
3832 public MethodBuilder OperatorMethodBuilder;
3834 public string MethodName;
3835 public Method OperatorMethod;
3837 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
3838 string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
3841 OperatorType = type;
3842 ReturnType = ret_type;
3843 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
3844 FirstArgType = arg1type;
3845 FirstArgName = arg1name;
3846 SecondArgType = arg2type;
3847 SecondArgName = arg2name;
3849 OptAttributes = attrs;
3852 string Prototype (TypeContainer parent)
3854 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
3855 SecondArgType + ")";
3858 public override bool Define (TypeContainer parent)
3861 MethodName = "op_" + OperatorType;
3863 if (SecondArgType != null)
3866 Parameter [] param_list = new Parameter [length];
3868 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
3871 "User defined operators `" +
3872 Prototype (parent) +
3873 "' must be declared static and public");
3877 param_list[0] = new Parameter (FirstArgType, FirstArgName,
3878 Parameter.Modifier.NONE, null);
3879 if (SecondArgType != null)
3880 param_list[1] = new Parameter (SecondArgType, SecondArgName,
3881 Parameter.Modifier.NONE, null);
3883 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
3884 new Parameters (param_list, null, Location),
3885 OptAttributes, Mono.CSharp.Location.Null);
3887 OperatorMethod.Define (parent);
3889 if (OperatorMethod.MethodBuilder == null)
3892 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
3894 Type [] param_types = OperatorMethod.ParameterTypes (parent);
3895 Type declaring_type = OperatorMethodBuilder.DeclaringType;
3896 Type return_type = OperatorMethod.GetReturnType (parent);
3897 Type first_arg_type = param_types [0];
3899 // Rules for conversion operators
3901 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
3902 if (first_arg_type == return_type && first_arg_type == declaring_type){
3905 "User-defined conversion cannot take an object of the " +
3906 "enclosing type and convert to an object of the enclosing" +
3911 if (first_arg_type != declaring_type && return_type != declaring_type){
3914 "User-defined conversion must convert to or from the " +
3919 if (first_arg_type == TypeManager.object_type ||
3920 return_type == TypeManager.object_type){
3923 "User-defined conversion cannot convert to or from " +
3928 if (first_arg_type.IsInterface || return_type.IsInterface){
3931 "User-defined conversion cannot convert to or from an " +
3936 if (first_arg_type.IsSubclassOf (return_type) ||
3937 return_type.IsSubclassOf (first_arg_type)){
3940 "User-defined conversion cannot convert between types " +
3941 "that derive from each other");
3944 } else if (SecondArgType == null) {
3945 // Checks for Unary operators
3947 if (first_arg_type != declaring_type){
3950 "The parameter of a unary operator must be the " +
3955 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
3956 if (return_type != declaring_type){
3959 "The parameter and return type for ++ and -- " +
3960 "must be the containing type");
3966 if (OperatorType == OpType.True || OperatorType == OpType.False) {
3967 if (return_type != TypeManager.bool_type){
3970 "The return type of operator True or False " +
3977 // Checks for Binary operators
3979 if (first_arg_type != declaring_type &&
3980 param_types [1] != declaring_type){
3983 "One of the parameters of a binary operator must " +
3984 "be the containing type");
3992 public void Emit (TypeContainer parent)
3994 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
3995 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
3998 // abstract or extern methods have no bodies
4000 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4003 OperatorMethod.Block = Block;
4004 OperatorMethod.Emit (parent);
4009 // This is used to compare method signatures
4011 struct MethodSignature {
4013 public Type RetType;
4014 public Type [] Parameters;
4017 /// This delegate is used to extract methods which have the
4018 /// same signature as the argument
4020 public static MemberFilter method_signature_filter;
4023 /// This delegate is used to extract inheritable methods which
4024 /// have the same signature as the argument. By inheritable,
4025 /// this means that we have permissions to override the method
4026 /// from the current assembly and class
4028 public static MemberFilter inheritable_method_signature_filter;
4030 static MethodSignature ()
4032 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4033 inheritable_method_signature_filter = new MemberFilter (
4034 InheritableMemberSignatureCompare);
4037 public MethodSignature (string name, Type ret_type, Type [] parameters)
4042 if (parameters == null)
4043 Parameters = TypeManager.NoTypes;
4045 Parameters = parameters;
4048 public override int GetHashCode ()
4050 return Name.GetHashCode ();
4053 public override bool Equals (Object o)
4055 MethodSignature other = (MethodSignature) o;
4057 if (other.Name != Name)
4060 if (other.RetType != RetType)
4063 if (Parameters == null){
4064 if (other.Parameters == null)
4069 if (other.Parameters == null)
4072 int c = Parameters.Length;
4073 if (other.Parameters.Length != c)
4076 for (int i = 0; i < c; i++)
4077 if (other.Parameters [i] != Parameters [i])
4083 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4087 if (! (m is MethodInfo))
4090 MethodSignature sig = (MethodSignature) filter_criteria;
4092 if (m.Name != sig.Name)
4095 mi = (MethodInfo) m;
4097 if (mi.ReturnType != sig.RetType)
4100 Type [] args = TypeManager.GetArgumentTypes (mi);
4101 Type [] sigp = sig.Parameters;
4103 if (args.Length != sigp.Length)
4106 for (int i = args.Length; i > 0; ){
4108 if (args [i] != sigp [i])
4115 // This filter should be used when we are requesting methods that
4116 // we want to override.
4118 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4120 if (MemberSignatureCompare (m, filter_criteria)){
4121 MethodInfo mi = (MethodInfo) m;
4122 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4124 // If only accessible to the current class.
4125 if (prot == MethodAttributes.Private)
4128 // If only accessible to the defining assembly or
4129 if (prot == MethodAttributes.FamANDAssem ||
4130 prot == MethodAttributes.Assembly){
4131 if (m is MethodBuilder)
4137 // Anything else (FamOrAssembly and Public) is fine