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
70 // The emit context for toplevel objects.
74 // Pointers to the default constructor and the default static constructor
76 Constructor default_constructor;
77 Constructor default_static_constructor;
80 // Whether we have seen a static constructor for this class or not
82 bool have_static_constructor = false;
85 // This one is computed after we can distinguish interfaces
86 // from classes from the arraylist `type_bases'
88 string base_class_name;
92 // Attributes for this type
93 protected Attributes attributes;
95 // Information in the case we are an attribute type
97 public AttributeTargets Targets = AttributeTargets.All;
98 public bool AllowMultiple = false;
99 public bool Inherited;
102 // The indexer name for this class
104 public string IndexerName;
106 public TypeContainer (TypeContainer parent, string name, Location l)
107 : base (parent, name, l)
110 types = new ArrayList ();
117 base_class_name = null;
119 //Console.WriteLine ("New class " + name + " inside " + n);
122 public AdditionResult AddConstant (Const constant)
125 string name = constant.Name;
127 if ((res = IsValid (name)) != AdditionResult.Success)
130 if (constants == null)
131 constants = new ArrayList ();
133 constants.Add (constant);
134 DefineName (name, constant);
136 return AdditionResult.Success;
139 public AdditionResult AddEnum (Mono.CSharp.Enum e)
142 string name = e.Name;
144 if ((res = IsValid (name)) != AdditionResult.Success)
148 enums = new ArrayList ();
151 DefineName (name, e);
153 return AdditionResult.Success;
156 public AdditionResult AddClass (Class c)
159 string name = c.Name;
162 if ((res = IsValid (name)) != AdditionResult.Success)
165 DefineName (name, c);
168 return AdditionResult.Success;
171 public AdditionResult AddStruct (Struct s)
174 string name = s.Name;
176 if ((res = IsValid (name)) != AdditionResult.Success)
179 DefineName (name, s);
182 return AdditionResult.Success;
185 public AdditionResult AddDelegate (Delegate d)
188 string name = d.Name;
190 if ((res = IsValid (name)) != AdditionResult.Success)
193 if (delegates == null)
194 delegates = new ArrayList ();
196 DefineName (name, d);
199 return AdditionResult.Success;
202 public AdditionResult AddMethod (Method method)
204 string name = method.Name;
205 Object value = defined_names [name];
207 if (value != null && (!(value is Method)))
208 return AdditionResult.NameExists;
211 methods = new ArrayList ();
213 methods.Add (method);
215 DefineName (name, method);
217 return AdditionResult.Success;
220 public AdditionResult AddConstructor (Constructor c)
222 if (c.Name != Basename)
223 return AdditionResult.NotAConstructor;
225 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
228 have_static_constructor = true;
229 if (default_static_constructor != null){
230 Console.WriteLine ("I have a static constructor already");
231 Console.WriteLine (" " + default_static_constructor);
232 return AdditionResult.MethodExists;
235 default_static_constructor = c;
238 if (default_constructor != null)
239 return AdditionResult.MethodExists;
240 default_constructor = c;
243 if (instance_constructors == null)
244 instance_constructors = new ArrayList ();
246 instance_constructors.Add (c);
249 return AdditionResult.Success;
252 public AdditionResult AddInterface (Interface iface)
255 string name = iface.Name;
257 if ((res = IsValid (name)) != AdditionResult.Success)
260 if (interfaces == null)
261 interfaces = new ArrayList ();
262 interfaces.Add (iface);
263 DefineName (name, iface);
265 return AdditionResult.Success;
268 public AdditionResult AddField (Field field)
271 string name = field.Name;
273 if ((res = IsValid (name)) != AdditionResult.Success)
277 fields = new ArrayList ();
281 if (field.Initializer != null){
282 if ((field.ModFlags & Modifiers.STATIC) != 0){
283 if (initialized_static_fields == null)
284 initialized_static_fields = new ArrayList ();
286 initialized_static_fields.Add (field);
289 // We have not seen a static constructor,
290 // but we will provide static initialization of fields
292 have_static_constructor = true;
294 if (initialized_fields == null)
295 initialized_fields = new ArrayList ();
297 initialized_fields.Add (field);
301 DefineName (name, field);
302 return AdditionResult.Success;
305 public AdditionResult AddProperty (Property prop)
308 string name = prop.Name;
310 if ((res = IsValid (name)) != AdditionResult.Success)
313 if (properties == null)
314 properties = new ArrayList ();
316 properties.Add (prop);
317 DefineName (name, prop);
319 return AdditionResult.Success;
322 public AdditionResult AddEvent (Event e)
325 string name = e.Name;
327 if ((res = IsValid (name)) != AdditionResult.Success)
331 events = new ArrayList ();
334 DefineName (name, e);
336 return AdditionResult.Success;
339 public AdditionResult AddIndexer (Indexer i)
341 if (indexers == null)
342 indexers = new ArrayList ();
346 return AdditionResult.Success;
349 public AdditionResult AddOperator (Operator op)
351 if (operators == null)
352 operators = new ArrayList ();
356 return AdditionResult.Success;
359 public void RegisterOrder (Interface iface)
361 if (interface_order == null)
362 interface_order = new ArrayList ();
364 interface_order.Add (iface);
367 public ArrayList Types {
373 public ArrayList Methods {
379 public ArrayList Constants {
385 public ArrayList Interfaces {
393 return base_class_name;
397 public ArrayList Bases {
407 public ArrayList Fields {
413 public ArrayList InstanceConstructors {
415 return instance_constructors;
419 public ArrayList Properties {
425 public ArrayList Events {
431 public ArrayList Enums {
437 public ArrayList Indexers {
443 public ArrayList Operators {
449 public ArrayList Delegates {
455 public Attributes OptAttributes {
461 public bool HaveStaticConstructor {
463 return have_static_constructor;
467 public virtual TypeAttributes TypeAttr {
469 return Modifiers.TypeAttr (ModFlags, this);
474 // Emits the instance field initializers
476 public bool EmitFieldInitializers (EmitContext ec)
479 ILGenerator ig = ec.ig;
480 Expression instance_expr;
483 fields = initialized_static_fields;
484 instance_expr = null;
486 fields = initialized_fields;
487 instance_expr = new This (Location.Null).Resolve (ec);
493 foreach (Field f in fields){
494 Object init = f.Initializer;
497 if (init is Expression)
498 e = (Expression) init;
500 string base_type = f.Type.Substring (0, f.Type.IndexOf ("["));
501 string rank = f.Type.Substring (f.Type.IndexOf ("["));
502 e = new ArrayCreation (base_type, rank, (ArrayList)init, f.Location);
505 Location l = f.Location;
506 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
507 fe.InstanceExpression = instance_expr;
508 Expression a = new Assign (fe, e, l);
514 if (a is ExpressionStatement)
515 ((ExpressionStatement) a).EmitStatement (ec);
517 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
525 // Defines the default constructors
527 void DefineDefaultConstructor (bool is_static)
532 c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
533 new ConstructorBaseInitializer (null, new Location (-1)),
537 mods = Modifiers.STATIC;
543 c.Block = new Block (null);
547 public void ReportStructInitializedInstanceError ()
549 string n = TypeBuilder.FullName;
551 foreach (Field f in initialized_fields){
554 "`" + n + "." + f.Name + "': can not have " +
555 "instance field initializers in structs");
559 struct TypeAndMethods {
561 public MethodInfo [] methods;
563 // Far from ideal, but we want to avoid creating a copy
565 public Type [][] args;
568 // This flag on the method says `We found a match, but
569 // because it was private, we could not use the match
571 public bool [] found;
575 // This array keeps track of the pending implementations
577 TypeAndMethods [] pending_implementations;
580 // Returns a list of the abstract methods that are exposed by all of our
581 // parents that we must implement. Notice that this `flattens' the
582 // method search space, and takes into account overrides.
584 ArrayList GetAbstractMethods (Type t)
586 ArrayList list = null;
587 bool searching = true;
588 Type current_type = t;
594 current_type, MemberTypes.Method,
595 BindingFlags.Public | BindingFlags.Instance |
596 BindingFlags.DeclaredOnly,
597 virtual_method_filter, null);
599 if (current_type == TypeManager.object_type)
602 current_type = current_type.BaseType;
603 if (!current_type.IsAbstract)
610 int count = mi.Length;
614 if (count == 1 && !(mi [0] is MethodBase))
617 list = TypeManager.CopyNewMethods (list, mi);
623 for (int i = 0; i < list.Count; i++){
624 while (list.Count > i && !((MethodInfo) list [i]).IsAbstract)
635 // Registers the required method implementations for this class
637 // Register method implementations are either abstract methods
638 // flagged as such on the base class or interface methods
640 public void RegisterRequiredImplementations ()
642 Type [] ifaces = TypeBuilder.GetInterfaces ();
643 Type b = TypeBuilder.BaseType;
648 Type x = TypeBuilder;
651 Type [] iff = x.GetInterfaces ();
652 Console.WriteLine ("Type: " + x.Name);
654 foreach (Type tt in iff){
655 Console.WriteLine (" Iface: " + tt.Name);
662 icount = ifaces.Length;
665 // If we are implementing an abstract class, and we are not
666 // ourselves abstract, and there are abstract methods (C# allows
667 // abstract classes that have no abstract methods), then allocate
670 // We also pre-compute the methods.
672 bool implementing_abstract = (b.IsAbstract && !TypeBuilder.IsAbstract);
673 ArrayList abstract_methods = null;
675 if (implementing_abstract){
676 abstract_methods = GetAbstractMethods (b);
678 if (abstract_methods == null)
679 implementing_abstract = false;
682 int total = icount + (implementing_abstract ? 1 : 0);
686 pending_implementations = new TypeAndMethods [total];
690 foreach (Type t in ifaces){
693 if (t is TypeBuilder){
696 iface = TypeManager.LookupInterface (t);
698 mi = iface.GetMethods ();
700 mi = t.GetMethods ();
702 int count = mi.Length;
703 pending_implementations [i].type = t;
704 pending_implementations [i].methods = mi;
705 pending_implementations [i].args = new Type [count][];
706 pending_implementations [i].found = new bool [count];
709 foreach (MethodInfo m in mi){
710 Type [] types = TypeManager.GetArgumentTypes (m);
712 pending_implementations [i].args [j] = types;
719 if (abstract_methods != null){
720 int count = abstract_methods.Count;
721 pending_implementations [i].methods = new MethodInfo [count];
723 abstract_methods.CopyTo (pending_implementations [i].methods, 0);
724 pending_implementations [i].found = new bool [count];
725 pending_implementations [i].args = new Type [count][];
726 pending_implementations [i].type = TypeBuilder;
729 foreach (MemberInfo m in abstract_methods){
730 MethodInfo mi = (MethodInfo) m;
732 Type [] types = TypeManager.GetArgumentTypes (mi);
734 pending_implementations [i].args [j] = types;
741 /// This function computes the Base class and also the
742 /// list of interfaces that the class or struct @c implements.
744 /// The return value is an array (might be null) of
745 /// interfaces implemented (as Types).
747 /// The @parent argument is set to the parent object or null
748 /// if this is `System.Object'.
750 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
752 ArrayList bases = Bases;
761 parent = TypeManager.value_type;
765 if (RootContext.StdLib)
766 parent = TypeManager.object_type;
767 else if (Name != "System.Object")
768 parent = TypeManager.object_type;
771 // If we are compiling our runtime,
772 // and we are defining ValueType, then our
773 // parent is `System.Object'.
775 if (!RootContext.StdLib && Name == "System.ValueType")
776 parent = TypeManager.object_type;
783 // Bases should be null if there are no bases at all
788 string name = (string) bases [0];
789 Type first = FindType (name);
800 parent = TypeManager.object_type;
808 Type [] ifaces = new Type [count-start];
810 for (i = start, j = 0; i < count; i++, j++){
811 string name = (string) bases [i];
812 Type t = FindType (name);
819 if (is_class == false && !t.IsInterface){
820 Report.Error (527, "In Struct `" + Name + "', type `"+
821 name +"' is not an interface");
830 detail = " (a class can not inherit from a struct/enum)";
832 Report.Error (509, "class `"+ Name +
833 "': Cannot inherit from sealed class `"+
834 bases [i]+"'"+detail);
841 Report.Error (527, "In Class `" + Name + "', type `"+
842 name+"' is not an interface");
855 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
857 public override TypeBuilder DefineType ()
864 if (TypeBuilder != null)
877 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
879 ifaces = GetClassBases (is_class, out parent, out error);
884 if (is_class && parent != null){
885 if (parent == TypeManager.enum_type ||
886 (parent == TypeManager.value_type && RootContext.StdLib) ||
887 parent == TypeManager.delegate_type ||
888 parent == TypeManager.array_type){
890 644, Location, "`" + Name + "' cannot inherit from " +
891 "special class `" + TypeManager.CSharpName (parent) + "'");
896 if (!is_class && TypeManager.value_type == null)
897 throw new Exception ();
899 TypeAttributes type_attributes = TypeAttr;
901 // if (parent_builder is ModuleBuilder) {
903 ModuleBuilder builder = CodeGen.ModuleBuilder;
906 // Structs with no fields need to have a ".size 1"
910 if (!is_class && Fields == null)
911 TypeBuilder = builder.DefineType (Name,
914 PackingSize.Unspecified, 1);
917 // classes or structs with fields
919 TypeBuilder = builder.DefineType (Name,
924 TypeBuilder builder = Parent.TypeBuilder;
927 // Structs with no fields need to have a ".size 1"
930 if (!is_class && Fields == null)
931 TypeBuilder = builder.DefineNestedType (Basename,
934 PackingSize.Unspecified);
937 // classes or structs with fields
939 TypeBuilder = builder.DefineNestedType (Basename,
947 // Finish the setup for the EmitContext
949 ec.ContainerType = TypeBuilder;
951 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
953 if (parent == TypeManager.attribute_type ||
954 parent.IsSubclassOf (TypeManager.attribute_type)) {
955 RootContext.RegisterAttribute (this);
956 TypeManager.RegisterAttrType (TypeBuilder, this);
958 RootContext.RegisterOrder (this);
960 if (Interfaces != null) {
961 foreach (Interface iface in Interfaces)
966 foreach (TypeContainer tc in Types)
970 if (Delegates != null) {
971 foreach (Delegate d in Delegates)
976 foreach (Enum en in Enums)
986 /// Defines the MemberCore objects that are in the `list' Arraylist
988 /// The `defined_names' array contains a list of members defined in
991 static ArrayList remove_list = new ArrayList ();
992 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
996 remove_list.Clear ();
998 foreach (MemberCore mc in list){
999 if (!mc.Define (this)){
1000 remove_list.Add (mc);
1004 if (defined_names == null)
1007 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
1009 if (RootContext.WarningLevel >= 4){
1010 if ((mc.ModFlags & Modifiers.NEW) != 0)
1011 Warning_KewywordNewNotRequired (mc.Location, mc);
1016 MemberInfo match = defined_names [idx];
1018 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
1022 // If we are both methods, let the method resolution emit warnings
1024 if (match is MethodBase && mc is MethodCore)
1027 if ((mc.ModFlags & Modifiers.NEW) == 0)
1028 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
1031 foreach (object o in remove_list)
1034 remove_list.Clear ();
1038 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
1039 // class is consisten. Either it is `Item' or it is the name defined by all the
1040 // indexers with the `IndexerName' attribute.
1042 // Turns out that the IndexerNameAttribute is applied to each indexer,
1043 // but it is never emitted, instead a DefaultName attribute is attached
1046 void DefineIndexers ()
1048 string class_indexer_name = null;
1050 foreach (Indexer i in Indexers){
1055 name = i.IndexerName;
1056 if (class_indexer_name == null){
1057 class_indexer_name = name;
1061 if (name == class_indexer_name)
1065 668, "Two indexers have different names, " +
1066 " you should use the same name for all your indexers");
1068 if (class_indexer_name == null)
1069 class_indexer_name = "Item";
1070 IndexerName = class_indexer_name;
1074 /// Populates our TypeBuilder with fields and methods
1076 public override bool Define (TypeContainer parent)
1078 MemberInfo [] defined_names = null;
1080 if (RootContext.WarningLevel > 1){
1084 // This code throws an exception in the comparer
1085 // I guess the string is not an object?
1087 ptype = TypeBuilder.BaseType;
1089 defined_names = FindMembers (
1090 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1091 BindingFlags.Public | BindingFlags.Instance |
1092 BindingFlags.Static, null, null);
1094 Array.Sort (defined_names, mif_compare);
1098 if (constants != null)
1099 DefineMembers (constants, defined_names);
1102 DefineMembers (fields, defined_names);
1105 if (instance_constructors == null){
1106 if (default_constructor == null)
1107 DefineDefaultConstructor (false);
1110 if (initialized_static_fields != null &&
1111 default_static_constructor == null)
1112 DefineDefaultConstructor (true);
1115 if (this is Struct){
1117 // Structs can not have initialized instance
1120 if (initialized_static_fields != null &&
1121 default_static_constructor == null)
1122 DefineDefaultConstructor (true);
1124 if (initialized_fields != null)
1125 ReportStructInitializedInstanceError ();
1128 RegisterRequiredImplementations ();
1131 // Constructors are not in the defined_names array
1133 if (instance_constructors != null)
1134 DefineMembers (instance_constructors, null);
1136 if (default_static_constructor != null)
1137 default_static_constructor.Define (this);
1139 if (methods != null)
1140 DefineMembers (methods, defined_names);
1142 if (properties != null)
1143 DefineMembers (properties, defined_names);
1146 DefineMembers (events, defined_names);
1148 if (indexers != null) {
1151 IndexerName = "Item";
1153 if (operators != null)
1154 DefineMembers (operators, null);
1157 DefineMembers (enums, defined_names);
1159 if (delegates != null)
1160 DefineMembers (delegates, defined_names);
1166 /// Looks up the alias for the name
1168 public string LookupAlias (string name)
1170 if (Namespace != null)
1171 return Namespace.LookupAlias (name);
1177 /// This function is based by a delegate to the FindMembers routine
1179 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1185 /// This filter is used by FindMembers, and we just keep
1186 /// a global for the filter to `AlwaysAccept'
1188 static MemberFilter accepting_filter;
1190 static bool IsVirtualFilter (MemberInfo m, object filterCriteria)
1192 if (!(m is MethodInfo))
1195 return ((MethodInfo) m).IsVirtual;
1199 /// This filter is used by FindMembers, and it is used to
1200 /// extract only virtual/abstract fields
1202 static MemberFilter virtual_method_filter;
1205 /// A member comparission method based on name only
1207 static IComparer mif_compare;
1209 static TypeContainer ()
1211 accepting_filter = new MemberFilter (AlwaysAccept);
1212 virtual_method_filter = new MemberFilter (IsVirtualFilter);
1213 mif_compare = new MemberInfoCompare ();
1217 /// This method returns the members of this type just like Type.FindMembers would
1218 /// Only, we need to use this for types which are _being_ defined because MS'
1219 /// implementation can't take care of that.
1222 // FIXME: return an empty static array instead of null, that cleans up
1223 // some code and is consistent with some coding conventions I just found
1227 // Notice that in various cases we check if our field is non-null,
1228 // something that would normally mean that there was a bug elsewhere.
1230 // The problem happens while we are defining p-invoke methods, as those
1231 // will trigger a FindMembers, but this happens before things are defined
1233 // Since the whole process is a no-op, it is fine to check for null here.
1235 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1236 MemberFilter filter, object criteria)
1238 ArrayList members = new ArrayList ();
1239 bool priv = (bf & BindingFlags.NonPublic) != 0;
1242 filter = accepting_filter;
1244 if ((mt & MemberTypes.Field) != 0) {
1245 if (fields != null) {
1246 foreach (Field f in fields) {
1247 if ((f.ModFlags & Modifiers.PRIVATE) != 0)
1251 FieldBuilder fb = f.FieldBuilder;
1252 if (fb != null && filter (fb, criteria) == true)
1257 if (constants != null) {
1258 foreach (Const con in constants) {
1259 if ((con.ModFlags & Modifiers.PRIVATE) != 0)
1263 FieldBuilder fb = con.FieldBuilder;
1264 if (fb != null && filter (fb, criteria) == true)
1270 if ((mt & MemberTypes.Method) != 0) {
1271 if (methods != null) {
1272 foreach (Method m in methods) {
1273 if ((m.ModFlags & Modifiers.PRIVATE) != 0)
1277 MethodBuilder mb = m.MethodBuilder;
1279 if (mb != null && filter (mb, criteria) == true)
1284 if (operators != null){
1285 foreach (Operator o in operators) {
1286 if ((o.ModFlags & Modifiers.PRIVATE) != 0)
1290 MethodBuilder ob = o.OperatorMethodBuilder;
1291 if (ob != null && filter (ob, criteria) == true)
1296 if (properties != null){
1297 foreach (Property p in properties){
1298 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1305 if (b != null && filter (b, criteria) == true)
1309 if (b != null && filter (b, criteria) == true)
1315 if ((mt & MemberTypes.Event) != 0) {
1317 foreach (Event e in events) {
1318 if ((e.ModFlags & Modifiers.PRIVATE) != 0)
1322 MemberInfo eb = e.EventBuilder;
1323 if (eb != null && filter (eb, criteria) == true)
1324 members.Add (e.EventBuilder);
1328 if ((mt & MemberTypes.Property) != 0){
1329 if (properties != null)
1330 foreach (Property p in properties) {
1331 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1335 MemberInfo pb = p.PropertyBuilder;
1336 if (pb != null && filter (pb, criteria) == true) {
1337 members.Add (p.PropertyBuilder);
1341 if (indexers != null)
1342 foreach (Indexer ix in indexers) {
1343 if ((ix.ModFlags & Modifiers.PRIVATE) != 0)
1347 MemberInfo ib = ix.PropertyBuilder;
1348 if (ib != null && filter (ib, criteria) == true) {
1349 members.Add (ix.PropertyBuilder);
1354 if ((mt & MemberTypes.NestedType) != 0) {
1357 foreach (TypeContainer t in Types)
1358 if (filter (t.TypeBuilder, criteria) == true)
1359 members.Add (t.TypeBuilder);
1362 foreach (Enum en in Enums)
1363 if (filter (en.TypeBuilder, criteria) == true)
1364 members.Add (en.TypeBuilder);
1368 if ((mt & MemberTypes.Constructor) != 0){
1369 if (instance_constructors != null){
1370 foreach (Constructor c in instance_constructors){
1371 ConstructorBuilder cb = c.ConstructorBuilder;
1374 if (filter (cb, criteria) == true)
1379 if (default_static_constructor != null){
1380 ConstructorBuilder cb =
1381 default_static_constructor.ConstructorBuilder;
1383 if (filter (cb, criteria) == true)
1389 // Lookup members in parent if requested.
1391 if ((bf & BindingFlags.DeclaredOnly) == 0){
1394 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1396 members.AddRange (mi);
1399 int count = members.Count;
1401 MemberInfo [] mi = new MemberInfo [count];
1402 members.CopyTo (mi);
1409 public MemberInfo GetFieldFromEvent (EventExpr event_expr)
1411 EventInfo ei = event_expr.EventInfo;
1413 foreach (Event e in events) {
1415 if (e.FieldBuilder == null)
1418 if (Type.FilterName (e.FieldBuilder, ei.Name))
1419 return e.FieldBuilder;
1425 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1426 MemberFilter filter, object criteria)
1428 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1431 return tc.FindMembers (mt, bf, filter, criteria);
1433 return t.FindMembers (mt, bf, filter, criteria);
1437 // FindMethods will look for methods not only in the type `t', but in
1438 // any interfaces implemented by the type.
1440 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1441 MemberFilter filter, object criteria)
1447 /// Whether the specified method is an interface method implementation
1451 /// If a method in Type `t' (or null to look in all interfaces
1452 /// and the base abstract class) with name `Name', return type `ret_type' and
1453 /// arguments `args' implements an interface, this method will
1454 /// return the MethodInfo that this method implements.
1456 /// This will remove the method from the list of "pending" methods
1457 /// that are required to be implemented for this class as a side effect.
1460 public MethodInfo IsInterfaceMethod (Type t, string Name, Type ret_type, Type [] args,
1463 int arg_len = args.Length;
1465 if (pending_implementations == null)
1468 foreach (TypeAndMethods tm in pending_implementations){
1469 if (!(t == null || tm.type == t))
1473 foreach (MethodInfo m in tm.methods){
1479 if (Name != m.Name){
1484 if (ret_type != m.ReturnType){
1485 if (!((ret_type == null && m.ReturnType == TypeManager.void_type) ||
1486 (m.ReturnType == null && ret_type == TypeManager.void_type)))
1494 // Check if we have the same parameters
1496 if (tm.args [i].Length != arg_len){
1501 int j, top = args.Length;
1504 for (j = 0; j < top; j++){
1505 if (tm.args [i][j] != args[j]){
1516 tm.methods [i] = null;
1517 tm.found [i] = true;
1521 // If a specific type was requested, we can stop now.
1529 /// C# allows this kind of scenarios:
1530 /// interface I { void M (); }
1531 /// class X { public void M (); }
1532 /// class Y : X, I { }
1534 /// For that case, we create an explicit implementation function
1537 void DefineProxy (Type iface, MethodInfo parent_method, MethodInfo iface_method,
1540 MethodBuilder proxy;
1542 string proxy_name = iface.Name + "." + iface_method.Name;
1544 proxy = TypeBuilder.DefineMethod (
1546 MethodAttributes.HideBySig |
1547 MethodAttributes.NewSlot |
1548 MethodAttributes.Virtual,
1549 CallingConventions.Standard | CallingConventions.HasThis,
1550 parent_method.ReturnType, args);
1552 int top = args.Length;
1553 ILGenerator ig = proxy.GetILGenerator ();
1555 ig.Emit (OpCodes.Ldarg_0);
1556 for (int i = 0; i < top; i++){
1559 ig.Emit (OpCodes.Ldarg_1); break;
1561 ig.Emit (OpCodes.Ldarg_2); break;
1563 ig.Emit (OpCodes.Ldarg_3); break;
1565 ig.Emit (OpCodes.Ldarg, i - 1); break;
1568 ig.Emit (OpCodes.Call, parent_method);
1569 ig.Emit (OpCodes.Ret);
1571 TypeBuilder.DefineMethodOverride (proxy, iface_method);
1575 /// This function tells whether one of our parent classes implements
1576 /// the given method (which turns out, it is valid to have an interface
1577 /// implementation in a parent
1579 bool ParentImplements (Type iface_type, MethodInfo mi)
1583 Type [] args = TypeManager.GetArgumentTypes (mi);
1584 ms = new MethodSignature (mi.Name, mi.ReturnType, args);
1585 MemberInfo [] list = FindMembers (
1586 TypeBuilder.BaseType, MemberTypes.Method | MemberTypes.Property,
1587 BindingFlags.Public | BindingFlags.Instance,
1588 MethodSignature.method_signature_filter, ms);
1590 if (list == null || list.Length == 0)
1593 DefineProxy (iface_type, (MethodInfo) list [0], mi, args);
1598 /// Verifies that any pending abstract methods or interface methods
1599 /// were implemented.
1601 bool VerifyPendingMethods ()
1603 int top = pending_implementations.Length;
1604 bool errors = false;
1607 for (i = 0; i < top; i++){
1608 Type type = pending_implementations [i].type;
1611 foreach (MethodInfo mi in pending_implementations [i].methods){
1615 if (type.IsInterface){
1616 if (ParentImplements (type, mi))
1621 if (pending_implementations [i].found [j])
1622 extra = ". (method might be private or static)";
1625 "`" + Name + "' does not implement " +
1626 "interface member `" +
1627 type.FullName + "." + mi.Name + "'" + extra);
1631 "`" + Name + "' does not implement " +
1632 "inherited abstract member `" +
1633 type.FullName + "." + mi.Name + "'");
1643 /// Emits the values for the constants
1645 public void EmitConstants ()
1647 if (constants != null)
1648 foreach (Const con in constants)
1649 con.EmitConstant (this);
1654 /// Emits the code, this step is performed after all
1655 /// the types, enumerations, constructors
1659 if (instance_constructors != null)
1660 foreach (Constructor c in instance_constructors)
1663 if (default_static_constructor != null)
1664 default_static_constructor.Emit (this);
1666 if (methods != null)
1667 foreach (Method m in methods)
1670 if (operators != null)
1671 foreach (Operator o in operators)
1674 if (properties != null)
1675 foreach (Property p in properties)
1678 if (indexers != null){
1679 foreach (Indexer ix in indexers)
1682 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1683 this, IndexerName, ModFlags, Location);
1684 TypeBuilder.SetCustomAttribute (cb);
1688 foreach (Field f in fields)
1691 if (events != null){
1692 foreach (Event e in Events)
1696 if (pending_implementations != null)
1697 if (!VerifyPendingMethods ())
1700 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1703 // Check for internal or private fields that were never assigned
1705 if (fields != null && RootContext.WarningLevel >= 3) {
1706 foreach (Field f in fields) {
1707 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1712 169, f.Location, "Private field " +
1713 MakeName (f.Name) + " is never used");
1718 // Only report 649 on level 4
1720 if (RootContext.WarningLevel < 4)
1723 if ((f.status & Field.Status.ASSIGNED) != 0)
1728 "Field " + MakeName (f.Name) + " is never assigned " +
1729 " to and will always have its default value");
1733 // if (types != null)
1734 // foreach (TypeContainer tc in types)
1738 public override void CloseType ()
1743 TypeBuilder.CreateType ();
1745 } catch (TypeLoadException){
1747 // This is fine, the code still created the type
1749 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1750 // Console.WriteLine (e.Message);
1752 Console.WriteLine ("In type: " + Name);
1757 foreach (Enum en in Enums)
1760 if (interface_order != null){
1761 foreach (Interface iface in interface_order)
1766 foreach (TypeContainer tc in Types)
1770 foreach (TypeContainer tc in Types)
1771 if (!(tc is Struct))
1775 if (Delegates != null)
1776 foreach (Delegate d in Delegates)
1780 public string MakeName (string n)
1782 return "`" + Name + "." + n + "'";
1785 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1788 108, l, "The keyword new is required on " +
1789 MakeName (mi.Name) + " because it hides `" +
1790 mi.ReflectedType.Name + "." + mi.Name + "'");
1793 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1796 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1797 "inherited member, the keyword new is not required");
1800 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1806 // Performs the validation on a Method's modifiers (properties have
1807 // the same properties).
1809 public bool MethodModifiersValid (int flags, string n, Location loc)
1811 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1812 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1814 string name = MakeName (n);
1817 // At most one of static, virtual or override
1819 if ((flags & Modifiers.STATIC) != 0){
1820 if ((flags & vao) != 0){
1822 112, loc, "static method " + name + "can not be marked " +
1823 "as virtual, abstract or override");
1828 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1831 " marked as override cannot be marked as new or virtual");
1836 // If the declaration includes the abstract modifier, then the
1837 // declaration does not include static, virtual or extern
1839 if ((flags & Modifiers.ABSTRACT) != 0){
1840 if ((flags & Modifiers.EXTERN) != 0){
1842 180, loc, name + " can not be both abstract and extern");
1846 if ((flags & Modifiers.VIRTUAL) != 0){
1848 503, loc, name + " can not be both abstract and virtual");
1852 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1855 " is abstract but its container class is not");
1861 if ((flags & Modifiers.PRIVATE) != 0){
1862 if ((flags & vao) != 0){
1865 " virtual or abstract members can not be private");
1870 if ((flags & Modifiers.SEALED) != 0){
1871 if ((flags & Modifiers.OVERRIDE) == 0){
1874 " cannot be sealed because it is not an override");
1883 // Returns true if `type' is as accessible as the flags `flags'
1884 // given for this member
1886 static public bool AsAccessible (Type type, int flags)
1891 Hashtable builder_and_args;
1893 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1895 if (builder_and_args == null)
1896 builder_and_args = new Hashtable ();
1901 public class Class : TypeContainer {
1903 // Modifiers allowed in a class declaration
1905 public const int AllowedModifiers =
1908 Modifiers.PROTECTED |
1909 Modifiers.INTERNAL |
1911 Modifiers.ABSTRACT |
1915 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1916 : base (parent, name, l)
1920 if (parent.Parent == null)
1921 accmods = Modifiers.INTERNAL;
1923 accmods = Modifiers.PRIVATE;
1925 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1926 this.attributes = attrs;
1930 // FIXME: How do we deal with the user specifying a different
1933 public override TypeAttributes TypeAttr {
1935 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1940 public class Struct : TypeContainer {
1942 // Modifiers allowed in a struct declaration
1944 public const int AllowedModifiers =
1947 Modifiers.PROTECTED |
1948 Modifiers.INTERNAL |
1952 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1953 : base (parent, name, l)
1957 if (parent.Parent == null)
1958 accmods = Modifiers.INTERNAL;
1960 accmods = Modifiers.PRIVATE;
1962 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1964 this.ModFlags |= Modifiers.SEALED;
1965 this.attributes = attrs;
1970 // FIXME: Allow the user to specify a different set of attributes
1971 // in some cases (Sealed for example is mandatory for a class,
1972 // but what SequentialLayout can be changed
1974 public override TypeAttributes TypeAttr {
1976 return base.TypeAttr |
1977 TypeAttributes.SequentialLayout |
1978 TypeAttributes.Sealed |
1979 TypeAttributes.BeforeFieldInit;
1984 public abstract class MethodCore : MemberCore {
1985 public readonly Parameters Parameters;
1989 // Parameters, cached for semantic analysis.
1991 InternalParameters parameter_info;
1993 public MethodCore (string name, Parameters parameters, Location l)
1997 Parameters = parameters;
2001 // Returns the System.Type array for the parameters of this method
2003 Type [] parameter_types;
2004 public Type [] ParameterTypes (TypeContainer parent)
2006 if (Parameters == null)
2007 return TypeManager.NoTypes;
2009 if (parameter_types == null)
2010 parameter_types = Parameters.GetParameterInfo (parent);
2012 return parameter_types;
2015 public InternalParameters ParameterInfo
2018 return parameter_info;
2022 parameter_info = value;
2026 public Block Block {
2036 public CallingConventions GetCallingConvention (bool is_class)
2038 CallingConventions cc = 0;
2040 cc = Parameters.GetCallingConvention ();
2043 if ((ModFlags & Modifiers.STATIC) == 0)
2044 cc |= CallingConventions.HasThis;
2046 // FIXME: How is `ExplicitThis' used in C#?
2051 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
2054 // Define each type attribute (in/out/ref) and
2055 // the argument names.
2057 Parameter [] p = Parameters.FixedParameters;
2060 MethodBuilder mb = null;
2061 ConstructorBuilder cb = null;
2063 if (builder is MethodBuilder)
2064 mb = (MethodBuilder) builder;
2066 cb = (ConstructorBuilder) builder;
2069 for (i = 0; i < p.Length; i++) {
2070 ParameterBuilder pb;
2073 pb = cb.DefineParameter (
2074 i + 1, p [i].Attributes, p [i].Name);
2076 pb = mb.DefineParameter (
2077 i + 1, p [i].Attributes, p [i].Name);
2079 Attributes attr = p [i].OptAttributes;
2081 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
2085 if (Parameters.ArrayParameter != null){
2086 ParameterBuilder pb;
2087 Parameter array_param = Parameters.ArrayParameter;
2090 pb = cb.DefineParameter (
2091 i + 1, array_param.Attributes,
2094 pb = mb.DefineParameter (
2095 i + 1, array_param.Attributes,
2098 CustomAttributeBuilder a = new CustomAttributeBuilder (
2099 TypeManager.cons_param_array_attribute, new object [0]);
2101 pb.SetCustomAttribute (a);
2106 public class Method : MethodCore {
2107 public readonly string ReturnType;
2108 public MethodBuilder MethodBuilder;
2109 public readonly Attributes OptAttributes;
2111 MethodAttributes flags;
2114 /// Modifiers allowed in a class declaration
2116 const int AllowedModifiers =
2119 Modifiers.PROTECTED |
2120 Modifiers.INTERNAL |
2125 Modifiers.OVERRIDE |
2126 Modifiers.ABSTRACT |
2131 // return_type can be "null" for VOID values.
2133 public Method (string return_type, int mod, string name, Parameters parameters,
2134 Attributes attrs, Location l)
2135 : base (name, parameters, l)
2137 ReturnType = return_type;
2138 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
2139 OptAttributes = attrs;
2143 // Returns the `System.Type' for the ReturnType of this
2144 // function. Provides a nice cache. (used between semantic analysis
2145 // and actual code generation
2147 Type type_return_type;
2149 public Type GetReturnType (TypeContainer parent)
2151 if (type_return_type == null)
2152 type_return_type = RootContext.LookupType (
2153 parent, ReturnType, false, Location);
2155 return type_return_type;
2158 void DuplicateEntryPoint (MethodInfo b, Location location)
2162 "Program `" + CodeGen.FileName +
2163 "' has more than one entry point defined: `" +
2164 TypeManager.CSharpSignature(b) + "'");
2167 void Report28 (MethodInfo b)
2169 if (RootContext.WarningLevel < 4)
2174 "`" + TypeManager.CSharpSignature(b) +
2175 "' has the wrong signature to be an entry point");
2178 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2180 if (b.ReturnType != TypeManager.void_type &&
2181 b.ReturnType != TypeManager.int32_type)
2184 if (pinfo.Count == 0)
2187 if (pinfo.Count > 1)
2190 Type t = pinfo.ParameterType(0);
2192 (t.GetArrayRank() == 1) &&
2193 (t.GetElementType() == TypeManager.string_type) &&
2194 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2203 public override bool Define (TypeContainer parent)
2205 Type ret_type = GetReturnType (parent);
2206 Type [] parameters = ParameterTypes (parent);
2208 MethodInfo implementing;
2209 Type iface_type = null;
2210 string iface = "", short_name;
2211 bool explicit_impl = false;
2213 // Check if the return type and arguments were correct
2214 if (ret_type == null || parameters == null)
2217 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2220 flags = Modifiers.MethodAttr (ModFlags);
2223 // verify accessibility
2225 if (!TypeContainer.AsAccessible (ret_type, ModFlags))
2228 if (ret_type.IsPointer && !UnsafeOK (parent))
2231 foreach (Type partype in parameters){
2232 if (!TypeContainer.AsAccessible (partype, ModFlags))
2234 if (partype.IsPointer && !UnsafeOK (parent))
2242 // Verify if the parent has a type with the same name, and then
2243 // check whether we have to create a new slot for it or not.
2245 Type ptype = parent.TypeBuilder.BaseType;
2247 // ptype is only null for System.Object while compiling corlib.
2249 MethodSignature ms = new MethodSignature (Name, null, parameters);
2250 MemberInfo [] mi, mi_static, mi_instance;
2252 mi_static = TypeContainer.FindMembers (
2253 ptype, MemberTypes.Method,
2254 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2255 MethodSignature.inheritable_method_signature_filter, ms);
2257 mi_instance = TypeContainer.FindMembers (
2258 ptype, MemberTypes.Method,
2259 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2260 MethodSignature.inheritable_method_signature_filter,
2263 if (mi_instance != null && mi_instance.Length > 0){
2265 } else if (mi_static != null && mi_static.Length > 0)
2270 if (mi != null && mi.Length > 0){
2271 if (!CheckMethodAgainstBase (parent, flags, (MethodInfo) mi [0])){
2275 if ((ModFlags & Modifiers.NEW) != 0)
2276 WarningNotHiding (parent);
2278 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2279 Report.Error (115, Location,
2280 parent.MakeName (Name) +
2281 " no suitable methods found to override");
2284 } else if ((ModFlags & Modifiers.NEW) != 0)
2285 WarningNotHiding (parent);
2288 // If we implement an interface, extract the interface name.
2291 if (Name.IndexOf (".") != -1){
2292 int pos = Name.LastIndexOf (".");
2293 iface = Name.Substring (0, pos);
2295 iface_type = RootContext.LookupType (parent, iface, false, Location);
2296 short_name = Name.Substring (pos + 1);
2298 if (iface_type == null)
2301 // Compute the full name that we need to export
2302 Name = iface_type.FullName + "." + short_name;
2303 explicit_impl = true;
2308 // Check if we are an implementation of an interface method or
2311 implementing = parent.IsInterfaceMethod (
2312 iface_type, short_name, ret_type, parameters, false);
2315 // For implicit implementations, make sure we are public, for
2316 // explicit implementations, make sure we are private.
2318 if (implementing != null){
2320 // Setting null inside this block will trigger a more
2321 // verbose error reporting for missing interface implementations
2323 // The "candidate" function has been flagged already
2324 // but it wont get cleared
2326 if (iface_type == null){
2328 // We already catch different accessibility settings
2329 // so we just need to check that we are not private
2331 if ((ModFlags & Modifiers.PRIVATE) != 0)
2332 implementing = null;
2335 // Static is not allowed
2337 if ((ModFlags & Modifiers.STATIC) != 0)
2338 implementing = null;
2340 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2342 106, Location, "`public' or `abstract' modifiers "+
2343 "are not allowed in explicit interface declarations"
2345 implementing = null;
2351 // If implementing is still valid, set flags
2353 if (implementing != null){
2354 if (implementing.DeclaringType.IsInterface)
2355 flags |= MethodAttributes.NewSlot;
2358 MethodAttributes.Virtual |
2359 MethodAttributes.HideBySig;
2364 parent.IsInterfaceMethod (
2365 iface_type, short_name, ret_type, parameters, true);
2368 Attribute dllimport_attr = null;
2369 if (OptAttributes != null && OptAttributes.AttributeSections != null) {
2370 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2371 if (asec.Attributes == null)
2374 foreach (Attribute a in asec.Attributes)
2375 if (a.Name.IndexOf ("DllImport") != -1) {
2376 flags |= MethodAttributes.PinvokeImpl;
2383 // Finally, define the method
2386 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2388 if ((ModFlags & Modifiers.STATIC) == 0) {
2389 Report.Error (601, Location, "The DllImport attribute must be specified on " +
2390 "a method marked 'static' and 'extern'.");
2394 EmitContext ec = new EmitContext (
2395 parent, Location, null, GetReturnType (parent), ModFlags);
2397 MethodBuilder = dllimport_attr.DefinePInvokeMethod (
2398 ec, parent.TypeBuilder,
2399 Name, flags, ret_type, parameters);
2401 MethodBuilder = parent.TypeBuilder.DefineMethod (
2403 GetCallingConvention (parent is Class),
2404 ret_type, parameters);
2406 if (implementing != null && explicit_impl)
2407 parent.TypeBuilder.DefineMethodOverride (
2408 MethodBuilder, implementing);
2411 if (MethodBuilder == null)
2415 // HACK because System.Reflection.Emit is lame
2417 ParameterInfo = new InternalParameters (parent, Parameters);
2419 if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo,
2423 "Class `" + parent.Name + "' already contains a definition with " +
2424 " the same return value and parameter types for method `" +
2430 // This is used to track the Entry Point,
2432 if (Name == "Main" &&
2433 ((ModFlags & Modifiers.STATIC) != 0) &&
2434 (RootContext.MainClass == null ||
2435 RootContext.MainClass == parent.TypeBuilder.FullName)){
2436 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2437 if (RootContext.EntryPoint == null) {
2438 RootContext.EntryPoint = MethodBuilder;
2439 RootContext.EntryPointLocation = Location;
2441 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2442 DuplicateEntryPoint (MethodBuilder, Location);
2445 Report28(MethodBuilder);
2454 public void Emit (TypeContainer parent)
2459 if ((flags & MethodAttributes.PinvokeImpl) == 0)
2460 ig = MethodBuilder.GetILGenerator ();
2464 ec = new EmitContext (parent, Location, ig, GetReturnType (parent), ModFlags);
2466 if (OptAttributes != null)
2467 Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location);
2470 LabelParameters (ec, ParameterTypes (parent), MethodBuilder);
2473 // abstract or extern methods have no bodies
2475 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
2477 if ((ModFlags & Modifiers.ABSTRACT) != 0){
2479 500, "Abstract method `" +
2480 TypeManager.CSharpSignature (MethodBuilder) +
2481 "' can not have a body");
2488 // Handle destructors specially
2490 // FIXME: This code generates buggy code
2492 if (Name == "Finalize" && type_return_type == TypeManager.void_type)
2493 EmitDestructor (ec);
2495 ISymbolWriter sw = CodeGen.SymbolWriter;
2497 if ((sw != null) && (!Location.IsNull (Location))) {
2498 MethodToken token = MethodBuilder.GetToken ();
2499 sw.OpenMethod (new SymbolToken (token.Token));
2500 sw.SetMethodSourceRange (Location.SymbolDocument,
2502 Block.EndLocation.SymbolDocument,
2503 Block.EndLocation.Row, 0);
2505 ec.EmitTopBlock (Block, Location);
2509 ec.EmitTopBlock (Block, Location);
2513 void EmitDestructor (EmitContext ec)
2515 ILGenerator ig = ec.ig;
2517 Label finish = ig.DefineLabel ();
2518 bool old_in_try = ec.InTry;
2519 Expression member_lookup;
2521 ig.BeginExceptionBlock ();
2523 ec.ReturnLabel = finish;
2524 ec.EmitTopBlock (Block, Location);
2525 ec.InTry = old_in_try;
2527 ig.MarkLabel (finish);
2528 bool old_in_finally = ec.InFinally;
2529 ec.InFinally = true;
2530 ig.BeginFinallyBlock ();
2532 member_lookup = Expression.MemberLookup (
2533 ec, ec.ContainerType.BaseType, "Finalize",
2534 MemberTypes.Method, Expression.AllBindingFlags, Location);
2536 if (member_lookup != null){
2537 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
2539 ig.Emit (OpCodes.Ldarg_0);
2540 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
2542 ec.InFinally = old_in_finally;
2544 ig.EndExceptionBlock ();
2545 //ig.MarkLabel (ec.ReturnLabel);
2546 ig.Emit (OpCodes.Ret);
2550 public abstract class ConstructorInitializer {
2551 ArrayList argument_list;
2552 ConstructorInfo parent_constructor;
2555 public ConstructorInitializer (ArrayList argument_list, Location location)
2557 this.argument_list = argument_list;
2558 this.location = location;
2561 public ArrayList Arguments {
2563 return argument_list;
2567 public bool Resolve (EmitContext ec)
2569 Expression parent_constructor_group;
2572 if (argument_list != null){
2573 foreach (Argument a in argument_list){
2574 if (!a.Resolve (ec, location))
2579 if (this is ConstructorBaseInitializer)
2580 t = ec.ContainerType.BaseType;
2582 t = ec.ContainerType;
2584 parent_constructor_group = Expression.MemberLookup (
2586 MemberTypes.Constructor,
2587 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2590 if (parent_constructor_group == null){
2591 Report.Error (1501, location,
2592 "Can not find a constructor for this argument list");
2596 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2597 (MethodGroupExpr) parent_constructor_group, argument_list, location);
2599 if (parent_constructor == null){
2600 Report.Error (1501, location,
2601 "Can not find a constructor for this argument list");
2608 public void Emit (EmitContext ec)
2610 ec.ig.Emit (OpCodes.Ldarg_0);
2611 if (argument_list != null)
2612 Invocation.EmitArguments (ec, null, argument_list);
2613 ec.ig.Emit (OpCodes.Call, parent_constructor);
2617 public class ConstructorBaseInitializer : ConstructorInitializer {
2618 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2623 public class ConstructorThisInitializer : ConstructorInitializer {
2624 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2629 public class Constructor : MethodCore {
2630 public ConstructorBuilder ConstructorBuilder;
2631 public ConstructorInitializer Initializer;
2632 public Attributes OptAttributes;
2635 // Modifiers allowed for a constructor.
2637 const int AllowedModifiers =
2639 Modifiers.PROTECTED |
2640 Modifiers.INTERNAL |
2646 // The spec claims that static is not permitted, but
2647 // my very own code has static constructors.
2649 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2650 : base (name, args, l)
2656 // Returns true if this is a default constructor
2658 public bool IsDefault ()
2660 if ((ModFlags & Modifiers.STATIC) != 0)
2661 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2662 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2665 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2666 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2667 (Initializer is ConstructorBaseInitializer) &&
2668 (Initializer.Arguments == null);
2672 // Creates the ConstructorBuilder
2674 public override bool Define (TypeContainer parent)
2676 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2677 MethodAttributes.SpecialName);
2679 Type [] parameters = ParameterTypes (parent);
2681 if (parameters == null)
2684 if ((ModFlags & Modifiers.STATIC) != 0)
2685 ca |= MethodAttributes.Static;
2687 if (parent is Struct && parameters.Length == 0){
2690 "Structs can not contain explicit parameterless " +
2694 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2697 foreach (Type partype in parameters)
2698 if (!TypeContainer.AsAccessible (partype, ModFlags))
2701 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2702 ca, GetCallingConvention (parent is Class), parameters);
2705 // HACK because System.Reflection.Emit is lame
2707 ParameterInfo = new InternalParameters (parent, Parameters);
2709 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
2712 "Class `" +parent.Name+ "' already contains a definition with the " +
2713 "same return value and parameter types for constructor `" + Name
2724 public void Emit (TypeContainer parent)
2726 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2727 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2729 if (parent is Class && ((ModFlags & Modifiers.STATIC) == 0)){
2730 if (Initializer == null)
2731 Initializer = new ConstructorBaseInitializer (null, parent.Location);
2735 // Spec mandates that Initializers will not have
2739 if (!Initializer.Resolve (ec))
2741 ec.IsStatic = false;
2744 LabelParameters (ec, ParameterTypes (parent), ConstructorBuilder);
2747 // Classes can have base initializers and instance field initializers.
2749 if (parent is Class){
2750 if ((ModFlags & Modifiers.STATIC) == 0){
2751 parent.EmitFieldInitializers (ec);
2753 Initializer.Emit (ec);
2757 if ((ModFlags & Modifiers.STATIC) != 0)
2758 parent.EmitFieldInitializers (ec);
2760 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2762 ec.EmitTopBlock (Block, Location);
2767 // Fields and Events both generate FieldBuilders, we use this to share
2768 // their common bits. This is also used to flag usage of the field
2770 abstract public class FieldBase : MemberCore {
2771 public readonly string Type;
2772 public readonly Object Initializer;
2773 public readonly Attributes OptAttributes;
2774 public FieldBuilder FieldBuilder;
2775 public Status status;
2778 public enum Status : byte { ASSIGNED = 1, USED = 2 }
2781 // The constructor is only exposed to our children
2783 protected FieldBase (string type, int mod, int allowed_mod, string name,
2784 object init, Attributes attrs, Location loc)
2788 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
2790 OptAttributes = attrs;
2795 // The Field class is used to represents class/struct fields during parsing.
2797 public class Field : FieldBase {
2799 // Modifiers allowed in a class declaration
2801 const int AllowedModifiers =
2804 Modifiers.PROTECTED |
2805 Modifiers.INTERNAL |
2808 Modifiers.VOLATILE |
2812 public Field (string type, int mod, string name, Object expr_or_array_init,
2813 Attributes attrs, Location loc)
2814 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
2818 public override bool Define (TypeContainer parent)
2820 Type t = RootContext.LookupType (parent, Type, false, Location);
2825 if (!TypeContainer.AsAccessible (t, ModFlags))
2828 if (t.IsPointer && !UnsafeOK (parent))
2831 if (RootContext.WarningLevel > 1){
2832 Type ptype = parent.TypeBuilder.BaseType;
2834 // ptype is only null for System.Object while compiling corlib.
2838 mi = TypeContainer.FindMembers (
2839 ptype, MemberTypes.Method,
2840 BindingFlags.Public |
2841 BindingFlags.Static | BindingFlags.Instance,
2842 System.Type.FilterName, Name);
2846 if ((ModFlags & Modifiers.VOLATILE) != 0){
2848 if (TypeManager.IsEnumType (t))
2849 t = TypeManager.EnumToUnderlying (t);
2851 if (!((t == TypeManager.bool_type) ||
2852 (t == TypeManager.sbyte_type) ||
2853 (t == TypeManager.byte_type) ||
2854 (t == TypeManager.short_type) ||
2855 (t == TypeManager.ushort_type) ||
2856 (t == TypeManager.int32_type) ||
2857 (t == TypeManager.uint32_type) ||
2858 (t == TypeManager.char_type) ||
2859 (t == TypeManager.float_type))){
2861 677, Location, parent.MakeName (Name) +
2862 " A volatile field can not be of type `" +
2863 TypeManager.CSharpName (t) + "'");
2869 FieldBuilder = parent.TypeBuilder.DefineField (
2870 Name, t, Modifiers.FieldAttr (ModFlags));
2872 TypeManager.RegisterFieldBase (FieldBuilder, this);
2876 public void Emit (TypeContainer tc)
2878 EmitContext ec = new EmitContext (tc, Location, null,
2879 FieldBuilder.FieldType, ModFlags);
2881 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
2886 // `set' and `get' accessors are represented with an Accessor.
2888 public class Accessor {
2890 // Null if the accessor is empty, or a Block if not
2894 public Accessor (Block b)
2900 public class Property : MemberCore {
2901 public readonly string Type;
2902 public Accessor Get, Set;
2903 public PropertyBuilder PropertyBuilder;
2904 public Attributes OptAttributes;
2905 public MethodBuilder GetBuilder, SetBuilder;
2908 // The type, once we compute it.
2912 const int AllowedModifiers =
2915 Modifiers.PROTECTED |
2916 Modifiers.INTERNAL |
2920 Modifiers.OVERRIDE |
2921 Modifiers.ABSTRACT |
2926 public Property (string type, string name, int mod_flags,
2927 Accessor get_block, Accessor set_block,
2928 Attributes attrs, Location loc)
2932 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
2935 OptAttributes = attrs;
2939 // Checks our base implementation if any
2941 bool CheckBase (MethodAttributes flags, TypeContainer parent)
2944 // Find properties with the same name on the base class
2947 MemberInfo [] props;
2948 MemberInfo [] props_static = TypeManager.MemberLookup (
2950 parent.TypeBuilder.BaseType,
2951 MemberTypes.Property, BindingFlags.Public | BindingFlags.Static,
2954 MemberInfo [] props_instance = TypeManager.MemberLookup (
2956 parent.TypeBuilder.BaseType,
2957 MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance,
2961 // Find if we have anything
2963 if (props_static != null && props_static.Length > 0)
2964 props = props_static;
2965 else if (props_instance != null && props_instance.Length > 0)
2966 props = props_instance;
2971 // If we have something on the base.
2972 if (props != null && props.Length > 0){
2973 if (props.Length > 1)
2974 throw new Exception ("Should not happen");
2976 PropertyInfo pi = (PropertyInfo) props [0];
2978 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
2979 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
2981 MethodInfo reference = inherited_get == null ?
2982 inherited_set : inherited_get;
2984 if (reference != null)
2985 if (!CheckMethodAgainstBase (parent, flags, reference))
2989 if ((ModFlags & Modifiers.NEW) != 0)
2990 WarningNotHiding (parent);
2992 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2993 Report.Error (115, Location,
2994 parent.MakeName (Name) +
2995 " no suitable properties found to override");
3002 bool DefineMethod (TypeContainer parent, Type iface_type, string short_name,
3003 MethodAttributes flags, bool is_get)
3005 Type [] parameters = TypeManager.NoTypes;
3006 MethodInfo implementing;
3011 fn_type = PropertyType;
3012 name = "get_" + short_name;
3014 name = "set_" + short_name;
3015 parameters = new Type [1];
3016 parameters [0] = PropertyType;
3017 fn_type = TypeManager.void_type;
3020 implementing = parent.IsInterfaceMethod (
3021 iface_type, name, fn_type, parameters, false);
3024 // For implicit implementations, make sure we are public, for
3025 // explicit implementations, make sure we are private.
3027 if (implementing != null){
3029 // Setting null inside this block will trigger a more
3030 // verbose error reporting for missing interface implementations
3032 // The "candidate" function has been flagged already
3033 // but it wont get cleared
3035 if (iface_type == null){
3037 // We already catch different accessibility settings
3038 // so we just need to check that we are not private
3040 if ((ModFlags & Modifiers.PRIVATE) != 0)
3041 implementing = null;
3044 // Static is not allowed
3046 if ((ModFlags & Modifiers.STATIC) != 0)
3047 implementing = null;
3049 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
3051 106, Location, "`public' or `abstract' modifiers "+
3052 "are not allowed in explicit interface declarations"
3054 implementing = null;
3060 // If implementing is still valid, set flags
3062 if (implementing != null){
3064 // When implementing interface methods, set NewSlot.
3066 if (implementing.DeclaringType.IsInterface)
3067 flags |= MethodAttributes.NewSlot;
3070 MethodAttributes.Virtual |
3071 MethodAttributes.HideBySig;
3074 // clear the pending flag
3076 parent.IsInterfaceMethod (
3077 iface_type, name, fn_type, parameters, true);
3081 // If this is not an explicit interface implementation,
3082 // clear implementing, as it is only used for explicit
3083 // interface implementation
3085 if (Name.IndexOf (".") == -1)
3086 implementing = null;
3089 GetBuilder = parent.TypeBuilder.DefineMethod (
3090 name, flags, PropertyType, null);
3091 PropertyBuilder.SetGetMethod (GetBuilder);
3093 if (implementing != null)
3094 parent.TypeBuilder.DefineMethodOverride (
3095 GetBuilder, implementing);
3098 // HACK because System.Reflection.Emit is lame
3100 InternalParameters ip = new InternalParameters (
3101 parent, Parameters.GetEmptyReadOnlyParameters ());
3103 if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) {
3104 Report.Error (111, Location,
3105 "Class `" + parent.Name +
3106 "' already contains a definition with the " +
3107 "same return value and parameter types as the " +
3108 "'get' method of property `" + Name + "'");
3112 SetBuilder = parent.TypeBuilder.DefineMethod (
3113 name, flags, null, parameters);
3115 if (implementing != null)
3116 parent.TypeBuilder.DefineMethodOverride (
3117 SetBuilder, implementing);
3119 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3120 PropertyBuilder.SetSetMethod (SetBuilder);
3123 // HACK because System.Reflection.Emit is lame
3125 Parameter [] parms = new Parameter [1];
3126 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3127 InternalParameters ip = new InternalParameters (
3128 parent, new Parameters (parms, null, Location));
3130 if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) {
3133 "Class `" + parent.Name +
3134 "' already contains a definition with the " +
3135 "same return value and parameter types as the " +
3136 "'set' method of property `" + Name + "'");
3144 public override bool Define (TypeContainer parent)
3146 Type iface_type = null;
3149 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3152 MethodAttributes flags = Modifiers.MethodAttr (ModFlags);
3154 flags |= MethodAttributes.HideBySig |
3155 MethodAttributes.SpecialName;
3157 // Lookup Type, verify validity
3158 PropertyType = RootContext.LookupType (parent, Type, false, Location);
3159 if (PropertyType == null)
3162 // verify accessibility
3163 if (!TypeContainer.AsAccessible (PropertyType, ModFlags))
3166 if (PropertyType.IsPointer && !UnsafeOK (parent))
3169 if (!CheckBase (flags, parent))
3173 // Check for explicit interface implementation
3175 if (Name.IndexOf (".") != -1){
3176 int pos = Name.LastIndexOf (".");
3177 string iface = Name.Substring (0, pos);
3179 iface_type = RootContext.LookupType (parent, iface, false, Location);
3180 if (iface_type == null)
3183 short_name = Name.Substring (pos + 1);
3185 // Compute the full name that we need to export.
3186 Name = iface_type.FullName + "." + short_name;
3190 // FIXME - PropertyAttributes.HasDefault ?
3192 PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
3193 PropertyAttributes.SpecialName;
3195 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3196 Name, prop_attr, PropertyType, null);
3199 if (!DefineMethod (parent, iface_type, short_name, flags, true))
3203 if (!DefineMethod (parent, iface_type, short_name, flags, false))
3207 // HACK for the reasons exposed above
3209 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3212 "Class `" + parent.Name +
3213 "' already contains a definition for the property `" +
3221 public void Emit (TypeContainer tc)
3226 ec = new EmitContext (tc, Location, null, PropertyType, ModFlags);
3227 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3231 // abstract or extern properties have no bodies
3233 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3237 ig = GetBuilder.GetILGenerator ();
3238 ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags);
3240 ec.EmitTopBlock (Get.Block, Location);
3244 ig = SetBuilder.GetILGenerator ();
3245 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3247 ec.EmitTopBlock (Set.Block, Location);
3254 /// Gigantic workaround for lameness in SRE follows :
3255 /// This class derives from EventInfo and attempts to basically
3256 /// wrap around the EventBuilder so that FindMembers can quickly
3257 /// return this in it search for members
3259 public class MyEventBuilder : EventInfo {
3262 // We use this to "point" to our Builder which is
3263 // not really a MemberInfo
3265 EventBuilder MyBuilder;
3268 // We "catch" and wrap these methods
3270 MethodInfo raise, remove, add;
3272 EventAttributes attributes;
3273 Type declaring_type, reflected_type, event_type;
3276 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3278 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3280 // And now store the values in our own fields.
3282 declaring_type = type_builder;
3284 reflected_type = type_builder;
3286 attributes = event_attr;
3288 this.event_type = event_type;
3292 // Methods that you have to override. Note that you only need
3293 // to "implement" the variants that take the argument (those are
3294 // the "abstract" methods, the others (GetAddMethod()) are
3297 public override MethodInfo GetAddMethod (bool nonPublic)
3302 public override MethodInfo GetRemoveMethod (bool nonPublic)
3307 public override MethodInfo GetRaiseMethod (bool nonPublic)
3313 // These methods make "MyEventInfo" look like a Builder
3315 public void SetRaiseMethod (MethodBuilder raiseMethod)
3317 raise = raiseMethod;
3318 MyBuilder.SetRaiseMethod (raiseMethod);
3321 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3323 remove = removeMethod;
3324 MyBuilder.SetRemoveOnMethod (removeMethod);
3327 public void SetAddOnMethod (MethodBuilder addMethod)
3330 MyBuilder.SetAddOnMethod (addMethod);
3333 public void SetCustomAttribute (CustomAttributeBuilder cb)
3335 MyBuilder.SetCustomAttribute (cb);
3338 public override object [] GetCustomAttributes (bool inherit)
3340 // FIXME : There's nothing which can be seemingly done here because
3341 // we have no way of getting at the custom attribute objects of the
3346 public override object [] GetCustomAttributes (Type t, bool inherit)
3348 // FIXME : Same here !
3352 public override bool IsDefined (Type t, bool b)
3357 public override EventAttributes Attributes {
3363 public override string Name {
3369 public override Type DeclaringType {
3371 return declaring_type;
3375 public override Type ReflectedType {
3377 return reflected_type;
3381 public Type EventType {
3388 public class Event : FieldBase {
3389 const int AllowedModifiers =
3392 Modifiers.PROTECTED |
3393 Modifiers.INTERNAL |
3398 Modifiers.OVERRIDE |
3402 public readonly Block Add;
3403 public readonly Block Remove;
3404 public MyEventBuilder EventBuilder;
3407 MethodBuilder AddBuilder, RemoveBuilder;
3409 public Event (string type, string name, Object init, int mod, Block add_block,
3410 Block rem_block, Attributes attrs, Location loc)
3411 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
3417 public override bool Define (TypeContainer parent)
3419 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3422 MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
3423 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3425 EventType = RootContext.LookupType (parent, Type, false, Location);
3426 if (EventType == null)
3429 if (!TypeContainer.AsAccessible (EventType, ModFlags))
3432 if (EventType.IsPointer && !UnsafeOK (parent))
3435 if (!EventType.IsSubclassOf (TypeManager.delegate_type)) {
3436 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3437 "' : event must be of a delegate type");
3441 Type [] parameters = new Type [1];
3442 parameters [0] = EventType;
3444 EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType);
3446 if (Add == null && Remove == null){
3447 FieldBuilder = parent.TypeBuilder.DefineField (
3448 Name, EventType, FieldAttributes.Private);
3449 TypeManager.RegisterFieldBase (FieldBuilder, this);
3453 // Now define the accessors
3455 string add_name = "add_" + Name;
3457 AddBuilder = parent.TypeBuilder.DefineMethod (
3458 add_name, m_attr, null, parameters);
3459 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3460 EventBuilder.SetAddOnMethod (AddBuilder);
3461 parent.IsInterfaceMethod (null, add_name, null, parameters, true);
3464 // HACK because System.Reflection.Emit is lame
3466 Parameter [] parms = new Parameter [1];
3467 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3468 InternalParameters ip = new InternalParameters (
3469 parent, new Parameters (parms, null, Location));
3471 if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) {
3472 Report.Error (111, Location,
3473 "Class `" + parent.Name + "' already contains a definition with the " +
3474 "same return value and parameter types for the " +
3475 "'add' method of event `" + Name + "'");
3479 string remove_name = "remove_" + Name;
3480 RemoveBuilder = parent.TypeBuilder.DefineMethod (
3481 remove_name, m_attr, null, parameters);
3482 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3483 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3484 parent.IsInterfaceMethod (null, remove_name, null, parameters, true);
3487 // HACK because System.Reflection.Emit is lame
3490 if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) {
3491 Report.Error (111, Location,
3492 "Class `" + parent.Name + "' already contains a definition with the " +
3493 "same return value and parameter types for the " +
3494 "'remove' method of event `" + Name + "'");
3498 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3499 Report.Error (111, Location,
3500 "Class `" + parent.Name +
3501 "' already contains a definition for the event `" +
3509 void EmitDefaultMethod (EmitContext ec, bool is_add)
3511 ILGenerator ig = ec.ig;
3512 MethodInfo method = null;
3515 method = TypeManager.delegate_combine_delegate_delegate;
3517 method = TypeManager.delegate_remove_delegate_delegate;
3519 ig.Emit (OpCodes.Ldarg_0);
3520 ig.Emit (OpCodes.Ldarg_0);
3521 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3522 ig.Emit (OpCodes.Ldarg_1);
3523 ig.Emit (OpCodes.Call, method);
3524 ig.Emit (OpCodes.Castclass, EventType);
3525 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3526 ig.Emit (OpCodes.Ret);
3529 public void Emit (TypeContainer tc)
3534 ig = AddBuilder.GetILGenerator ();
3535 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3538 ec.EmitTopBlock (Add, Location);
3540 EmitDefaultMethod (ec, true);
3542 ig = RemoveBuilder.GetILGenerator ();
3543 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3546 ec.EmitTopBlock (Remove, Location);
3548 EmitDefaultMethod (ec, false);
3550 ec = new EmitContext (tc, Location, null, EventType, ModFlags);
3551 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3558 // FIXME: This does not handle:
3560 // int INTERFACENAME [ args ]
3564 // int this [ args ]
3566 public class Indexer : MemberCore {
3568 const int AllowedModifiers =
3571 Modifiers.PROTECTED |
3572 Modifiers.INTERNAL |
3576 Modifiers.OVERRIDE |
3581 public readonly string Type;
3582 public readonly string InterfaceType;
3583 public readonly Parameters FormalParameters;
3584 public readonly Accessor Get, Set;
3585 public Attributes OptAttributes;
3586 public MethodBuilder GetBuilder;
3587 public MethodBuilder SetBuilder;
3588 public PropertyBuilder PropertyBuilder;
3589 public Type IndexerType;
3590 public string IndexerName;
3593 public Indexer (string type, string int_type, int flags, Parameters parms,
3594 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
3599 InterfaceType = int_type;
3600 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
3601 FormalParameters = parms;
3604 OptAttributes = attrs;
3607 bool DefineMethod (TypeContainer parent, Type iface_type,
3608 Type ret_type, string name,
3609 Type [] parameters, MethodAttributes attr, bool is_get)
3611 MethodInfo implementing;
3612 bool is_implementation;
3614 implementing = parent.IsInterfaceMethod (
3615 iface_type, name, ret_type, parameters, false);
3617 is_implementation = implementing != null;
3620 // Setting null inside this block will trigger a more
3621 // verbose error reporting for missing interface implementations
3623 // The "candidate" function has been flagged already
3624 // but it wont get cleared
3626 if (implementing != null){
3627 if (iface_type == null){
3629 // We already catch different accessibility settings
3630 // so we just need to check that we are not private
3632 if ((ModFlags & Modifiers.PRIVATE) != 0)
3633 implementing = null;
3636 // Static is not allowed
3638 if ((ModFlags & Modifiers.STATIC) != 0)
3639 implementing = null;
3641 if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
3644 "`public' or `abstract' modifiers are not "+
3645 "allowed in explicit interface declarations"
3647 implementing = null;
3651 if (implementing != null){
3653 // When implementing interface methods, set NewSlot.
3655 if (implementing.DeclaringType.IsInterface)
3656 attr |= MethodAttributes.NewSlot;
3659 MethodAttributes.Virtual |
3660 MethodAttributes.HideBySig;
3663 // clear the pending flag
3665 parent.IsInterfaceMethod (
3666 iface_type, name, ret_type, parameters, true);
3670 // If this is not an explicit interface implementation,
3671 // clear implementing, as it is only used for explicit
3672 // interface implementation
3674 if (InterfaceType == null)
3675 implementing = null;
3678 string meth_name = "get_" + IndexerName;
3679 if (iface_type != null)
3680 meth_name = iface_type + ".get_" + IndexerName;
3682 GetBuilder = parent.TypeBuilder.DefineMethod (
3683 meth_name, attr, IndexerType, parameters);
3685 if (implementing != null)
3686 parent.TypeBuilder.DefineMethodOverride (
3687 GetBuilder, implementing);
3689 string meth_name = "set_" + IndexerName;
3691 if (iface_type != null)
3692 meth_name = iface_type + ".set_" + IndexerName;
3694 SetBuilder = parent.TypeBuilder.DefineMethod (
3695 meth_name, attr, null, parameters);
3696 if (implementing != null)
3697 parent.TypeBuilder.DefineMethodOverride (
3698 SetBuilder, implementing);
3701 return is_implementation;
3704 public override bool Define (TypeContainer parent)
3706 PropertyAttributes prop_attr =
3707 PropertyAttributes.RTSpecialName |
3708 PropertyAttributes.SpecialName;
3711 IndexerType = RootContext.LookupType (parent, Type, false, Location);
3712 Type [] parameters = FormalParameters.GetParameterInfo (parent);
3714 // Check if the return type and arguments were correct
3715 if (IndexerType == null || parameters == null)
3718 if (!parent.MethodModifiersValid (ModFlags, InterfaceType == null ?
3719 "this" : InterfaceType, Location))
3723 // verify accessibility and unsafe pointers
3725 if (!TypeContainer.AsAccessible (IndexerType, ModFlags))
3728 if (IndexerType.IsPointer && !UnsafeOK (parent))
3731 foreach (Type partype in parameters){
3732 if (!TypeContainer.AsAccessible (partype, ModFlags))
3734 if (partype.IsPointer && !UnsafeOK (parent))
3741 Type iface_type = null;
3743 if (InterfaceType != null){
3744 iface_type = RootContext.LookupType (parent, InterfaceType, false, Location);
3745 if (iface_type == null)
3749 ec = new EmitContext (parent, Location, null, IndexerType, ModFlags);
3751 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
3752 if (IndexerName == null)
3753 IndexerName = "Item";
3755 MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
3757 bool is_implementing = false;
3760 is_implementing = DefineMethod (
3761 parent, iface_type, IndexerType, "get_" + IndexerName,
3762 parameters, attr, true);
3763 InternalParameters pi = new InternalParameters (parent, FormalParameters);
3764 if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) {
3765 Report.Error (111, Location,
3766 "Class `" + parent.Name +
3767 "' already contains a definition with the " +
3768 "same return value and parameter types for the " +
3775 int top = parameters.Length;
3776 Type [] set_pars = new Type [top + 1];
3777 parameters.CopyTo (set_pars, 0);
3778 set_pars [top] = IndexerType;
3780 Parameter [] fixed_parms = FormalParameters.FixedParameters;
3782 if (fixed_parms == null){
3783 throw new Exception ("We currently do not support only array arguments in an indexer");
3784 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3785 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3787 // Here is the problem: the `value' parameter has
3788 // to come *after* the array parameter in the declaration
3790 // X (object [] x, Type value)
3793 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3794 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3798 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3801 fixed_parms.CopyTo (tmp, 0);
3802 tmp [fixed_parms.Length] = new Parameter (
3803 Type, "value", Parameter.Modifier.NONE, null);
3805 Parameters set_formal_params = new Parameters (tmp, null, Location);
3807 is_implementing = DefineMethod (
3808 parent, iface_type, TypeManager.void_type,
3809 "set_" + IndexerName, set_pars, attr, false);
3811 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3813 if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) {
3816 "Class `" + parent.Name + "' already contains a " +
3817 "definition with the " +
3818 "same return value and parameter types for the " +
3825 // Now name the parameters
3827 Parameter [] p = FormalParameters.FixedParameters;
3831 for (i = 0; i < p.Length; ++i) {
3833 GetBuilder.DefineParameter (
3834 i + 1, p [i].Attributes, p [i].Name);
3837 SetBuilder.DefineParameter (
3838 i + 1, p [i].Attributes, p [i].Name);
3842 SetBuilder.DefineParameter (
3843 i + 1, ParameterAttributes.None, "value");
3845 if (i != parameters.Length) {
3846 Parameter array_param = FormalParameters.ArrayParameter;
3847 SetBuilder.DefineParameter (i + 1, array_param.Attributes,
3854 // Only define the PropertyBuilder if we are not implementing
3855 // an interface property.
3857 if (!is_implementing){
3858 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3859 IndexerName, prop_attr, IndexerType, parameters);
3860 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
3862 if (GetBuilder != null)
3863 PropertyBuilder.SetGetMethod (GetBuilder);
3865 if (SetBuilder != null)
3866 PropertyBuilder.SetSetMethod (SetBuilder);
3872 public void Emit (TypeContainer tc)
3876 Attribute.ApplyAttributes (
3877 ec, PropertyBuilder, this, OptAttributes, Location);
3879 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3883 ig = GetBuilder.GetILGenerator ();
3884 ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags);
3886 ec.EmitTopBlock (Get.Block, Location);
3890 ig = SetBuilder.GetILGenerator ();
3891 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3893 ec.EmitTopBlock (Set.Block, Location);
3898 public class Operator : MemberCore {
3900 const int AllowedModifiers =
3906 const int RequiredModifiers =
3910 public enum OpType : byte {
3920 // Unary and Binary operators
3943 // Implicit and Explicit
3948 public readonly OpType OperatorType;
3949 public readonly string ReturnType;
3950 public readonly string FirstArgType;
3951 public readonly string FirstArgName;
3952 public readonly string SecondArgType;
3953 public readonly string SecondArgName;
3954 public readonly Block Block;
3955 public Attributes OptAttributes;
3956 public MethodBuilder OperatorMethodBuilder;
3958 public string MethodName;
3959 public Method OperatorMethod;
3961 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
3962 string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
3965 OperatorType = type;
3966 ReturnType = ret_type;
3967 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
3968 FirstArgType = arg1type;
3969 FirstArgName = arg1name;
3970 SecondArgType = arg2type;
3971 SecondArgName = arg2name;
3973 OptAttributes = attrs;
3976 string Prototype (TypeContainer parent)
3978 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
3979 SecondArgType + ")";
3982 public override bool Define (TypeContainer parent)
3985 MethodName = "op_" + OperatorType;
3987 if (SecondArgType != null)
3990 Parameter [] param_list = new Parameter [length];
3992 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
3995 "User defined operators `" +
3996 Prototype (parent) +
3997 "' must be declared static and public");
4001 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4002 Parameter.Modifier.NONE, null);
4003 if (SecondArgType != null)
4004 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4005 Parameter.Modifier.NONE, null);
4007 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
4008 new Parameters (param_list, null, Location),
4009 OptAttributes, Mono.CSharp.Location.Null);
4011 OperatorMethod.Define (parent);
4013 if (OperatorMethod.MethodBuilder == null)
4016 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4018 Type [] param_types = OperatorMethod.ParameterTypes (parent);
4019 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4020 Type return_type = OperatorMethod.GetReturnType (parent);
4021 Type first_arg_type = param_types [0];
4023 // Rules for conversion operators
4025 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4026 if (first_arg_type == return_type && first_arg_type == declaring_type){
4029 "User-defined conversion cannot take an object of the " +
4030 "enclosing type and convert to an object of the enclosing" +
4035 if (first_arg_type != declaring_type && return_type != declaring_type){
4038 "User-defined conversion must convert to or from the " +
4043 if (first_arg_type == TypeManager.object_type ||
4044 return_type == TypeManager.object_type){
4047 "User-defined conversion cannot convert to or from " +
4052 if (first_arg_type.IsInterface || return_type.IsInterface){
4055 "User-defined conversion cannot convert to or from an " +
4060 if (first_arg_type.IsSubclassOf (return_type) ||
4061 return_type.IsSubclassOf (first_arg_type)){
4064 "User-defined conversion cannot convert between types " +
4065 "that derive from each other");
4068 } else if (SecondArgType == null) {
4069 // Checks for Unary operators
4071 if (first_arg_type != declaring_type){
4074 "The parameter of a unary operator must be the " +
4079 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4080 if (return_type != declaring_type){
4083 "The parameter and return type for ++ and -- " +
4084 "must be the containing type");
4090 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4091 if (return_type != TypeManager.bool_type){
4094 "The return type of operator True or False " +
4101 // Checks for Binary operators
4103 if (first_arg_type != declaring_type &&
4104 param_types [1] != declaring_type){
4107 "One of the parameters of a binary operator must " +
4108 "be the containing type");
4116 public void Emit (TypeContainer parent)
4118 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
4119 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
4122 // abstract or extern methods have no bodies
4124 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4127 OperatorMethod.Block = Block;
4128 OperatorMethod.Emit (parent);
4133 // This is used to compare method signatures
4135 struct MethodSignature {
4137 public Type RetType;
4138 public Type [] Parameters;
4141 /// This delegate is used to extract methods which have the
4142 /// same signature as the argument
4144 public static MemberFilter method_signature_filter;
4147 /// This delegate is used to extract inheritable methods which
4148 /// have the same signature as the argument. By inheritable,
4149 /// this means that we have permissions to override the method
4150 /// from the current assembly and class
4152 public static MemberFilter inheritable_method_signature_filter;
4154 static MethodSignature ()
4156 method_signature_filter = new MemberFilter (MemberSignatureCompare);
4157 inheritable_method_signature_filter = new MemberFilter (
4158 InheritableMemberSignatureCompare);
4161 public MethodSignature (string name, Type ret_type, Type [] parameters)
4166 if (parameters == null)
4167 Parameters = TypeManager.NoTypes;
4169 Parameters = parameters;
4172 public override int GetHashCode ()
4174 return Name.GetHashCode ();
4177 public override bool Equals (Object o)
4179 MethodSignature other = (MethodSignature) o;
4181 if (other.Name != Name)
4184 if (other.RetType != RetType)
4187 if (Parameters == null){
4188 if (other.Parameters == null)
4193 if (other.Parameters == null)
4196 int c = Parameters.Length;
4197 if (other.Parameters.Length != c)
4200 for (int i = 0; i < c; i++)
4201 if (other.Parameters [i] != Parameters [i])
4207 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
4211 if (! (m is MethodInfo))
4214 MethodSignature sig = (MethodSignature) filter_criteria;
4216 if (m.Name != sig.Name)
4219 mi = (MethodInfo) m;
4222 // we use sig.RetType == null to mean `do not check the
4223 // method return value.
4225 if (sig.RetType != null)
4226 if (mi.ReturnType != sig.RetType)
4229 Type [] args = TypeManager.GetArgumentTypes (mi);
4230 Type [] sigp = sig.Parameters;
4232 if (args.Length != sigp.Length)
4235 for (int i = args.Length; i > 0; ){
4237 if (args [i] != sigp [i])
4244 // This filter should be used when we are requesting methods that
4245 // we want to override.
4247 // This makes a number of assumptions, for example
4248 // that the methods being extracted are of a parent
4249 // class (this means we know implicitly that we are
4250 // being called to find out about members by a derived
4253 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
4255 if (MemberSignatureCompare (m, filter_criteria)){
4256 MethodInfo mi = (MethodInfo) m;
4257 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
4259 // If only accessible to the current class.
4260 if (prot == MethodAttributes.Private)
4263 // If only accessible to the defining assembly or
4264 if (prot == MethodAttributes.FamANDAssem ||
4265 prot == MethodAttributes.Assembly){
4266 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
4272 // Anything else (FamOrAssembly and Public) is fine