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, 2002 Ximian, Inc (http://www.ximian.com)
13 using System.Collections;
14 using System.Reflection;
15 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 // Whether we have at least one non-static field
87 bool have_nonstatic_fields = false;
90 // This one is computed after we can distinguish interfaces
91 // from classes from the arraylist `type_bases'
93 string base_class_name;
97 // Attributes for this type
98 protected Attributes attributes;
100 // Information in the case we are an attribute type
102 public AttributeTargets Targets = AttributeTargets.All;
103 public bool AllowMultiple = false;
104 public bool Inherited;
107 // The indexer name for this class
109 public string IndexerName;
111 public TypeContainer (TypeContainer parent, string name, Location l)
112 : base (parent, name, l)
115 types = new ArrayList ();
122 base_class_name = null;
124 //Console.WriteLine ("New class " + name + " inside " + n);
127 public AdditionResult AddConstant (Const constant)
130 string name = constant.Name;
132 if ((res = IsValid (name)) != AdditionResult.Success)
135 if (constants == null)
136 constants = new ArrayList ();
138 constants.Add (constant);
139 DefineName (name, constant);
141 return AdditionResult.Success;
144 public AdditionResult AddEnum (Mono.CSharp.Enum e)
147 string name = e.Name;
149 if ((res = IsValid (name)) != AdditionResult.Success)
153 enums = new ArrayList ();
156 DefineName (name, e);
158 return AdditionResult.Success;
161 public AdditionResult AddClass (Class c)
164 string name = c.Name;
167 if ((res = IsValid (name)) != AdditionResult.Success)
170 DefineName (name, c);
173 return AdditionResult.Success;
176 public AdditionResult AddStruct (Struct s)
179 string name = s.Name;
181 if ((res = IsValid (name)) != AdditionResult.Success)
184 DefineName (name, s);
187 return AdditionResult.Success;
190 public AdditionResult AddDelegate (Delegate d)
193 string name = d.Name;
195 if ((res = IsValid (name)) != AdditionResult.Success)
198 if (delegates == null)
199 delegates = new ArrayList ();
201 DefineName (name, d);
204 return AdditionResult.Success;
207 public AdditionResult AddMethod (Method method)
209 string name = method.Name;
210 Object value = defined_names [name];
212 if (value != null && (!(value is Method)))
213 return AdditionResult.NameExists;
216 methods = new ArrayList ();
218 methods.Add (method);
220 DefineName (name, method);
222 return AdditionResult.Success;
225 public AdditionResult AddConstructor (Constructor c)
227 if (c.Name != Basename)
228 return AdditionResult.NotAConstructor;
230 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
233 have_static_constructor = true;
234 if (default_static_constructor != null){
235 Console.WriteLine ("I have a static constructor already");
236 Console.WriteLine (" " + default_static_constructor);
237 return AdditionResult.MethodExists;
240 default_static_constructor = c;
243 if (default_constructor != null)
244 return AdditionResult.MethodExists;
245 default_constructor = c;
248 if (instance_constructors == null)
249 instance_constructors = new ArrayList ();
251 instance_constructors.Add (c);
254 return AdditionResult.Success;
257 public AdditionResult AddInterface (Interface iface)
260 string name = iface.Name;
262 if ((res = IsValid (name)) != AdditionResult.Success)
265 if (interfaces == null)
266 interfaces = new ArrayList ();
267 interfaces.Add (iface);
268 DefineName (name, iface);
270 return AdditionResult.Success;
273 public AdditionResult AddField (Field field)
276 string name = field.Name;
278 if ((res = IsValid (name)) != AdditionResult.Success)
282 fields = new ArrayList ();
286 if (field.Initializer != null){
287 if ((field.ModFlags & Modifiers.STATIC) != 0){
288 if (initialized_static_fields == null)
289 initialized_static_fields = new ArrayList ();
291 initialized_static_fields.Add (field);
294 // We have not seen a static constructor,
295 // but we will provide static initialization of fields
297 have_static_constructor = true;
299 if (initialized_fields == null)
300 initialized_fields = new ArrayList ();
302 initialized_fields.Add (field);
306 if ((field.ModFlags & Modifiers.STATIC) == 0)
307 have_nonstatic_fields = true;
309 DefineName (name, field);
310 return AdditionResult.Success;
313 public AdditionResult AddProperty (Property prop)
316 string name = prop.Name;
318 if ((res = IsValid (name)) != AdditionResult.Success)
321 if (properties == null)
322 properties = new ArrayList ();
324 properties.Add (prop);
325 DefineName (name, prop);
327 return AdditionResult.Success;
330 public AdditionResult AddEvent (Event e)
333 string name = e.Name;
335 if ((res = IsValid (name)) != AdditionResult.Success)
339 events = new ArrayList ();
342 DefineName (name, e);
344 return AdditionResult.Success;
347 public AdditionResult AddIndexer (Indexer i)
349 if (indexers == null)
350 indexers = new ArrayList ();
354 return AdditionResult.Success;
357 public AdditionResult AddOperator (Operator op)
359 if (operators == null)
360 operators = new ArrayList ();
364 return AdditionResult.Success;
367 public void RegisterOrder (Interface iface)
369 if (interface_order == null)
370 interface_order = new ArrayList ();
372 interface_order.Add (iface);
375 public ArrayList Types {
381 public ArrayList Methods {
387 public ArrayList Constants {
393 public ArrayList Interfaces {
401 return base_class_name;
405 public ArrayList Bases {
415 public ArrayList Fields {
421 public ArrayList InstanceConstructors {
423 return instance_constructors;
427 public ArrayList Properties {
433 public ArrayList Events {
439 public ArrayList Enums {
445 public ArrayList Indexers {
451 public ArrayList Operators {
457 public ArrayList Delegates {
463 public Attributes OptAttributes {
469 public bool HaveStaticConstructor {
471 return have_static_constructor;
475 public virtual TypeAttributes TypeAttr {
477 return Modifiers.TypeAttr (ModFlags, this);
482 // Emits the instance field initializers
484 public bool EmitFieldInitializers (EmitContext ec)
487 ILGenerator ig = ec.ig;
488 Expression instance_expr;
491 fields = initialized_static_fields;
492 instance_expr = null;
494 fields = initialized_fields;
495 instance_expr = new This (Location.Null).Resolve (ec);
501 foreach (Field f in fields){
502 Object init = f.Initializer;
505 if (init is Expression)
506 e = (Expression) init;
508 string base_type = f.Type.Substring (0, f.Type.IndexOf ("["));
509 string rank = f.Type.Substring (f.Type.IndexOf ("["));
510 e = new ArrayCreation (base_type, rank, (ArrayList)init, f.Location);
513 Location l = f.Location;
514 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
515 fe.InstanceExpression = instance_expr;
516 Expression a = new Assign (fe, e, l);
522 if (a is ExpressionStatement)
523 ((ExpressionStatement) a).EmitStatement (ec);
525 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
533 // Defines the default constructors
535 void DefineDefaultConstructor (bool is_static)
540 c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
541 new ConstructorBaseInitializer (null, new Location (-1)),
545 mods = Modifiers.STATIC;
551 c.Block = new Block (null);
555 public void ReportStructInitializedInstanceError ()
557 string n = TypeBuilder.FullName;
559 foreach (Field f in initialized_fields){
562 "`" + n + "." + f.Name + "': can not have " +
563 "instance field initializers in structs");
568 /// The pending methods that need to be implemented (interfaces or abstract methods)
570 public PendingImplementation Pending;
573 /// This function computes the Base class and also the
574 /// list of interfaces that the class or struct @c implements.
576 /// The return value is an array (might be null) of
577 /// interfaces implemented (as Types).
579 /// The @parent argument is set to the parent object or null
580 /// if this is `System.Object'.
582 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
584 ArrayList bases = Bases;
593 parent = TypeManager.value_type;
597 if (RootContext.StdLib)
598 parent = TypeManager.object_type;
599 else if (Name != "System.Object")
600 parent = TypeManager.object_type;
603 // If we are compiling our runtime,
604 // and we are defining ValueType, then our
605 // parent is `System.Object'.
607 if (!RootContext.StdLib && Name == "System.ValueType")
608 parent = TypeManager.object_type;
615 // Bases should be null if there are no bases at all
620 string name = (string) bases [0];
621 Type first = FindType (name);
632 parent = TypeManager.object_type;
640 Type [] ifaces = new Type [count-start];
642 for (i = start, j = 0; i < count; i++, j++){
643 string name = (string) bases [i];
644 Type t = FindType (name);
651 if (is_class == false && !t.IsInterface){
652 Report.Error (527, "In Struct `" + Name + "', type `"+
653 name +"' is not an interface");
662 detail = " (a class can not inherit from a struct/enum)";
664 Report.Error (509, "class `"+ Name +
665 "': Cannot inherit from sealed class `"+
666 bases [i]+"'"+detail);
673 Report.Error (527, "In Class `" + Name + "', type `"+
674 name+"' is not an interface");
680 for (int x = 0; x < j; x++) {
681 if (t == ifaces [x]) {
682 Report.Error (528, "`" + name + "' is already listed in interface list");
691 return TypeManager.ExpandInterfaces (ifaces);
695 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
697 public override TypeBuilder DefineType ()
704 if (TypeBuilder != null)
717 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
719 ifaces = GetClassBases (is_class, out parent, out error);
724 if (is_class && parent != null){
725 if (parent == TypeManager.enum_type ||
726 (parent == TypeManager.value_type && RootContext.StdLib) ||
727 parent == TypeManager.delegate_type ||
728 parent == TypeManager.array_type){
730 644, Location, "`" + Name + "' cannot inherit from " +
731 "special class `" + TypeManager.CSharpName (parent) + "'");
736 if (!is_class && TypeManager.value_type == null)
737 throw new Exception ();
739 TypeAttributes type_attributes = TypeAttr;
741 // if (parent_builder is ModuleBuilder) {
743 ModuleBuilder builder = CodeGen.ModuleBuilder;
746 // Structs with no fields need to have a ".size 1"
750 if (!is_class && !have_nonstatic_fields)
751 TypeBuilder = builder.DefineType (Name,
754 PackingSize.Unspecified, 1);
757 // classes or structs with fields
759 TypeBuilder = builder.DefineType (Name,
764 TypeBuilder builder = Parent.TypeBuilder;
767 // Structs with no fields need to have a ".size 1"
770 if (!is_class && !have_nonstatic_fields)
771 TypeBuilder = builder.DefineNestedType (Basename,
774 PackingSize.Unspecified);
777 // classes or structs with fields
779 TypeBuilder = builder.DefineNestedType (Basename,
787 // Finish the setup for the EmitContext
789 ec.ContainerType = TypeBuilder;
791 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
793 if (parent == TypeManager.attribute_type ||
794 parent.IsSubclassOf (TypeManager.attribute_type)) {
795 RootContext.RegisterAttribute (this);
796 TypeManager.RegisterAttrType (TypeBuilder, this);
798 RootContext.RegisterOrder (this);
800 if (Interfaces != null) {
801 foreach (Interface iface in Interfaces)
806 foreach (TypeContainer tc in Types)
810 if (Delegates != null) {
811 foreach (Delegate d in Delegates)
816 foreach (Enum en in Enums)
826 /// Defines the MemberCore objects that are in the `list' Arraylist
828 /// The `defined_names' array contains a list of members defined in
831 static ArrayList remove_list = new ArrayList ();
832 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
836 remove_list.Clear ();
838 foreach (MemberCore mc in list){
839 if (!mc.Define (this)){
840 remove_list.Add (mc);
844 if (defined_names == null)
847 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
849 if (RootContext.WarningLevel >= 4){
850 if ((mc.ModFlags & Modifiers.NEW) != 0)
851 Warning_KewywordNewNotRequired (mc.Location, mc);
856 MemberInfo match = defined_names [idx];
858 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
862 // If we are both methods, let the method resolution emit warnings
864 if (match is MethodBase && mc is MethodCore)
867 if ((mc.ModFlags & Modifiers.NEW) == 0)
868 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
871 foreach (object o in remove_list)
874 remove_list.Clear ();
878 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
879 // class is consisten. Either it is `Item' or it is the name defined by all the
880 // indexers with the `IndexerName' attribute.
882 // Turns out that the IndexerNameAttribute is applied to each indexer,
883 // but it is never emitted, instead a DefaultName attribute is attached
886 void DefineIndexers ()
888 string class_indexer_name = null;
890 foreach (Indexer i in Indexers){
895 name = i.IndexerName;
896 if (class_indexer_name == null){
897 class_indexer_name = name;
901 if (name == class_indexer_name)
905 668, "Two indexers have different names, " +
906 " you should use the same name for all your indexers");
908 if (class_indexer_name == null)
909 class_indexer_name = "Item";
910 IndexerName = class_indexer_name;
914 /// Populates our TypeBuilder with fields and methods
916 public override bool Define (TypeContainer parent)
918 MemberInfo [] defined_names = null;
920 if (RootContext.WarningLevel > 1){
924 // This code throws an exception in the comparer
925 // I guess the string is not an object?
927 ptype = TypeBuilder.BaseType;
929 defined_names = FindMembers (
930 ptype, MemberTypes.All & ~MemberTypes.Constructor,
931 BindingFlags.Public | BindingFlags.Instance |
932 BindingFlags.Static, null, null);
934 Array.Sort (defined_names, mif_compare);
938 if (constants != null)
939 DefineMembers (constants, defined_names);
942 DefineMembers (fields, defined_names);
945 if (instance_constructors == null){
946 if (default_constructor == null)
947 DefineDefaultConstructor (false);
950 if (initialized_static_fields != null &&
951 default_static_constructor == null)
952 DefineDefaultConstructor (true);
957 // Structs can not have initialized instance
960 if (initialized_static_fields != null &&
961 default_static_constructor == null)
962 DefineDefaultConstructor (true);
964 if (initialized_fields != null)
965 ReportStructInitializedInstanceError ();
968 Pending = PendingImplementation.GetPendingImplementations (this);
971 // Constructors are not in the defined_names array
973 if (instance_constructors != null)
974 DefineMembers (instance_constructors, null);
976 if (default_static_constructor != null)
977 default_static_constructor.Define (this);
980 DefineMembers (methods, defined_names);
982 if (properties != null)
983 DefineMembers (properties, defined_names);
986 DefineMembers (events, defined_names);
988 if (indexers != null) {
991 IndexerName = "Item";
993 if (operators != null)
994 DefineMembers (operators, null);
997 DefineMembers (enums, defined_names);
999 if (delegates != null)
1000 DefineMembers (delegates, defined_names);
1006 /// Looks up the alias for the name
1008 public string LookupAlias (string name)
1010 if (Namespace != null)
1011 return Namespace.LookupAlias (name);
1017 /// This function is based by a delegate to the FindMembers routine
1019 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1025 /// This filter is used by FindMembers, and we just keep
1026 /// a global for the filter to `AlwaysAccept'
1028 static MemberFilter accepting_filter;
1032 /// A member comparission method based on name only
1034 static IComparer mif_compare;
1036 static TypeContainer ()
1038 accepting_filter = new MemberFilter (AlwaysAccept);
1039 mif_compare = new MemberInfoCompare ();
1043 /// This method returns the members of this type just like Type.FindMembers would
1044 /// Only, we need to use this for types which are _being_ defined because MS'
1045 /// implementation can't take care of that.
1048 // FIXME: return an empty static array instead of null, that cleans up
1049 // some code and is consistent with some coding conventions I just found
1053 // Notice that in various cases we check if our field is non-null,
1054 // something that would normally mean that there was a bug elsewhere.
1056 // The problem happens while we are defining p-invoke methods, as those
1057 // will trigger a FindMembers, but this happens before things are defined
1059 // Since the whole process is a no-op, it is fine to check for null here.
1061 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1062 MemberFilter filter, object criteria)
1064 ArrayList members = new ArrayList ();
1065 bool priv = (bf & BindingFlags.NonPublic) != 0;
1068 filter = accepting_filter;
1070 if ((mt & MemberTypes.Field) != 0) {
1071 if (fields != null) {
1072 foreach (Field f in fields) {
1073 if ((f.ModFlags & Modifiers.PRIVATE) != 0)
1077 FieldBuilder fb = f.FieldBuilder;
1078 if (fb != null && filter (fb, criteria) == true)
1083 if (constants != null) {
1084 foreach (Const con in constants) {
1085 if ((con.ModFlags & Modifiers.PRIVATE) != 0)
1089 FieldBuilder fb = con.FieldBuilder;
1090 if (fb != null && filter (fb, criteria) == true)
1096 if ((mt & MemberTypes.Method) != 0) {
1097 if (methods != null) {
1098 foreach (Method m in methods) {
1099 if ((m.ModFlags & Modifiers.PRIVATE) != 0)
1103 MethodBuilder mb = m.MethodBuilder;
1105 if (mb != null && filter (mb, criteria) == true)
1110 if (operators != null){
1111 foreach (Operator o in operators) {
1112 if ((o.ModFlags & Modifiers.PRIVATE) != 0)
1116 MethodBuilder ob = o.OperatorMethodBuilder;
1117 if (ob != null && filter (ob, criteria) == true)
1122 if (properties != null){
1123 foreach (Property p in properties){
1124 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1131 if (b != null && filter (b, criteria) == true)
1135 if (b != null && filter (b, criteria) == true)
1141 if ((mt & MemberTypes.Event) != 0) {
1143 foreach (Event e in events) {
1144 if ((e.ModFlags & Modifiers.PRIVATE) != 0)
1148 MemberInfo eb = e.EventBuilder;
1149 if (eb != null && filter (eb, criteria) == true)
1150 members.Add (e.EventBuilder);
1154 if ((mt & MemberTypes.Property) != 0){
1155 if (properties != null)
1156 foreach (Property p in properties) {
1157 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1161 MemberInfo pb = p.PropertyBuilder;
1162 if (pb != null && filter (pb, criteria) == true) {
1163 members.Add (p.PropertyBuilder);
1167 if (indexers != null)
1168 foreach (Indexer ix in indexers) {
1169 if ((ix.ModFlags & Modifiers.PRIVATE) != 0)
1173 MemberInfo ib = ix.PropertyBuilder;
1174 if (ib != null && filter (ib, criteria) == true) {
1175 members.Add (ix.PropertyBuilder);
1180 if ((mt & MemberTypes.NestedType) != 0) {
1183 foreach (TypeContainer t in Types)
1184 if (filter (t.TypeBuilder, criteria) == true)
1185 members.Add (t.TypeBuilder);
1188 foreach (Enum en in Enums)
1189 if (filter (en.TypeBuilder, criteria) == true)
1190 members.Add (en.TypeBuilder);
1194 if ((mt & MemberTypes.Constructor) != 0){
1195 if (instance_constructors != null){
1196 foreach (Constructor c in instance_constructors){
1197 ConstructorBuilder cb = c.ConstructorBuilder;
1200 if (filter (cb, criteria) == true)
1205 if (default_static_constructor != null){
1206 ConstructorBuilder cb =
1207 default_static_constructor.ConstructorBuilder;
1209 if (filter (cb, criteria) == true)
1215 // Lookup members in parent if requested.
1217 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1220 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1222 members.AddRange (mi);
1225 int count = members.Count;
1227 MemberInfo [] mi = new MemberInfo [count];
1228 members.CopyTo (mi);
1235 public MemberInfo GetFieldFromEvent (EventExpr event_expr)
1240 EventInfo ei = event_expr.EventInfo;
1242 foreach (Event e in events) {
1244 if (e.FieldBuilder == null)
1247 if (Type.FilterName (e.FieldBuilder, ei.Name))
1248 return e.FieldBuilder;
1254 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1255 MemberFilter filter, object criteria)
1257 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1260 return tc.FindMembers (mt, bf, filter, criteria);
1262 return t.FindMembers (mt, bf, filter, criteria);
1266 // FindMethods will look for methods not only in the type `t', but in
1267 // any interfaces implemented by the type.
1269 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1270 MemberFilter filter, object criteria)
1276 /// Emits the values for the constants
1278 public void EmitConstants ()
1280 if (constants != null)
1281 foreach (Const con in constants)
1282 con.EmitConstant (this);
1287 /// Emits the code, this step is performed after all
1288 /// the types, enumerations, constructors
1292 if (instance_constructors != null)
1293 foreach (Constructor c in instance_constructors)
1296 if (default_static_constructor != null)
1297 default_static_constructor.Emit (this);
1299 if (methods != null)
1300 foreach (Method m in methods)
1303 if (operators != null)
1304 foreach (Operator o in operators)
1307 if (properties != null)
1308 foreach (Property p in properties)
1311 if (indexers != null){
1312 foreach (Indexer ix in indexers)
1315 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1316 this, IndexerName, ModFlags, Location);
1317 TypeBuilder.SetCustomAttribute (cb);
1321 foreach (Field f in fields)
1324 if (events != null){
1325 foreach (Event e in Events)
1329 if (Pending != null)
1330 if (Pending.VerifyPendingMethods ())
1333 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1336 // Check for internal or private fields that were never assigned
1338 if (fields != null && RootContext.WarningLevel >= 3) {
1339 foreach (Field f in fields) {
1340 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1345 169, f.Location, "Private field " +
1346 MakeName (f.Name) + " is never used");
1351 // Only report 649 on level 4
1353 if (RootContext.WarningLevel < 4)
1356 if ((f.status & Field.Status.ASSIGNED) != 0)
1361 "Field " + MakeName (f.Name) + " is never assigned " +
1362 " to and will always have its default value");
1366 // if (types != null)
1367 // foreach (TypeContainer tc in types)
1371 public override void CloseType ()
1376 TypeBuilder.CreateType ();
1378 } catch (TypeLoadException){
1380 // This is fine, the code still created the type
1382 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1383 // Console.WriteLine (e.Message);
1385 Console.WriteLine ("In type: " + Name);
1390 foreach (Enum en in Enums)
1393 if (interface_order != null){
1394 foreach (Interface iface in interface_order)
1399 foreach (TypeContainer tc in Types)
1403 foreach (TypeContainer tc in Types)
1404 if (!(tc is Struct))
1408 if (Delegates != null)
1409 foreach (Delegate d in Delegates)
1413 public string MakeName (string n)
1415 return "`" + Name + "." + n + "'";
1418 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1421 108, l, "The keyword new is required on " +
1422 MakeName (mi.Name) + " because it hides `" +
1423 mi.ReflectedType.Name + "." + mi.Name + "'");
1426 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1429 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1430 "inherited member, the keyword new is not required");
1433 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1439 // Performs the validation on a Method's modifiers (properties have
1440 // the same properties).
1442 public bool MethodModifiersValid (int flags, string n, Location loc)
1444 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1445 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1447 string name = MakeName (n);
1450 // At most one of static, virtual or override
1452 if ((flags & Modifiers.STATIC) != 0){
1453 if ((flags & vao) != 0){
1455 112, loc, "static method " + name + "can not be marked " +
1456 "as virtual, abstract or override");
1461 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1464 " marked as override cannot be marked as new or virtual");
1469 // If the declaration includes the abstract modifier, then the
1470 // declaration does not include static, virtual or extern
1472 if ((flags & Modifiers.ABSTRACT) != 0){
1473 if ((flags & Modifiers.EXTERN) != 0){
1475 180, loc, name + " can not be both abstract and extern");
1479 if ((flags & Modifiers.VIRTUAL) != 0){
1481 503, loc, name + " can not be both abstract and virtual");
1485 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1488 " is abstract but its container class is not");
1494 if ((flags & Modifiers.PRIVATE) != 0){
1495 if ((flags & vao) != 0){
1498 " virtual or abstract members can not be private");
1503 if ((flags & Modifiers.SEALED) != 0){
1504 if ((flags & Modifiers.OVERRIDE) == 0){
1507 " cannot be sealed because it is not an override");
1516 // Returns true if `type' is as accessible as the flags `flags'
1517 // given for this member
1519 static public bool AsAccessible (Type type, int flags)
1524 Hashtable builder_and_args;
1526 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1528 if (builder_and_args == null)
1529 builder_and_args = new Hashtable ();
1534 public class Class : TypeContainer {
1536 // Modifiers allowed in a class declaration
1538 public const int AllowedModifiers =
1541 Modifiers.PROTECTED |
1542 Modifiers.INTERNAL |
1544 Modifiers.ABSTRACT |
1548 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1549 : base (parent, name, l)
1553 if (parent.Parent == null)
1554 accmods = Modifiers.INTERNAL;
1556 accmods = Modifiers.PRIVATE;
1558 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1559 this.attributes = attrs;
1563 // FIXME: How do we deal with the user specifying a different
1566 public override TypeAttributes TypeAttr {
1568 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1573 public class Struct : TypeContainer {
1575 // Modifiers allowed in a struct declaration
1577 public const int AllowedModifiers =
1580 Modifiers.PROTECTED |
1581 Modifiers.INTERNAL |
1585 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1586 : base (parent, name, l)
1590 if (parent.Parent == null)
1591 accmods = Modifiers.INTERNAL;
1593 accmods = Modifiers.PRIVATE;
1595 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1597 this.ModFlags |= Modifiers.SEALED;
1598 this.attributes = attrs;
1603 // FIXME: Allow the user to specify a different set of attributes
1604 // in some cases (Sealed for example is mandatory for a class,
1605 // but what SequentialLayout can be changed
1607 public override TypeAttributes TypeAttr {
1609 return base.TypeAttr |
1610 TypeAttributes.SequentialLayout |
1611 TypeAttributes.Sealed |
1612 TypeAttributes.BeforeFieldInit;
1617 public abstract class MethodCore : MemberCore {
1618 public readonly Parameters Parameters;
1622 // Parameters, cached for semantic analysis.
1624 InternalParameters parameter_info;
1626 public MethodCore (string name, Parameters parameters, Location l)
1630 Parameters = parameters;
1634 // Returns the System.Type array for the parameters of this method
1636 Type [] parameter_types;
1637 public Type [] ParameterTypes (TypeContainer parent)
1639 if (Parameters == null)
1640 return TypeManager.NoTypes;
1642 if (parameter_types == null)
1643 parameter_types = Parameters.GetParameterInfo (parent);
1645 return parameter_types;
1648 public InternalParameters ParameterInfo
1651 return parameter_info;
1655 parameter_info = value;
1659 public Block Block {
1669 public CallingConventions GetCallingConvention (bool is_class)
1671 CallingConventions cc = 0;
1673 cc = Parameters.GetCallingConvention ();
1676 if ((ModFlags & Modifiers.STATIC) == 0)
1677 cc |= CallingConventions.HasThis;
1679 // FIXME: How is `ExplicitThis' used in C#?
1684 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
1687 // Define each type attribute (in/out/ref) and
1688 // the argument names.
1690 Parameter [] p = Parameters.FixedParameters;
1693 MethodBuilder mb = null;
1694 ConstructorBuilder cb = null;
1696 if (builder is MethodBuilder)
1697 mb = (MethodBuilder) builder;
1699 cb = (ConstructorBuilder) builder;
1702 for (i = 0; i < p.Length; i++) {
1703 ParameterBuilder pb;
1706 pb = cb.DefineParameter (
1707 i + 1, p [i].Attributes, p [i].Name);
1709 pb = mb.DefineParameter (
1710 i + 1, p [i].Attributes, p [i].Name);
1712 Attributes attr = p [i].OptAttributes;
1714 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
1718 if (Parameters.ArrayParameter != null){
1719 ParameterBuilder pb;
1720 Parameter array_param = Parameters.ArrayParameter;
1723 pb = cb.DefineParameter (
1724 i + 1, array_param.Attributes,
1727 pb = mb.DefineParameter (
1728 i + 1, array_param.Attributes,
1731 CustomAttributeBuilder a = new CustomAttributeBuilder (
1732 TypeManager.cons_param_array_attribute, new object [0]);
1734 pb.SetCustomAttribute (a);
1739 public class Method : MethodCore {
1740 public readonly string ReturnType;
1741 public MethodBuilder MethodBuilder;
1742 public readonly Attributes OptAttributes;
1744 MethodAttributes flags;
1747 /// Modifiers allowed in a class declaration
1749 const int AllowedModifiers =
1752 Modifiers.PROTECTED |
1753 Modifiers.INTERNAL |
1758 Modifiers.OVERRIDE |
1759 Modifiers.ABSTRACT |
1764 // return_type can be "null" for VOID values.
1766 public Method (string return_type, int mod, string name, Parameters parameters,
1767 Attributes attrs, Location l)
1768 : base (name, parameters, l)
1770 ReturnType = return_type;
1771 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
1772 OptAttributes = attrs;
1776 // Returns the `System.Type' for the ReturnType of this
1777 // function. Provides a nice cache. (used between semantic analysis
1778 // and actual code generation
1780 Type type_return_type;
1782 public Type GetReturnType (TypeContainer parent)
1784 if (type_return_type == null)
1785 type_return_type = RootContext.LookupType (
1786 parent, ReturnType, false, Location);
1788 return type_return_type;
1791 void DuplicateEntryPoint (MethodInfo b, Location location)
1795 "Program `" + CodeGen.FileName +
1796 "' has more than one entry point defined: `" +
1797 TypeManager.CSharpSignature(b) + "'");
1800 void Report28 (MethodInfo b)
1802 if (RootContext.WarningLevel < 4)
1807 "`" + TypeManager.CSharpSignature(b) +
1808 "' has the wrong signature to be an entry point");
1811 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
1813 if (b.ReturnType != TypeManager.void_type &&
1814 b.ReturnType != TypeManager.int32_type)
1817 if (pinfo.Count == 0)
1820 if (pinfo.Count > 1)
1823 Type t = pinfo.ParameterType(0);
1825 (t.GetArrayRank() == 1) &&
1826 (t.GetElementType() == TypeManager.string_type) &&
1827 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
1836 public override bool Define (TypeContainer parent)
1838 Type ret_type = GetReturnType (parent);
1839 Type [] parameters = ParameterTypes (parent);
1841 MethodInfo implementing = null;
1842 Type iface_type = null;
1843 string iface = "", short_name;
1844 bool explicit_impl = false;
1846 // Check if the return type and arguments were correct
1847 if (ret_type == null || parameters == null)
1850 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
1853 flags = Modifiers.MethodAttr (ModFlags);
1856 // verify accessibility
1858 if (!TypeContainer.AsAccessible (ret_type, ModFlags))
1861 if (ret_type.IsPointer && !UnsafeOK (parent))
1864 foreach (Type partype in parameters){
1865 if (!TypeContainer.AsAccessible (partype, ModFlags))
1867 if (partype.IsPointer && !UnsafeOK (parent))
1875 // Verify if the parent has a type with the same name, and then
1876 // check whether we have to create a new slot for it or not.
1878 Type ptype = parent.TypeBuilder.BaseType;
1880 // ptype is only null for System.Object while compiling corlib.
1882 MethodSignature ms = new MethodSignature (Name, null, parameters);
1883 MemberInfo [] mi, mi_static, mi_instance;
1885 mi_static = TypeContainer.FindMembers (
1886 ptype, MemberTypes.Method,
1887 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
1888 MethodSignature.inheritable_method_signature_filter, ms);
1890 mi_instance = TypeContainer.FindMembers (
1891 ptype, MemberTypes.Method,
1892 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
1893 MethodSignature.inheritable_method_signature_filter,
1896 if (mi_instance != null && mi_instance.Length > 0){
1898 } else if (mi_static != null && mi_static.Length > 0)
1903 if (mi != null && mi.Length > 0){
1904 if (!CheckMethodAgainstBase (parent, flags, (MethodInfo) mi [0])){
1908 if ((ModFlags & Modifiers.NEW) != 0)
1909 WarningNotHiding (parent);
1911 if ((ModFlags & Modifiers.OVERRIDE) != 0){
1912 Report.Error (115, Location,
1913 parent.MakeName (Name) +
1914 " no suitable methods found to override");
1917 } else if ((ModFlags & Modifiers.NEW) != 0)
1918 WarningNotHiding (parent);
1921 // If we implement an interface, extract the interface name.
1924 if (Name.IndexOf (".") != -1){
1925 int pos = Name.LastIndexOf (".");
1926 iface = Name.Substring (0, pos);
1928 iface_type = RootContext.LookupType (parent, iface, false, Location);
1929 short_name = Name.Substring (pos + 1);
1931 if (iface_type == null)
1934 // Compute the full name that we need to export
1935 Name = iface_type.FullName + "." + short_name;
1936 explicit_impl = true;
1941 // Check if we are an implementation of an interface method or
1944 if (parent.Pending != null)
1945 implementing = parent.Pending.IsInterfaceMethod (
1946 iface_type, short_name, ret_type, parameters);
1949 // For implicit implementations, make sure we are public, for
1950 // explicit implementations, make sure we are private.
1952 if (implementing != null){
1954 // Setting null inside this block will trigger a more
1955 // verbose error reporting for missing interface implementations
1957 // The "candidate" function has been flagged already
1958 // but it wont get cleared
1960 if (iface_type == null){
1962 // We already catch different accessibility settings
1963 // so we just need to check that we are not private
1965 if ((ModFlags & Modifiers.PRIVATE) != 0)
1966 implementing = null;
1969 // Static is not allowed
1971 if ((ModFlags & Modifiers.STATIC) != 0)
1972 implementing = null;
1974 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
1976 106, Location, "`public' or `abstract' modifiers "+
1977 "are not allowed in explicit interface declarations"
1979 implementing = null;
1985 // If implementing is still valid, set flags
1987 if (implementing != null){
1988 if (implementing.DeclaringType.IsInterface)
1989 flags |= MethodAttributes.NewSlot;
1992 MethodAttributes.Virtual |
1993 MethodAttributes.HideBySig;
1996 // clear the pending implementation flag
1998 parent.Pending.ImplementMethod (
1999 iface_type, short_name, ret_type, parameters, explicit_impl);
2002 Attribute dllimport_attr = null;
2003 if (OptAttributes != null && OptAttributes.AttributeSections != null) {
2004 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2005 if (asec.Attributes == null)
2008 foreach (Attribute a in asec.Attributes)
2009 if (a.Name.IndexOf ("DllImport") != -1) {
2010 flags |= MethodAttributes.PinvokeImpl;
2017 // Finally, define the method
2020 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2022 if ((ModFlags & Modifiers.STATIC) == 0) {
2023 Report.Error (601, Location, "The DllImport attribute must be specified on " +
2024 "a method marked 'static' and 'extern'.");
2028 EmitContext ec = new EmitContext (
2029 parent, Location, null, GetReturnType (parent), ModFlags);
2031 MethodBuilder = dllimport_attr.DefinePInvokeMethod (
2032 ec, parent.TypeBuilder,
2033 Name, flags, ret_type, parameters);
2035 MethodBuilder = parent.TypeBuilder.DefineMethod (
2037 GetCallingConvention (parent is Class),
2038 ret_type, parameters);
2040 if (implementing != null && explicit_impl)
2041 parent.TypeBuilder.DefineMethodOverride (
2042 MethodBuilder, implementing);
2045 if (MethodBuilder == null)
2049 // HACK because System.Reflection.Emit is lame
2051 ParameterInfo = new InternalParameters (parent, Parameters);
2053 if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo,
2057 "Class `" + parent.Name + "' already contains a definition with " +
2058 " the same return value and parameter types for method `" +
2064 // This is used to track the Entry Point,
2066 if (Name == "Main" &&
2067 ((ModFlags & Modifiers.STATIC) != 0) &&
2068 (RootContext.MainClass == null ||
2069 RootContext.MainClass == parent.TypeBuilder.FullName)){
2070 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2071 if (RootContext.EntryPoint == null) {
2072 RootContext.EntryPoint = MethodBuilder;
2073 RootContext.EntryPointLocation = Location;
2075 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2076 DuplicateEntryPoint (MethodBuilder, Location);
2079 Report28(MethodBuilder);
2088 public void Emit (TypeContainer parent)
2093 if ((flags & MethodAttributes.PinvokeImpl) == 0)
2094 ig = MethodBuilder.GetILGenerator ();
2098 ec = new EmitContext (parent, Location, ig, GetReturnType (parent), ModFlags);
2100 if (OptAttributes != null)
2101 Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location);
2104 LabelParameters (ec, ParameterTypes (parent), MethodBuilder);
2107 // abstract or extern methods have no bodies
2109 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
2111 if ((ModFlags & Modifiers.ABSTRACT) != 0){
2113 500, "Abstract method `" +
2114 TypeManager.CSharpSignature (MethodBuilder) +
2115 "' can not have a body");
2122 // Handle destructors specially
2124 // FIXME: This code generates buggy code
2126 if (Name == "Finalize" && type_return_type == TypeManager.void_type)
2127 EmitDestructor (ec);
2129 ISymbolWriter sw = CodeGen.SymbolWriter;
2131 if ((sw != null) && (!Location.IsNull (Location))) {
2132 MethodToken token = MethodBuilder.GetToken ();
2133 sw.OpenMethod (new SymbolToken (token.Token));
2134 sw.SetMethodSourceRange (Location.SymbolDocument,
2136 Block.EndLocation.SymbolDocument,
2137 Block.EndLocation.Row, 0);
2139 ec.EmitTopBlock (Block, Location);
2143 ec.EmitTopBlock (Block, Location);
2147 void EmitDestructor (EmitContext ec)
2149 ILGenerator ig = ec.ig;
2151 Label finish = ig.DefineLabel ();
2152 bool old_in_try = ec.InTry;
2154 ig.BeginExceptionBlock ();
2156 ec.ReturnLabel = finish;
2157 ec.EmitTopBlock (Block, Location);
2158 ec.InTry = old_in_try;
2160 ig.MarkLabel (finish);
2161 bool old_in_finally = ec.InFinally;
2162 ec.InFinally = true;
2163 ig.BeginFinallyBlock ();
2165 if (ec.ContainerType.BaseType != null) {
2166 Expression member_lookup = Expression.MemberLookup (
2167 ec, ec.ContainerType.BaseType, "Finalize",
2168 MemberTypes.Method, Expression.AllBindingFlags, Location);
2170 if (member_lookup != null){
2171 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
2173 ig.Emit (OpCodes.Ldarg_0);
2174 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
2177 ec.InFinally = old_in_finally;
2179 ig.EndExceptionBlock ();
2180 //ig.MarkLabel (ec.ReturnLabel);
2181 ig.Emit (OpCodes.Ret);
2185 public abstract class ConstructorInitializer {
2186 ArrayList argument_list;
2187 ConstructorInfo parent_constructor;
2190 public ConstructorInitializer (ArrayList argument_list, Location location)
2192 this.argument_list = argument_list;
2193 this.location = location;
2196 public ArrayList Arguments {
2198 return argument_list;
2202 public bool Resolve (EmitContext ec)
2204 Expression parent_constructor_group;
2207 if (argument_list != null){
2208 foreach (Argument a in argument_list){
2209 if (!a.Resolve (ec, location))
2214 if (this is ConstructorBaseInitializer) {
2215 if (ec.ContainerType.BaseType == null)
2218 t = ec.ContainerType.BaseType;
2220 t = ec.ContainerType;
2222 parent_constructor_group = Expression.MemberLookup (
2224 MemberTypes.Constructor,
2225 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2228 if (parent_constructor_group == null){
2229 Report.Error (1501, location,
2230 "Can not find a constructor for this argument list");
2234 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2235 (MethodGroupExpr) parent_constructor_group, argument_list, location);
2237 if (parent_constructor == null){
2238 Report.Error (1501, location,
2239 "Can not find a constructor for this argument list");
2246 public void Emit (EmitContext ec)
2248 ec.ig.Emit (OpCodes.Ldarg_0);
2249 if (argument_list != null)
2250 Invocation.EmitArguments (ec, null, argument_list);
2251 if (parent_constructor != null)
2252 ec.ig.Emit (OpCodes.Call, parent_constructor);
2256 public class ConstructorBaseInitializer : ConstructorInitializer {
2257 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2262 public class ConstructorThisInitializer : ConstructorInitializer {
2263 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2268 public class Constructor : MethodCore {
2269 public ConstructorBuilder ConstructorBuilder;
2270 public ConstructorInitializer Initializer;
2271 public Attributes OptAttributes;
2274 // Modifiers allowed for a constructor.
2276 const int AllowedModifiers =
2278 Modifiers.PROTECTED |
2279 Modifiers.INTERNAL |
2285 // The spec claims that static is not permitted, but
2286 // my very own code has static constructors.
2288 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2289 : base (name, args, l)
2295 // Returns true if this is a default constructor
2297 public bool IsDefault ()
2299 if ((ModFlags & Modifiers.STATIC) != 0)
2300 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2301 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2304 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2305 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2306 (Initializer is ConstructorBaseInitializer) &&
2307 (Initializer.Arguments == null);
2311 // Creates the ConstructorBuilder
2313 public override bool Define (TypeContainer parent)
2315 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2316 MethodAttributes.SpecialName);
2318 Type [] parameters = ParameterTypes (parent);
2320 if (parameters == null)
2323 if ((ModFlags & Modifiers.STATIC) != 0)
2324 ca |= MethodAttributes.Static;
2326 if (parent is Struct && parameters.Length == 0){
2329 "Structs can not contain explicit parameterless " +
2333 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2336 foreach (Type partype in parameters)
2337 if (!TypeContainer.AsAccessible (partype, ModFlags))
2340 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2341 ca, GetCallingConvention (parent is Class), parameters);
2344 // HACK because System.Reflection.Emit is lame
2346 ParameterInfo = new InternalParameters (parent, Parameters);
2348 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
2351 "Class `" +parent.Name+ "' already contains a definition with the " +
2352 "same return value and parameter types for constructor `" + Name
2363 public void Emit (TypeContainer parent)
2365 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2366 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2368 if (parent is Class && ((ModFlags & Modifiers.STATIC) == 0)){
2369 if (Initializer == null)
2370 Initializer = new ConstructorBaseInitializer (null, parent.Location);
2374 // Spec mandates that Initializers will not have
2378 if (!Initializer.Resolve (ec))
2380 ec.IsStatic = false;
2383 LabelParameters (ec, ParameterTypes (parent), ConstructorBuilder);
2386 // Classes can have base initializers and instance field initializers.
2388 if (parent is Class){
2389 if ((ModFlags & Modifiers.STATIC) == 0){
2390 parent.EmitFieldInitializers (ec);
2392 Initializer.Emit (ec);
2396 if ((ModFlags & Modifiers.STATIC) != 0)
2397 parent.EmitFieldInitializers (ec);
2399 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2401 ec.EmitTopBlock (Block, Location);
2406 // Fields and Events both generate FieldBuilders, we use this to share
2407 // their common bits. This is also used to flag usage of the field
2409 abstract public class FieldBase : MemberCore {
2410 public readonly string Type;
2411 public readonly Object Initializer;
2412 public readonly Attributes OptAttributes;
2413 public FieldBuilder FieldBuilder;
2414 public Status status;
2417 public enum Status : byte { ASSIGNED = 1, USED = 2 }
2420 // The constructor is only exposed to our children
2422 protected FieldBase (string type, int mod, int allowed_mod, string name,
2423 object init, Attributes attrs, Location loc)
2427 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
2429 OptAttributes = attrs;
2434 // The Field class is used to represents class/struct fields during parsing.
2436 public class Field : FieldBase {
2438 // Modifiers allowed in a class declaration
2440 const int AllowedModifiers =
2443 Modifiers.PROTECTED |
2444 Modifiers.INTERNAL |
2447 Modifiers.VOLATILE |
2451 public Field (string type, int mod, string name, Object expr_or_array_init,
2452 Attributes attrs, Location loc)
2453 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
2457 public override bool Define (TypeContainer parent)
2459 Type t = RootContext.LookupType (parent, Type, false, Location);
2464 if (!TypeContainer.AsAccessible (t, ModFlags))
2467 if (t.IsPointer && !UnsafeOK (parent))
2470 if (RootContext.WarningLevel > 1){
2471 Type ptype = parent.TypeBuilder.BaseType;
2473 // ptype is only null for System.Object while compiling corlib.
2477 mi = TypeContainer.FindMembers (
2478 ptype, MemberTypes.Method,
2479 BindingFlags.Public |
2480 BindingFlags.Static | BindingFlags.Instance,
2481 System.Type.FilterName, Name);
2485 if ((ModFlags & Modifiers.VOLATILE) != 0){
2487 if (TypeManager.IsEnumType (t))
2488 t = TypeManager.EnumToUnderlying (t);
2490 if (!((t == TypeManager.bool_type) ||
2491 (t == TypeManager.sbyte_type) ||
2492 (t == TypeManager.byte_type) ||
2493 (t == TypeManager.short_type) ||
2494 (t == TypeManager.ushort_type) ||
2495 (t == TypeManager.int32_type) ||
2496 (t == TypeManager.uint32_type) ||
2497 (t == TypeManager.char_type) ||
2498 (t == TypeManager.float_type))){
2500 677, Location, parent.MakeName (Name) +
2501 " A volatile field can not be of type `" +
2502 TypeManager.CSharpName (t) + "'");
2508 FieldBuilder = parent.TypeBuilder.DefineField (
2509 Name, t, Modifiers.FieldAttr (ModFlags));
2511 TypeManager.RegisterFieldBase (FieldBuilder, this);
2515 public void Emit (TypeContainer tc)
2517 EmitContext ec = new EmitContext (tc, Location, null,
2518 FieldBuilder.FieldType, ModFlags);
2520 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
2525 // `set' and `get' accessors are represented with an Accessor.
2527 public class Accessor {
2529 // Null if the accessor is empty, or a Block if not
2532 public Attributes OptAttributes;
2534 public Accessor (Block b, Attributes attrs)
2537 OptAttributes = attrs;
2541 public class Property : MemberCore {
2542 public readonly string Type;
2543 public Accessor Get, Set;
2544 public PropertyBuilder PropertyBuilder;
2545 public Attributes OptAttributes;
2546 public MethodBuilder GetBuilder, SetBuilder;
2549 // The type, once we compute it.
2554 const int AllowedModifiers =
2557 Modifiers.PROTECTED |
2558 Modifiers.INTERNAL |
2562 Modifiers.OVERRIDE |
2563 Modifiers.ABSTRACT |
2568 public Property (string type, string name, int mod_flags,
2569 Accessor get_block, Accessor set_block,
2570 Attributes attrs, Location loc)
2574 ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
2577 OptAttributes = attrs;
2581 // Checks our base implementation if any
2583 bool CheckBase (MethodAttributes flags, TypeContainer parent)
2586 // Find properties with the same name on the base class
2589 MemberInfo [] props;
2590 MemberInfo [] props_static = TypeManager.MemberLookup (
2592 parent.TypeBuilder.BaseType,
2593 MemberTypes.Property, BindingFlags.Public | BindingFlags.Static,
2596 MemberInfo [] props_instance = TypeManager.MemberLookup (
2598 parent.TypeBuilder.BaseType,
2599 MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance,
2603 // Find if we have anything
2605 if (props_static != null && props_static.Length > 0)
2606 props = props_static;
2607 else if (props_instance != null && props_instance.Length > 0)
2608 props = props_instance;
2613 // If we have something on the base.
2614 if (props != null && props.Length > 0){
2615 if (props.Length > 1)
2616 throw new Exception ("Should not happen");
2618 PropertyInfo pi = (PropertyInfo) props [0];
2620 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
2621 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
2623 MethodInfo reference = inherited_get == null ?
2624 inherited_set : inherited_get;
2626 if (reference != null)
2627 if (!CheckMethodAgainstBase (parent, flags, reference))
2631 if ((ModFlags & Modifiers.NEW) != 0)
2632 WarningNotHiding (parent);
2634 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2635 Report.Error (115, Location,
2636 parent.MakeName (Name) +
2637 " no suitable properties found to override");
2644 bool DefineMethod (TypeContainer parent, Type iface_type, string short_name,
2645 MethodAttributes flags, bool is_get)
2647 Type [] parameters = TypeManager.NoTypes;
2648 MethodInfo implementing = null;
2653 fn_type = PropertyType;
2654 name = "get_" + short_name;
2656 name = "set_" + short_name;
2657 parameters = new Type [1];
2658 parameters [0] = PropertyType;
2659 fn_type = TypeManager.void_type;
2662 if (parent.Pending != null)
2663 implementing = parent.Pending.IsInterfaceMethod (
2664 iface_type, name, fn_type, parameters);
2667 // For implicit implementations, make sure we are public, for
2668 // explicit implementations, make sure we are private.
2670 if (implementing != null){
2672 // Setting null inside this block will trigger a more
2673 // verbose error reporting for missing interface implementations
2675 // The "candidate" function has been flagged already
2676 // but it wont get cleared
2678 if (iface_type == null){
2680 // We already catch different accessibility settings
2681 // so we just need to check that we are not private
2683 if ((ModFlags & Modifiers.PRIVATE) != 0)
2684 implementing = null;
2687 // Static is not allowed
2689 if ((ModFlags & Modifiers.STATIC) != 0)
2690 implementing = null;
2692 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
2694 106, Location, "`public' or `abstract' modifiers "+
2695 "are not allowed in explicit interface declarations"
2697 implementing = null;
2703 // If implementing is still valid, set flags
2705 if (implementing != null){
2707 // When implementing interface methods, set NewSlot.
2709 if (implementing.DeclaringType.IsInterface)
2710 flags |= MethodAttributes.NewSlot;
2713 MethodAttributes.Virtual |
2714 MethodAttributes.HideBySig;
2717 // clear the pending implemntation flag
2719 parent.Pending.ImplementMethod (
2720 iface_type, name, fn_type, parameters, explicit_impl);
2724 // If this is not an explicit interface implementation,
2725 // clear implementing, as it is only used for explicit
2726 // interface implementation
2728 if (Name.IndexOf (".") == -1)
2729 implementing = null;
2732 GetBuilder = parent.TypeBuilder.DefineMethod (
2733 name, flags, PropertyType, null);
2734 PropertyBuilder.SetGetMethod (GetBuilder);
2736 if (implementing != null)
2737 parent.TypeBuilder.DefineMethodOverride (
2738 GetBuilder, implementing);
2741 // HACK because System.Reflection.Emit is lame
2743 InternalParameters ip = new InternalParameters (
2744 parent, Parameters.GetEmptyReadOnlyParameters ());
2746 if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) {
2747 Report.Error (111, Location,
2748 "Class `" + parent.Name +
2749 "' already contains a definition with the " +
2750 "same return value and parameter types as the " +
2751 "'get' method of property `" + Name + "'");
2755 SetBuilder = parent.TypeBuilder.DefineMethod (
2756 name, flags, null, parameters);
2758 if (implementing != null)
2759 parent.TypeBuilder.DefineMethodOverride (
2760 SetBuilder, implementing);
2762 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
2763 PropertyBuilder.SetSetMethod (SetBuilder);
2766 // HACK because System.Reflection.Emit is lame
2768 Parameter [] parms = new Parameter [1];
2769 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
2770 InternalParameters ip = new InternalParameters (
2771 parent, new Parameters (parms, null, Location));
2773 if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) {
2776 "Class `" + parent.Name +
2777 "' already contains a definition with the " +
2778 "same return value and parameter types as the " +
2779 "'set' method of property `" + Name + "'");
2787 public override bool Define (TypeContainer parent)
2789 Type iface_type = null;
2792 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2795 MethodAttributes flags = Modifiers.MethodAttr (ModFlags);
2797 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
2799 // Lookup Type, verify validity
2800 PropertyType = RootContext.LookupType (parent, Type, false, Location);
2801 if (PropertyType == null)
2804 // verify accessibility
2805 if (!TypeContainer.AsAccessible (PropertyType, ModFlags))
2808 if (PropertyType.IsPointer && !UnsafeOK (parent))
2811 if (!CheckBase (flags, parent))
2815 // Check for explicit interface implementation
2817 if (Name.IndexOf (".") != -1){
2818 int pos = Name.LastIndexOf (".");
2819 string iface = Name.Substring (0, pos);
2821 iface_type = RootContext.LookupType (parent, iface, false, Location);
2822 if (iface_type == null)
2825 short_name = Name.Substring (pos + 1);
2827 // Compute the full name that we need to export.
2828 Name = iface_type.FullName + "." + short_name;
2829 explicit_impl = true;
2831 explicit_impl = false;
2835 // FIXME - PropertyAttributes.HasDefault ?
2837 PropertyAttributes prop_attr = PropertyAttributes.RTSpecialName |
2838 PropertyAttributes.SpecialName;
2840 PropertyBuilder = parent.TypeBuilder.DefineProperty (
2841 Name, prop_attr, PropertyType, null);
2844 if (!DefineMethod (parent, iface_type, short_name, flags, true))
2848 if (!DefineMethod (parent, iface_type, short_name, flags, false))
2852 // HACK for the reasons exposed above
2854 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
2857 "Class `" + parent.Name +
2858 "' already contains a definition for the property `" +
2866 public void Emit (TypeContainer tc)
2871 ec = new EmitContext (tc, Location, null, PropertyType, ModFlags);
2872 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
2876 // abstract or extern properties have no bodies
2878 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
2882 ig = GetBuilder.GetILGenerator ();
2883 ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags);
2885 Attribute.ApplyAttributes (ec, GetBuilder, Get, Get.OptAttributes, Location);
2886 ec.EmitTopBlock (Get.Block, Location);
2890 ig = SetBuilder.GetILGenerator ();
2891 ec = new EmitContext (tc, Location, ig, null, ModFlags);
2893 Attribute.ApplyAttributes (ec, SetBuilder, Set, Set.OptAttributes, Location);
2894 ec.EmitTopBlock (Set.Block, Location);
2901 /// Gigantic workaround for lameness in SRE follows :
2902 /// This class derives from EventInfo and attempts to basically
2903 /// wrap around the EventBuilder so that FindMembers can quickly
2904 /// return this in it search for members
2906 public class MyEventBuilder : EventInfo {
2909 // We use this to "point" to our Builder which is
2910 // not really a MemberInfo
2912 EventBuilder MyBuilder;
2915 // We "catch" and wrap these methods
2917 MethodInfo raise, remove, add;
2919 EventAttributes attributes;
2920 Type declaring_type, reflected_type, event_type;
2923 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
2925 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
2927 // And now store the values in our own fields.
2929 declaring_type = type_builder;
2931 reflected_type = type_builder;
2933 attributes = event_attr;
2935 this.event_type = event_type;
2939 // Methods that you have to override. Note that you only need
2940 // to "implement" the variants that take the argument (those are
2941 // the "abstract" methods, the others (GetAddMethod()) are
2944 public override MethodInfo GetAddMethod (bool nonPublic)
2949 public override MethodInfo GetRemoveMethod (bool nonPublic)
2954 public override MethodInfo GetRaiseMethod (bool nonPublic)
2960 // These methods make "MyEventInfo" look like a Builder
2962 public void SetRaiseMethod (MethodBuilder raiseMethod)
2964 raise = raiseMethod;
2965 MyBuilder.SetRaiseMethod (raiseMethod);
2968 public void SetRemoveOnMethod (MethodBuilder removeMethod)
2970 remove = removeMethod;
2971 MyBuilder.SetRemoveOnMethod (removeMethod);
2974 public void SetAddOnMethod (MethodBuilder addMethod)
2977 MyBuilder.SetAddOnMethod (addMethod);
2980 public void SetCustomAttribute (CustomAttributeBuilder cb)
2982 MyBuilder.SetCustomAttribute (cb);
2985 public override object [] GetCustomAttributes (bool inherit)
2987 // FIXME : There's nothing which can be seemingly done here because
2988 // we have no way of getting at the custom attribute objects of the
2993 public override object [] GetCustomAttributes (Type t, bool inherit)
2995 // FIXME : Same here !
2999 public override bool IsDefined (Type t, bool b)
3004 public override EventAttributes Attributes {
3010 public override string Name {
3016 public override Type DeclaringType {
3018 return declaring_type;
3022 public override Type ReflectedType {
3024 return reflected_type;
3028 public Type EventType {
3035 public class Event : FieldBase {
3036 const int AllowedModifiers =
3039 Modifiers.PROTECTED |
3040 Modifiers.INTERNAL |
3045 Modifiers.OVERRIDE |
3049 public readonly Accessor Add;
3050 public readonly Accessor Remove;
3051 public MyEventBuilder EventBuilder;
3054 MethodBuilder AddBuilder, RemoveBuilder;
3056 public Event (string type, string name, Object init, int mod, Accessor add,
3057 Accessor remove, Attributes attrs, Location loc)
3058 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
3064 public override bool Define (TypeContainer parent)
3066 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
3069 MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
3070 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3072 EventType = RootContext.LookupType (parent, Type, false, Location);
3073 if (EventType == null)
3076 if (!TypeContainer.AsAccessible (EventType, ModFlags))
3079 if (EventType.IsPointer && !UnsafeOK (parent))
3082 if (!EventType.IsSubclassOf (TypeManager.delegate_type)) {
3083 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3084 "' : event must be of a delegate type");
3088 Type [] parameters = new Type [1];
3089 parameters [0] = EventType;
3091 EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType);
3093 if (Add == null && Remove == null){
3094 FieldBuilder = parent.TypeBuilder.DefineField (
3095 Name, EventType, FieldAttributes.Private);
3096 TypeManager.RegisterFieldBase (FieldBuilder, this);
3100 // Now define the accessors
3102 string add_name = "add_" + Name;
3104 AddBuilder = parent.TypeBuilder.DefineMethod (
3105 add_name, m_attr, null, parameters);
3106 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3107 EventBuilder.SetAddOnMethod (AddBuilder);
3108 if (parent.Pending != null)
3109 parent.Pending.ImplementMethod (null, add_name, null, parameters, false);
3112 // HACK because System.Reflection.Emit is lame
3114 Parameter [] parms = new Parameter [1];
3115 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3116 InternalParameters ip = new InternalParameters (
3117 parent, new Parameters (parms, null, Location));
3119 if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) {
3120 Report.Error (111, Location,
3121 "Class `" + parent.Name + "' already contains a definition with the " +
3122 "same return value and parameter types for the " +
3123 "'add' method of event `" + Name + "'");
3127 string remove_name = "remove_" + Name;
3128 RemoveBuilder = parent.TypeBuilder.DefineMethod (
3129 remove_name, m_attr, null, parameters);
3130 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3131 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3134 // This looks like dead code
3136 //if (parent.Pending != null)
3137 // parent.Pending.IsInterfaceMethod (null, remove_name, null, parameters, false);
3140 // HACK because System.Reflection.Emit is lame
3143 if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) {
3144 Report.Error (111, Location,
3145 "Class `" + parent.Name + "' already contains a definition with the " +
3146 "same return value and parameter types for the " +
3147 "'remove' method of event `" + Name + "'");
3151 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3152 Report.Error (111, Location,
3153 "Class `" + parent.Name +
3154 "' already contains a definition for the event `" +
3162 void EmitDefaultMethod (EmitContext ec, bool is_add)
3164 ILGenerator ig = ec.ig;
3165 MethodInfo method = null;
3168 method = TypeManager.delegate_combine_delegate_delegate;
3170 method = TypeManager.delegate_remove_delegate_delegate;
3172 ig.Emit (OpCodes.Ldarg_0);
3173 ig.Emit (OpCodes.Ldarg_0);
3174 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3175 ig.Emit (OpCodes.Ldarg_1);
3176 ig.Emit (OpCodes.Call, method);
3177 ig.Emit (OpCodes.Castclass, EventType);
3178 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3179 ig.Emit (OpCodes.Ret);
3182 public void Emit (TypeContainer tc)
3187 ig = AddBuilder.GetILGenerator ();
3188 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3191 Attribute.ApplyAttributes (ec, AddBuilder, Add, Add.OptAttributes, Location);
3192 ec.EmitTopBlock (Add.Block, Location);
3194 EmitDefaultMethod (ec, true);
3196 ig = RemoveBuilder.GetILGenerator ();
3197 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3199 if (Remove != null) {
3200 Attribute.ApplyAttributes (ec, RemoveBuilder, Remove, Remove.OptAttributes, Location);
3201 ec.EmitTopBlock (Remove.Block, Location);
3203 EmitDefaultMethod (ec, false);
3205 ec = new EmitContext (tc, Location, null, EventType, ModFlags);
3206 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3213 // FIXME: This does not handle:
3215 // int INTERFACENAME [ args ]
3220 // int this [ args ]
3222 public class Indexer : MemberCore {
3224 const int AllowedModifiers =
3227 Modifiers.PROTECTED |
3228 Modifiers.INTERNAL |
3232 Modifiers.OVERRIDE |
3237 public readonly string Type;
3238 public readonly string InterfaceType;
3239 public readonly Parameters FormalParameters;
3240 public readonly Accessor Get, Set;
3241 public Attributes OptAttributes;
3242 public MethodBuilder GetBuilder;
3243 public MethodBuilder SetBuilder;
3244 public PropertyBuilder PropertyBuilder;
3245 public Type IndexerType;
3246 public string IndexerName;
3250 public Indexer (string type, string int_type, int flags, Parameters parms,
3251 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
3256 InterfaceType = int_type;
3257 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
3258 FormalParameters = parms;
3261 OptAttributes = attrs;
3264 bool DefineMethod (TypeContainer parent, Type iface_type,
3265 Type ret_type, string name,
3266 Type [] parameters, MethodAttributes attr, bool is_get)
3268 MethodInfo implementing = null;
3269 bool is_implementation;
3271 if (parent.Pending != null)
3272 implementing = parent.Pending.IsInterfaceMethod (
3273 iface_type, name, ret_type, parameters);
3275 is_implementation = implementing != null;
3278 // Setting null inside this block will trigger a more
3279 // verbose error reporting for missing interface implementations
3281 // The "candidate" function has been flagged already
3282 // but it wont get cleared
3284 if (implementing != null){
3285 if (iface_type == null){
3287 // We already catch different accessibility settings
3288 // so we just need to check that we are not private
3290 if ((ModFlags & Modifiers.PRIVATE) != 0)
3291 implementing = null;
3294 // Static is not allowed
3296 if ((ModFlags & Modifiers.STATIC) != 0)
3297 implementing = null;
3299 if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT)) != 0){
3302 "`public' or `abstract' modifiers are not "+
3303 "allowed in explicit interface declarations"
3305 implementing = null;
3309 if (implementing != null){
3311 // When implementing interface methods, set NewSlot.
3313 if (implementing.DeclaringType.IsInterface)
3314 attr |= MethodAttributes.NewSlot;
3317 MethodAttributes.Virtual |
3318 MethodAttributes.HideBySig;
3321 // clear the pending implementing flag
3323 parent.Pending.ImplementMethod (
3324 iface_type, name, ret_type, parameters, true);
3328 // If this is not an explicit interface implementation,
3329 // clear implementing, as it is only used for explicit
3330 // interface implementation
3332 if (InterfaceType == null)
3333 implementing = null;
3336 string meth_name = "get_" + IndexerName;
3337 if (iface_type != null)
3338 meth_name = iface_type + ".get_" + IndexerName;
3340 GetBuilder = parent.TypeBuilder.DefineMethod (
3341 meth_name, attr, IndexerType, parameters);
3343 if (implementing != null)
3344 parent.TypeBuilder.DefineMethodOverride (
3345 GetBuilder, implementing);
3347 string meth_name = "set_" + IndexerName;
3349 if (iface_type != null)
3350 meth_name = iface_type + ".set_" + IndexerName;
3352 SetBuilder = parent.TypeBuilder.DefineMethod (
3353 meth_name, attr, null, parameters);
3354 if (implementing != null)
3355 parent.TypeBuilder.DefineMethodOverride (
3356 SetBuilder, implementing);
3359 return is_implementation;
3362 public override bool Define (TypeContainer parent)
3364 PropertyAttributes prop_attr =
3365 PropertyAttributes.RTSpecialName |
3366 PropertyAttributes.SpecialName;
3369 IndexerType = RootContext.LookupType (parent, Type, false, Location);
3370 Type [] parameters = FormalParameters.GetParameterInfo (parent);
3372 // Check if the return type and arguments were correct
3373 if (IndexerType == null || parameters == null)
3376 if (!parent.MethodModifiersValid (ModFlags, InterfaceType == null ?
3377 "this" : InterfaceType, Location))
3381 // verify accessibility and unsafe pointers
3383 if (!TypeContainer.AsAccessible (IndexerType, ModFlags))
3386 if (IndexerType.IsPointer && !UnsafeOK (parent))
3389 foreach (Type partype in parameters){
3390 if (!TypeContainer.AsAccessible (partype, ModFlags))
3392 if (partype.IsPointer && !UnsafeOK (parent))
3399 Type iface_type = null;
3401 if (InterfaceType != null){
3402 iface_type = RootContext.LookupType (parent, InterfaceType, false, Location);
3403 if (iface_type == null)
3407 ec = new EmitContext (parent, Location, null, IndexerType, ModFlags);
3409 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
3410 if (IndexerName == null)
3411 IndexerName = "Item";
3413 MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
3415 bool is_implementing = false;
3418 is_implementing = DefineMethod (
3419 parent, iface_type, IndexerType, "get_" + IndexerName,
3420 parameters, attr, true);
3421 InternalParameters pi = new InternalParameters (parent, FormalParameters);
3422 if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) {
3423 Report.Error (111, Location,
3424 "Class `" + parent.Name +
3425 "' already contains a definition with the " +
3426 "same return value and parameter types for the " +
3433 int top = parameters.Length;
3434 Type [] set_pars = new Type [top + 1];
3435 parameters.CopyTo (set_pars, 0);
3436 set_pars [top] = IndexerType;
3438 Parameter [] fixed_parms = FormalParameters.FixedParameters;
3440 if (fixed_parms == null){
3441 throw new Exception ("We currently do not support only array arguments in an indexer");
3442 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3443 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3445 // Here is the problem: the `value' parameter has
3446 // to come *after* the array parameter in the declaration
3448 // X (object [] x, Type value)
3451 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3452 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3456 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3459 fixed_parms.CopyTo (tmp, 0);
3460 tmp [fixed_parms.Length] = new Parameter (
3461 Type, "value", Parameter.Modifier.NONE, null);
3463 Parameters set_formal_params = new Parameters (tmp, null, Location);
3465 is_implementing = DefineMethod (
3466 parent, iface_type, TypeManager.void_type,
3467 "set_" + IndexerName, set_pars, attr, false);
3469 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3471 if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) {
3474 "Class `" + parent.Name + "' already contains a " +
3475 "definition with the " +
3476 "same return value and parameter types for the " +
3483 // Now name the parameters
3485 Parameter [] p = FormalParameters.FixedParameters;
3489 for (i = 0; i < p.Length; ++i) {
3491 GetBuilder.DefineParameter (
3492 i + 1, p [i].Attributes, p [i].Name);
3495 SetBuilder.DefineParameter (
3496 i + 1, p [i].Attributes, p [i].Name);
3500 SetBuilder.DefineParameter (
3501 i + 1, ParameterAttributes.None, "value");
3503 if (i != parameters.Length) {
3504 Parameter array_param = FormalParameters.ArrayParameter;
3505 SetBuilder.DefineParameter (i + 1, array_param.Attributes,
3512 // Only define the PropertyBuilder if we are not implementing
3513 // an interface property.
3515 if (!is_implementing){
3516 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3517 IndexerName, prop_attr, IndexerType, parameters);
3518 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
3520 if (GetBuilder != null)
3521 PropertyBuilder.SetGetMethod (GetBuilder);
3523 if (SetBuilder != null)
3524 PropertyBuilder.SetSetMethod (SetBuilder);
3530 public void Emit (TypeContainer tc)
3534 Attribute.ApplyAttributes (
3535 ec, PropertyBuilder, this, OptAttributes, Location);
3537 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3541 ig = GetBuilder.GetILGenerator ();
3542 ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags);
3544 ec.EmitTopBlock (Get.Block, Location);
3548 ig = SetBuilder.GetILGenerator ();
3549 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3551 ec.EmitTopBlock (Set.Block, Location);
3556 public class Operator : MemberCore {
3558 const int AllowedModifiers =
3564 const int RequiredModifiers =
3568 public enum OpType : byte {
3578 // Unary and Binary operators
3601 // Implicit and Explicit
3606 public readonly OpType OperatorType;
3607 public readonly string ReturnType;
3608 public readonly string FirstArgType;
3609 public readonly string FirstArgName;
3610 public readonly string SecondArgType;
3611 public readonly string SecondArgName;
3612 public readonly Block Block;
3613 public Attributes OptAttributes;
3614 public MethodBuilder OperatorMethodBuilder;
3616 public string MethodName;
3617 public Method OperatorMethod;
3619 public Operator (OpType type, string ret_type, int flags, string arg1type, string arg1name,
3620 string arg2type, string arg2name, Block block, Attributes attrs, Location loc)
3623 OperatorType = type;
3624 ReturnType = ret_type;
3625 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
3626 FirstArgType = arg1type;
3627 FirstArgName = arg1name;
3628 SecondArgType = arg2type;
3629 SecondArgName = arg2name;
3631 OptAttributes = attrs;
3634 string Prototype (TypeContainer parent)
3636 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
3637 SecondArgType + ")";
3640 public override bool Define (TypeContainer parent)
3643 MethodName = "op_" + OperatorType;
3645 if (SecondArgType != null)
3648 Parameter [] param_list = new Parameter [length];
3650 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
3653 "User defined operators `" +
3654 Prototype (parent) +
3655 "' must be declared static and public");
3659 param_list[0] = new Parameter (FirstArgType, FirstArgName,
3660 Parameter.Modifier.NONE, null);
3661 if (SecondArgType != null)
3662 param_list[1] = new Parameter (SecondArgType, SecondArgName,
3663 Parameter.Modifier.NONE, null);
3665 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
3666 new Parameters (param_list, null, Location),
3667 OptAttributes, Mono.CSharp.Location.Null);
3669 OperatorMethod.Define (parent);
3671 if (OperatorMethod.MethodBuilder == null)
3674 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
3676 Type [] param_types = OperatorMethod.ParameterTypes (parent);
3677 Type declaring_type = OperatorMethodBuilder.DeclaringType;
3678 Type return_type = OperatorMethod.GetReturnType (parent);
3679 Type first_arg_type = param_types [0];
3681 // Rules for conversion operators
3683 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
3684 if (first_arg_type == return_type && first_arg_type == declaring_type){
3687 "User-defined conversion cannot take an object of the " +
3688 "enclosing type and convert to an object of the enclosing" +
3693 if (first_arg_type != declaring_type && return_type != declaring_type){
3696 "User-defined conversion must convert to or from the " +
3701 if (first_arg_type == TypeManager.object_type ||
3702 return_type == TypeManager.object_type){
3705 "User-defined conversion cannot convert to or from " +
3710 if (first_arg_type.IsInterface || return_type.IsInterface){
3713 "User-defined conversion cannot convert to or from an " +
3718 if (first_arg_type.IsSubclassOf (return_type) ||
3719 return_type.IsSubclassOf (first_arg_type)){
3722 "User-defined conversion cannot convert between types " +
3723 "that derive from each other");
3726 } else if (SecondArgType == null) {
3727 // Checks for Unary operators
3729 if (first_arg_type != declaring_type){
3732 "The parameter of a unary operator must be the " +
3737 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
3738 if (return_type != declaring_type){
3741 "The parameter and return type for ++ and -- " +
3742 "must be the containing type");
3748 if (OperatorType == OpType.True || OperatorType == OpType.False) {
3749 if (return_type != TypeManager.bool_type){
3752 "The return type of operator True or False " +
3759 // Checks for Binary operators
3761 if (first_arg_type != declaring_type &&
3762 param_types [1] != declaring_type){
3765 "One of the parameters of a binary operator must " +
3766 "be the containing type");
3774 public void Emit (TypeContainer parent)
3776 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
3777 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
3780 // abstract or extern methods have no bodies
3782 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3785 OperatorMethod.Block = Block;
3786 OperatorMethod.Emit (parent);
3791 // This is used to compare method signatures
3793 struct MethodSignature {
3795 public Type RetType;
3796 public Type [] Parameters;
3799 /// This delegate is used to extract methods which have the
3800 /// same signature as the argument
3802 public static MemberFilter method_signature_filter;
3805 /// This delegate is used to extract inheritable methods which
3806 /// have the same signature as the argument. By inheritable,
3807 /// this means that we have permissions to override the method
3808 /// from the current assembly and class
3810 public static MemberFilter inheritable_method_signature_filter;
3812 static MethodSignature ()
3814 method_signature_filter = new MemberFilter (MemberSignatureCompare);
3815 inheritable_method_signature_filter = new MemberFilter (
3816 InheritableMemberSignatureCompare);
3819 public MethodSignature (string name, Type ret_type, Type [] parameters)
3824 if (parameters == null)
3825 Parameters = TypeManager.NoTypes;
3827 Parameters = parameters;
3830 public override int GetHashCode ()
3832 return Name.GetHashCode ();
3835 public override bool Equals (Object o)
3837 MethodSignature other = (MethodSignature) o;
3839 if (other.Name != Name)
3842 if (other.RetType != RetType)
3845 if (Parameters == null){
3846 if (other.Parameters == null)
3851 if (other.Parameters == null)
3854 int c = Parameters.Length;
3855 if (other.Parameters.Length != c)
3858 for (int i = 0; i < c; i++)
3859 if (other.Parameters [i] != Parameters [i])
3865 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
3869 if (! (m is MethodInfo))
3872 MethodSignature sig = (MethodSignature) filter_criteria;
3874 if (m.Name != sig.Name)
3877 mi = (MethodInfo) m;
3880 // we use sig.RetType == null to mean `do not check the
3881 // method return value.
3883 if (sig.RetType != null)
3884 if (mi.ReturnType != sig.RetType)
3887 Type [] args = TypeManager.GetArgumentTypes (mi);
3888 Type [] sigp = sig.Parameters;
3890 if (args.Length != sigp.Length)
3893 for (int i = args.Length; i > 0; ){
3895 if (args [i] != sigp [i])
3902 // This filter should be used when we are requesting methods that
3903 // we want to override.
3905 // This makes a number of assumptions, for example
3906 // that the methods being extracted are of a parent
3907 // class (this means we know implicitly that we are
3908 // being called to find out about members by a derived
3911 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
3913 if (MemberSignatureCompare (m, filter_criteria)){
3914 MethodInfo mi = (MethodInfo) m;
3915 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
3917 // If only accessible to the current class.
3918 if (prot == MethodAttributes.Private)
3921 // If only accessible to the defining assembly or
3922 if (prot == MethodAttributes.FamANDAssem ||
3923 prot == MethodAttributes.Assembly){
3924 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
3930 // Anything else (FamOrAssembly and Public) is fine