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;
106 // The interfaces we implement.
110 // The indexer name for this class
112 public string IndexerName;
114 public TypeContainer (TypeContainer parent, string name, Location l)
115 : base (parent, name, l)
118 types = new ArrayList ();
125 base_class_name = null;
127 //Console.WriteLine ("New class " + name + " inside " + n);
130 public AdditionResult AddConstant (Const constant)
133 string name = constant.Name;
135 if ((res = IsValid (name)) != AdditionResult.Success)
138 if (constants == null)
139 constants = new ArrayList ();
141 constants.Add (constant);
142 DefineName (name, constant);
144 return AdditionResult.Success;
147 public AdditionResult AddEnum (Mono.CSharp.Enum e)
150 string name = e.Name;
152 if ((res = IsValid (name)) != AdditionResult.Success)
156 enums = new ArrayList ();
159 DefineName (name, e);
161 return AdditionResult.Success;
164 public AdditionResult AddClass (Class c)
167 string name = c.Name;
170 if ((res = IsValid (name)) != AdditionResult.Success)
173 DefineName (name, c);
176 return AdditionResult.Success;
179 public AdditionResult AddStruct (Struct s)
182 string name = s.Name;
184 if ((res = IsValid (name)) != AdditionResult.Success)
187 DefineName (name, s);
190 return AdditionResult.Success;
193 public AdditionResult AddDelegate (Delegate d)
196 string name = d.Name;
198 if ((res = IsValid (name)) != AdditionResult.Success)
201 if (delegates == null)
202 delegates = new ArrayList ();
204 DefineName (name, d);
207 return AdditionResult.Success;
210 public AdditionResult AddMethod (Method method)
212 string name = method.Name;
213 Object value = defined_names [name];
215 if (value != null && (!(value is Method)))
216 return AdditionResult.NameExists;
218 if (name == Basename)
219 return AdditionResult.EnclosingClash;
222 methods = new ArrayList ();
224 if (method.Name.IndexOf (".") != -1)
225 methods.Insert (0, method);
227 methods.Add (method);
230 DefineName (name, method);
232 return AdditionResult.Success;
235 public AdditionResult AddConstructor (Constructor c)
237 if (c.Name != Basename)
238 return AdditionResult.NotAConstructor;
240 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
243 have_static_constructor = true;
244 if (default_static_constructor != null){
245 Console.WriteLine ("I have a static constructor already");
246 Console.WriteLine (" " + default_static_constructor);
247 return AdditionResult.MethodExists;
250 default_static_constructor = c;
253 if (default_constructor != null)
254 return AdditionResult.MethodExists;
255 default_constructor = c;
258 if (instance_constructors == null)
259 instance_constructors = new ArrayList ();
261 instance_constructors.Add (c);
264 return AdditionResult.Success;
267 public AdditionResult AddInterface (Interface iface)
270 string name = iface.Name;
272 if ((res = IsValid (name)) != AdditionResult.Success)
275 if (interfaces == null)
276 interfaces = new ArrayList ();
277 interfaces.Add (iface);
278 DefineName (name, iface);
280 return AdditionResult.Success;
283 public AdditionResult AddField (Field field)
286 string name = field.Name;
288 if ((res = IsValid (name)) != AdditionResult.Success)
292 fields = new ArrayList ();
296 if (field.Initializer != null){
297 if ((field.ModFlags & Modifiers.STATIC) != 0){
298 if (initialized_static_fields == null)
299 initialized_static_fields = new ArrayList ();
301 initialized_static_fields.Add (field);
304 // We have not seen a static constructor,
305 // but we will provide static initialization of fields
307 have_static_constructor = true;
309 if (initialized_fields == null)
310 initialized_fields = new ArrayList ();
312 initialized_fields.Add (field);
316 if ((field.ModFlags & Modifiers.STATIC) == 0)
317 have_nonstatic_fields = true;
319 DefineName (name, field);
320 return AdditionResult.Success;
323 public AdditionResult AddProperty (Property prop)
326 string name = prop.Name;
328 if ((res = IsValid (name)) != AdditionResult.Success)
331 if (properties == null)
332 properties = new ArrayList ();
334 if (prop.Name.IndexOf (".") != -1)
335 properties.Insert (0, prop);
337 properties.Add (prop);
338 DefineName (name, prop);
340 return AdditionResult.Success;
343 public AdditionResult AddEvent (Event e)
346 string name = e.Name;
348 if ((res = IsValid (name)) != AdditionResult.Success)
352 events = new ArrayList ();
355 DefineName (name, e);
357 return AdditionResult.Success;
360 public AdditionResult AddIndexer (Indexer i)
362 if (indexers == null)
363 indexers = new ArrayList ();
365 if (i.InterfaceType != null)
366 indexers.Insert (0, i);
370 return AdditionResult.Success;
373 public AdditionResult AddOperator (Operator op)
375 if (operators == null)
376 operators = new ArrayList ();
380 return AdditionResult.Success;
383 public void RegisterOrder (Interface iface)
385 if (interface_order == null)
386 interface_order = new ArrayList ();
388 interface_order.Add (iface);
391 public ArrayList Types {
397 public ArrayList Methods {
403 public ArrayList Constants {
409 public ArrayList Interfaces {
417 return base_class_name;
421 public ArrayList Bases {
431 public ArrayList Fields {
441 public ArrayList InstanceConstructors {
443 return instance_constructors;
447 public ArrayList Properties {
453 public ArrayList Events {
459 public ArrayList Enums {
465 public ArrayList Indexers {
471 public ArrayList Operators {
477 public ArrayList Delegates {
483 public Attributes OptAttributes {
489 public bool HaveStaticConstructor {
491 return have_static_constructor;
495 public virtual TypeAttributes TypeAttr {
497 return Modifiers.TypeAttr (ModFlags, this);
502 // Emits the instance field initializers
504 public bool EmitFieldInitializers (EmitContext ec)
507 ILGenerator ig = ec.ig;
508 Expression instance_expr;
511 fields = initialized_static_fields;
512 instance_expr = null;
514 fields = initialized_fields;
515 instance_expr = new This (Location.Null).Resolve (ec);
521 foreach (Field f in fields){
522 Object init = f.Initializer;
525 if (init is Expression)
526 e = (Expression) init;
528 e = new ArrayCreation (f.Type, "", (ArrayList)init, f.Location);
531 Location l = f.Location;
532 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
533 fe.InstanceExpression = instance_expr;
534 Expression a = new Assign (fe, e, l);
540 if (a is ExpressionStatement)
541 ((ExpressionStatement) a).EmitStatement (ec);
543 throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
551 // Defines the default constructors
553 void DefineDefaultConstructor (bool is_static)
558 c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
559 new ConstructorBaseInitializer (null, new Location (-1)),
563 mods = Modifiers.STATIC;
569 c.Block = new Block (null);
573 public void ReportStructInitializedInstanceError ()
575 string n = TypeBuilder.FullName;
577 foreach (Field f in initialized_fields){
580 "`" + n + "." + f.Name + "': can not have " +
581 "instance field initializers in structs");
586 /// The pending methods that need to be implemented (interfaces or abstract methods)
588 public PendingImplementation Pending;
591 /// This function computes the Base class and also the
592 /// list of interfaces that the class or struct @c implements.
594 /// The return value is an array (might be null) of
595 /// interfaces implemented (as Types).
597 /// The @parent argument is set to the parent object or null
598 /// if this is `System.Object'.
600 Type [] GetClassBases (bool is_class, out Type parent, out bool error)
602 ArrayList bases = Bases;
611 parent = TypeManager.value_type;
615 if (RootContext.StdLib)
616 parent = TypeManager.object_type;
617 else if (Name != "System.Object")
618 parent = TypeManager.object_type;
621 // If we are compiling our runtime,
622 // and we are defining ValueType, then our
623 // parent is `System.Object'.
625 if (!RootContext.StdLib && Name == "System.ValueType")
626 parent = TypeManager.object_type;
633 // Bases should be null if there are no bases at all
638 Expression name = (Expression) bases [0];
639 name = ResolveTypeExpr (name, false, Location);
646 Type first = name.Type;
652 parent = TypeManager.object_type;
660 Type [] ifaces = new Type [count-start];
662 for (i = start, j = 0; i < count; i++, j++){
663 Expression name = (Expression) bases [i];
664 Expression resolved = ResolveTypeExpr (name, false, Location);
665 bases [i] = resolved;
666 Type t = resolved.Type;
673 if (is_class == false && !t.IsInterface){
674 Report.Error (527, "In Struct `" + Name + "', type `"+
675 name +"' is not an interface");
684 detail = " (a class can not inherit from a struct/enum)";
686 Report.Error (509, "class `"+ Name +
687 "': Cannot inherit from sealed class `"+
688 bases [i]+"'"+detail);
695 Report.Error (527, "In Class `" + Name + "', type `"+
696 name+"' is not an interface");
702 for (int x = 0; x < j; x++) {
703 if (t == ifaces [x]) {
704 Report.Error (528, "`" + name + "' is already listed in interface list");
713 return TypeManager.ExpandInterfaces (ifaces);
717 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
719 public override TypeBuilder DefineType ()
725 if (TypeBuilder != null)
738 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
740 ifaces = GetClassBases (is_class, out parent, out error);
745 if (is_class && parent != null){
746 if (parent == TypeManager.enum_type ||
747 (parent == TypeManager.value_type && RootContext.StdLib) ||
748 parent == TypeManager.delegate_type ||
749 parent == TypeManager.array_type){
751 644, Location, "`" + Name + "' cannot inherit from " +
752 "special class `" + TypeManager.CSharpName (parent) + "'");
757 if (!is_class && TypeManager.value_type == null)
758 throw new Exception ();
760 TypeAttributes type_attributes = TypeAttr;
762 // if (parent_builder is ModuleBuilder) {
764 ModuleBuilder builder = CodeGen.ModuleBuilder;
767 // Structs with no fields need to have a ".size 1"
771 if (!is_class && !have_nonstatic_fields)
772 TypeBuilder = builder.DefineType (Name,
775 PackingSize.Unspecified, 1);
778 // classes or structs with fields
780 TypeBuilder = builder.DefineType (Name,
785 TypeBuilder builder = Parent.TypeBuilder;
788 // Structs with no fields need to have a ".size 1"
791 if (!is_class && !have_nonstatic_fields)
792 TypeBuilder = builder.DefineNestedType (Basename,
795 PackingSize.Unspecified);
798 // classes or structs with fields
800 TypeBuilder = builder.DefineNestedType (Basename,
807 // add interfaces that were not added at type creation (weird API issue)
808 if (!is_class && !have_nonstatic_fields && (ifaces != null)) {
809 foreach (Type i in ifaces)
810 TypeBuilder.AddInterfaceImplementation (i);
814 // Finish the setup for the EmitContext
816 ec.ContainerType = TypeBuilder;
818 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
820 if ((parent != null) &&
821 (parent == TypeManager.attribute_type ||
822 parent.IsSubclassOf (TypeManager.attribute_type))) {
823 RootContext.RegisterAttribute (this);
824 TypeManager.RegisterAttrType (TypeBuilder, this);
826 RootContext.RegisterOrder (this);
828 if (Interfaces != null) {
829 foreach (Interface iface in Interfaces)
834 foreach (TypeContainer tc in Types)
838 if (Delegates != null) {
839 foreach (Delegate d in Delegates)
844 foreach (Enum en in Enums)
854 /// Defines the MemberCore objects that are in the `list' Arraylist
856 /// The `defined_names' array contains a list of members defined in
859 static ArrayList remove_list = new ArrayList ();
860 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
864 remove_list.Clear ();
866 foreach (MemberCore mc in list){
867 if (!mc.Define (this)){
868 remove_list.Add (mc);
872 if (defined_names == null)
875 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
877 if (RootContext.WarningLevel >= 4){
878 if ((mc.ModFlags & Modifiers.NEW) != 0)
879 Warning_KewywordNewNotRequired (mc.Location, mc);
884 MemberInfo match = defined_names [idx];
886 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
890 // If we are both methods, let the method resolution emit warnings
892 if (match is MethodBase && mc is MethodCore)
895 if ((mc.ModFlags & Modifiers.NEW) == 0)
896 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
899 foreach (object o in remove_list)
902 remove_list.Clear ();
906 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
907 // class is consisten. Either it is `Item' or it is the name defined by all the
908 // indexers with the `IndexerName' attribute.
910 // Turns out that the IndexerNameAttribute is applied to each indexer,
911 // but it is never emitted, instead a DefaultName attribute is attached
914 void DefineIndexers ()
916 string class_indexer_name = null;
918 foreach (Indexer i in Indexers){
923 name = i.IndexerName;
925 if (i.InterfaceType != null)
928 if (class_indexer_name == null){
929 class_indexer_name = name;
933 if (name == class_indexer_name)
937 668, "Two indexers have different names, " +
938 " you should use the same name for all your indexers");
940 if (class_indexer_name == null)
941 class_indexer_name = "Item";
942 IndexerName = class_indexer_name;
946 /// Populates our TypeBuilder with fields and methods
948 public override bool Define (TypeContainer parent)
950 MemberInfo [] defined_names = null;
952 if (RootContext.WarningLevel > 1){
956 // This code throws an exception in the comparer
957 // I guess the string is not an object?
959 ptype = TypeBuilder.BaseType;
961 defined_names = FindMembers (
962 ptype, MemberTypes.All & ~MemberTypes.Constructor,
963 BindingFlags.Public | BindingFlags.Instance |
964 BindingFlags.Static, null, null);
966 Array.Sort (defined_names, mif_compare);
970 if (constants != null)
971 DefineMembers (constants, defined_names);
974 DefineMembers (fields, defined_names);
977 if (instance_constructors == null){
978 if (default_constructor == null)
979 DefineDefaultConstructor (false);
982 if (initialized_static_fields != null &&
983 default_static_constructor == null)
984 DefineDefaultConstructor (true);
989 // Structs can not have initialized instance
992 if (initialized_static_fields != null &&
993 default_static_constructor == null)
994 DefineDefaultConstructor (true);
996 if (initialized_fields != null)
997 ReportStructInitializedInstanceError ();
1000 Pending = PendingImplementation.GetPendingImplementations (this);
1003 // Constructors are not in the defined_names array
1005 if (instance_constructors != null)
1006 DefineMembers (instance_constructors, null);
1008 if (default_static_constructor != null)
1009 default_static_constructor.Define (this);
1011 if (methods != null)
1012 DefineMembers (methods, defined_names);
1014 if (properties != null)
1015 DefineMembers (properties, defined_names);
1018 DefineMembers (events, defined_names);
1020 if (indexers != null) {
1023 IndexerName = "Item";
1025 if (operators != null)
1026 DefineMembers (operators, null);
1029 DefineMembers (enums, defined_names);
1031 if (delegates != null)
1032 DefineMembers (delegates, defined_names);
1038 /// This function is based by a delegate to the FindMembers routine
1040 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1046 /// This filter is used by FindMembers, and we just keep
1047 /// a global for the filter to `AlwaysAccept'
1049 static MemberFilter accepting_filter;
1053 /// A member comparission method based on name only
1055 static IComparer mif_compare;
1057 static TypeContainer ()
1059 accepting_filter = new MemberFilter (AlwaysAccept);
1060 mif_compare = new MemberInfoCompare ();
1064 /// This method returns the members of this type just like Type.FindMembers would
1065 /// Only, we need to use this for types which are _being_ defined because MS'
1066 /// implementation can't take care of that.
1069 // FIXME: return an empty static array instead of null, that cleans up
1070 // some code and is consistent with some coding conventions I just found
1074 // Notice that in various cases we check if our field is non-null,
1075 // something that would normally mean that there was a bug elsewhere.
1077 // The problem happens while we are defining p-invoke methods, as those
1078 // will trigger a FindMembers, but this happens before things are defined
1080 // Since the whole process is a no-op, it is fine to check for null here.
1082 public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
1083 MemberFilter filter, object criteria)
1085 ArrayList members = new ArrayList ();
1086 bool priv = (bf & BindingFlags.NonPublic) != 0;
1089 filter = accepting_filter;
1091 if ((mt & MemberTypes.Field) != 0) {
1092 if (fields != null) {
1093 foreach (Field f in fields) {
1094 if ((f.ModFlags & Modifiers.PRIVATE) != 0)
1098 FieldBuilder fb = f.FieldBuilder;
1099 if (fb != null && filter (fb, criteria) == true)
1104 if (constants != null) {
1105 foreach (Const con in constants) {
1106 if ((con.ModFlags & Modifiers.PRIVATE) != 0)
1110 FieldBuilder fb = con.FieldBuilder;
1111 if (fb != null && filter (fb, criteria) == true)
1117 if ((mt & MemberTypes.Method) != 0) {
1118 if (methods != null) {
1119 foreach (Method m in methods) {
1120 if ((m.ModFlags & Modifiers.PRIVATE) != 0)
1124 MethodBuilder mb = m.MethodBuilder;
1126 if (mb != null && filter (mb, criteria) == true)
1131 if (operators != null){
1132 foreach (Operator o in operators) {
1133 if ((o.ModFlags & Modifiers.PRIVATE) != 0)
1137 MethodBuilder ob = o.OperatorMethodBuilder;
1138 if (ob != null && filter (ob, criteria) == true)
1143 if (properties != null){
1144 foreach (Property p in properties){
1145 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1152 if (b != null && filter (b, criteria) == true)
1156 if (b != null && filter (b, criteria) == true)
1162 if ((mt & MemberTypes.Event) != 0) {
1164 foreach (Event e in events) {
1165 if ((e.ModFlags & Modifiers.PRIVATE) != 0)
1169 MemberInfo eb = e.EventBuilder;
1170 if (eb != null && filter (eb, criteria) == true)
1171 members.Add (e.EventBuilder);
1175 if ((mt & MemberTypes.Property) != 0){
1176 if (properties != null)
1177 foreach (Property p in properties) {
1178 if ((p.ModFlags & Modifiers.PRIVATE) != 0)
1182 MemberInfo pb = p.PropertyBuilder;
1183 if (pb != null && filter (pb, criteria) == true) {
1184 members.Add (p.PropertyBuilder);
1188 if (indexers != null)
1189 foreach (Indexer ix in indexers) {
1190 if ((ix.ModFlags & Modifiers.PRIVATE) != 0)
1194 MemberInfo ib = ix.PropertyBuilder;
1195 if (ib != null && filter (ib, criteria) == true) {
1196 members.Add (ix.PropertyBuilder);
1201 if ((mt & MemberTypes.NestedType) != 0) {
1203 foreach (TypeContainer t in types) {
1204 TypeBuilder tb = t.TypeBuilder;
1206 if (tb != null && (filter (tb, criteria) == true))
1212 foreach (Enum en in enums){
1213 TypeBuilder tb = en.TypeBuilder;
1215 if (tb != null && (filter (tb, criteria) == true))
1220 if (delegates != null){
1221 foreach (Delegate d in delegates){
1222 TypeBuilder tb = d.TypeBuilder;
1224 if (tb != null && (filter (tb, criteria) == true))
1230 if ((mt & MemberTypes.Constructor) != 0){
1231 if (instance_constructors != null){
1232 foreach (Constructor c in instance_constructors){
1233 ConstructorBuilder cb = c.ConstructorBuilder;
1236 if (filter (cb, criteria) == true)
1241 if (default_static_constructor != null){
1242 ConstructorBuilder cb =
1243 default_static_constructor.ConstructorBuilder;
1246 if (filter (cb, criteria) == true)
1252 // Lookup members in parent if requested.
1254 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1257 mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1259 members.AddRange (mi);
1262 int count = members.Count;
1264 MemberInfo [] mi = new MemberInfo [count];
1265 members.CopyTo (mi);
1274 public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1275 MemberFilter filter, object criteria)
1277 TypeContainer tc = TypeManager.LookupTypeContainer (t);
1280 return tc.FindMembers (mt, bf, filter, criteria);
1282 return t.FindMembers (mt, bf, filter, criteria);
1286 // FindMethods will look for methods not only in the type `t', but in
1287 // any interfaces implemented by the type.
1289 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1290 MemberFilter filter, object criteria)
1296 /// Emits the values for the constants
1298 public void EmitConstants ()
1300 if (constants != null)
1301 foreach (Const con in constants)
1302 con.EmitConstant (this);
1307 /// Emits the code, this step is performed after all
1308 /// the types, enumerations, constructors
1312 if (instance_constructors != null)
1313 foreach (Constructor c in instance_constructors)
1316 if (default_static_constructor != null)
1317 default_static_constructor.Emit (this);
1319 if (methods != null)
1320 foreach (Method m in methods)
1323 if (operators != null)
1324 foreach (Operator o in operators)
1327 if (properties != null)
1328 foreach (Property p in properties)
1331 if (indexers != null){
1332 foreach (Indexer ix in indexers)
1335 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1336 this, IndexerName, ModFlags, Location);
1337 TypeBuilder.SetCustomAttribute (cb);
1341 foreach (Field f in fields)
1344 if (events != null){
1345 foreach (Event e in Events)
1349 if (Pending != null)
1350 if (Pending.VerifyPendingMethods ())
1353 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
1356 // Check for internal or private fields that were never assigned
1358 if (fields != null && RootContext.WarningLevel >= 3) {
1359 foreach (Field f in fields) {
1360 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1365 169, f.Location, "Private field " +
1366 MakeName (f.Name) + " is never used");
1371 // Only report 649 on level 4
1373 if (RootContext.WarningLevel < 4)
1376 if ((f.status & Field.Status.ASSIGNED) != 0)
1381 "Field " + MakeName (f.Name) + " is never assigned " +
1382 " to and will always have its default value");
1386 // if (types != null)
1387 // foreach (TypeContainer tc in types)
1391 public override void CloseType ()
1396 TypeBuilder.CreateType ();
1398 } catch (TypeLoadException){
1400 // This is fine, the code still created the type
1402 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1403 // Console.WriteLine (e.Message);
1405 Console.WriteLine ("In type: " + Name);
1410 foreach (Enum en in Enums)
1413 if (interface_order != null){
1414 foreach (Interface iface in interface_order)
1419 foreach (TypeContainer tc in Types)
1423 foreach (TypeContainer tc in Types)
1424 if (!(tc is Struct))
1428 if (Delegates != null)
1429 foreach (Delegate d in Delegates)
1433 public string MakeName (string n)
1435 return "`" + Name + "." + n + "'";
1438 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1441 108, l, "The keyword new is required on " +
1442 MakeName (mi.Name) + " because it hides `" +
1443 mi.ReflectedType.Name + "." + mi.Name + "'");
1446 public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
1449 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1450 "inherited member, the keyword new is not required");
1453 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1459 // Performs the validation on a Method's modifiers (properties have
1460 // the same properties).
1462 public bool MethodModifiersValid (int flags, string n, Location loc)
1464 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1465 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1466 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1468 string name = MakeName (n);
1471 // At most one of static, virtual or override
1473 if ((flags & Modifiers.STATIC) != 0){
1474 if ((flags & vao) != 0){
1476 112, loc, "static method " + name + "can not be marked " +
1477 "as virtual, abstract or override");
1482 if (this is Struct){
1483 if ((flags & va) != 0){
1484 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1489 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1492 " marked as override cannot be marked as new or virtual");
1497 // If the declaration includes the abstract modifier, then the
1498 // declaration does not include static, virtual or extern
1500 if ((flags & Modifiers.ABSTRACT) != 0){
1501 if ((flags & Modifiers.EXTERN) != 0){
1503 180, loc, name + " can not be both abstract and extern");
1507 if ((flags & Modifiers.VIRTUAL) != 0){
1509 503, loc, name + " can not be both abstract and virtual");
1513 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1516 " is abstract but its container class is not");
1522 if ((flags & Modifiers.PRIVATE) != 0){
1523 if ((flags & vao) != 0){
1526 " virtual or abstract members can not be private");
1531 if ((flags & Modifiers.SEALED) != 0){
1532 if ((flags & Modifiers.OVERRIDE) == 0){
1535 " cannot be sealed because it is not an override");
1544 // Returns true if `type' is as accessible as the flags `flags'
1545 // given for this member
1547 static public bool AsAccessible (Type type, int flags)
1552 Hashtable builder_and_args;
1554 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1556 if (builder_and_args == null)
1557 builder_and_args = new Hashtable ();
1562 /// Performs checks for an explicit interface implementation. First it
1563 /// checks whether the `interface_type' is a base inteface implementation.
1564 /// Then it checks whether `name' exists in the interface type.
1566 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1570 if (ifaces != null){
1571 foreach (Type t in ifaces){
1572 if (t == interface_type){
1580 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1587 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1589 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1593 public class Class : TypeContainer {
1595 // Modifiers allowed in a class declaration
1597 public const int AllowedModifiers =
1600 Modifiers.PROTECTED |
1601 Modifiers.INTERNAL |
1603 Modifiers.ABSTRACT |
1607 public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1608 : base (parent, name, l)
1612 if (parent.Parent == null)
1613 accmods = Modifiers.INTERNAL;
1615 accmods = Modifiers.PRIVATE;
1617 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1618 this.attributes = attrs;
1622 // FIXME: How do we deal with the user specifying a different
1625 public override TypeAttributes TypeAttr {
1627 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
1632 public class Struct : TypeContainer {
1634 // Modifiers allowed in a struct declaration
1636 public const int AllowedModifiers =
1639 Modifiers.PROTECTED |
1640 Modifiers.INTERNAL |
1644 public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
1645 : base (parent, name, l)
1649 if (parent.Parent == null)
1650 accmods = Modifiers.INTERNAL;
1652 accmods = Modifiers.PRIVATE;
1654 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
1656 this.ModFlags |= Modifiers.SEALED;
1657 this.attributes = attrs;
1662 // FIXME: Allow the user to specify a different set of attributes
1663 // in some cases (Sealed for example is mandatory for a class,
1664 // but what SequentialLayout can be changed
1666 public override TypeAttributes TypeAttr {
1668 return base.TypeAttr |
1669 TypeAttributes.SequentialLayout |
1670 TypeAttributes.Sealed |
1671 TypeAttributes.BeforeFieldInit;
1676 public abstract class MethodCore : MemberCore {
1677 public readonly Parameters Parameters;
1681 // Parameters, cached for semantic analysis.
1683 InternalParameters parameter_info;
1685 public MethodCore (string name, Parameters parameters, Location l)
1689 Parameters = parameters;
1693 // Returns the System.Type array for the parameters of this method
1695 Type [] parameter_types;
1696 public Type [] ParameterTypes (TypeContainer parent)
1698 if (Parameters == null)
1699 return TypeManager.NoTypes;
1701 if (parameter_types == null)
1702 parameter_types = Parameters.GetParameterInfo (parent);
1704 return parameter_types;
1707 public InternalParameters ParameterInfo
1710 return parameter_info;
1714 parameter_info = value;
1718 public Block Block {
1728 public CallingConventions GetCallingConvention (bool is_class)
1730 CallingConventions cc = 0;
1732 cc = Parameters.GetCallingConvention ();
1735 if ((ModFlags & Modifiers.STATIC) == 0)
1736 cc |= CallingConventions.HasThis;
1738 // FIXME: How is `ExplicitThis' used in C#?
1743 public void LabelParameters (EmitContext ec, Type [] parameters, MethodBase builder)
1746 // Define each type attribute (in/out/ref) and
1747 // the argument names.
1749 Parameter [] p = Parameters.FixedParameters;
1752 MethodBuilder mb = null;
1753 ConstructorBuilder cb = null;
1755 if (builder is MethodBuilder)
1756 mb = (MethodBuilder) builder;
1758 cb = (ConstructorBuilder) builder;
1761 for (i = 0; i < p.Length; i++) {
1762 ParameterBuilder pb;
1765 pb = cb.DefineParameter (
1766 i + 1, p [i].Attributes, p [i].Name);
1768 pb = mb.DefineParameter (
1769 i + 1, p [i].Attributes, p [i].Name);
1771 Attributes attr = p [i].OptAttributes;
1773 Attribute.ApplyAttributes (ec, pb, pb, attr, Location);
1777 if (Parameters.ArrayParameter != null){
1778 ParameterBuilder pb;
1779 Parameter array_param = Parameters.ArrayParameter;
1782 pb = cb.DefineParameter (
1783 i + 1, array_param.Attributes,
1786 pb = mb.DefineParameter (
1787 i + 1, array_param.Attributes,
1790 CustomAttributeBuilder a = new CustomAttributeBuilder (
1791 TypeManager.cons_param_array_attribute, new object [0]);
1793 pb.SetCustomAttribute (a);
1798 public class Method : MethodCore {
1799 public Expression ReturnType;
1800 public MethodBuilder MethodBuilder;
1801 public readonly Attributes OptAttributes;
1803 MethodAttributes flags;
1806 /// Modifiers allowed in a class declaration
1808 const int AllowedModifiers =
1811 Modifiers.PROTECTED |
1812 Modifiers.INTERNAL |
1817 Modifiers.OVERRIDE |
1818 Modifiers.ABSTRACT |
1823 // return_type can be "null" for VOID values.
1825 public Method (Expression return_type, int mod, string name, Parameters parameters,
1826 Attributes attrs, Location l)
1827 : base (name, parameters, l)
1829 ReturnType = return_type;
1830 ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
1831 OptAttributes = attrs;
1835 // Returns the `System.Type' for the ReturnType of this
1836 // function. Provides a nice cache. (used between semantic analysis
1837 // and actual code generation
1839 Type type_return_type;
1841 public Type GetReturnType (TypeContainer parent)
1843 if (type_return_type == null)
1844 type_return_type = parent.ResolveType (ReturnType, false, Location);
1846 return type_return_type;
1849 void DuplicateEntryPoint (MethodInfo b, Location location)
1853 "Program `" + CodeGen.FileName +
1854 "' has more than one entry point defined: `" +
1855 TypeManager.CSharpSignature(b) + "'");
1858 void Report28 (MethodInfo b)
1860 if (RootContext.WarningLevel < 4)
1865 "`" + TypeManager.CSharpSignature(b) +
1866 "' has the wrong signature to be an entry point");
1869 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
1871 if (b.ReturnType != TypeManager.void_type &&
1872 b.ReturnType != TypeManager.int32_type)
1875 if (pinfo.Count == 0)
1878 if (pinfo.Count > 1)
1881 Type t = pinfo.ParameterType(0);
1883 (t.GetArrayRank() == 1) &&
1884 (t.GetElementType() == TypeManager.string_type) &&
1885 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
1894 public override bool Define (TypeContainer parent)
1896 Type ret_type = GetReturnType (parent);
1897 Type [] parameters = ParameterTypes (parent);
1899 MethodInfo implementing = null;
1900 Type iface_type = null;
1901 string iface = "", short_name;
1902 bool explicit_impl = false;
1904 // Check if the return type and arguments were correct
1905 if (ret_type == null || parameters == null)
1908 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
1911 flags = Modifiers.MethodAttr (ModFlags);
1914 // verify accessibility
1916 if (!TypeContainer.AsAccessible (ret_type, ModFlags))
1919 if (ret_type.IsPointer && !UnsafeOK (parent))
1922 foreach (Type partype in parameters){
1923 if (!TypeContainer.AsAccessible (partype, ModFlags))
1925 if (partype.IsPointer && !UnsafeOK (parent))
1933 // Verify if the parent has a type with the same name, and then
1934 // check whether we have to create a new slot for it or not.
1936 Type ptype = parent.TypeBuilder.BaseType;
1938 // ptype is only null for System.Object while compiling corlib.
1940 MethodSignature ms = new MethodSignature (Name, null, parameters);
1941 MemberInfo [] mi, mi_static, mi_instance;
1943 mi_static = TypeContainer.FindMembers (
1944 ptype, MemberTypes.Method,
1945 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
1946 MethodSignature.inheritable_method_signature_filter, ms);
1948 mi_instance = TypeContainer.FindMembers (
1949 ptype, MemberTypes.Method,
1950 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
1951 MethodSignature.inheritable_method_signature_filter,
1954 if (mi_instance != null && mi_instance.Length > 0){
1956 } else if (mi_static != null && mi_static.Length > 0)
1961 if (mi != null && mi.Length > 0){
1962 if (!CheckMethodAgainstBase (parent, flags, (MethodInfo) mi [0])){
1966 if ((ModFlags & Modifiers.NEW) != 0)
1967 WarningNotHiding (parent);
1969 if ((ModFlags & Modifiers.OVERRIDE) != 0){
1970 Report.Error (115, Location,
1971 parent.MakeName (Name) +
1972 " no suitable methods found to override");
1975 } else if ((ModFlags & Modifiers.NEW) != 0)
1976 WarningNotHiding (parent);
1979 // If we implement an interface, extract the interface name.
1981 if (Name.IndexOf (".") != -1){
1982 int pos = Name.LastIndexOf (".");
1983 iface = Name.Substring (0, pos);
1985 iface_type = RootContext.LookupType (parent, iface, false, Location);
1986 short_name = Name.Substring (pos + 1);
1988 if (iface_type == null)
1991 // Compute the full name that we need to export
1992 Name = iface_type.FullName + "." + short_name;
1994 if (!parent.VerifyImplements (iface_type, short_name, Name, Location))
1997 explicit_impl = true;
2002 // Check if we are an implementation of an interface method or
2005 if (parent.Pending != null){
2006 implementing = parent.Pending.IsInterfaceMethod (
2007 iface_type, short_name, ret_type, parameters);
2009 if (iface_type != null && implementing == null){
2010 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (Location, short_name);
2016 // For implicit implementations, make sure we are public, for
2017 // explicit implementations, make sure we are private.
2019 if (implementing != null){
2021 // Setting null inside this block will trigger a more
2022 // verbose error reporting for missing interface implementations
2024 // The "candidate" function has been flagged already
2025 // but it wont get cleared
2027 if (iface_type == null){
2029 // We already catch different accessibility settings
2030 // so we just need to check that we are not private
2032 if ((ModFlags & Modifiers.PRIVATE) != 0)
2033 implementing = null;
2036 // Static is not allowed
2038 if ((ModFlags & Modifiers.STATIC) != 0)
2039 implementing = null;
2041 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2042 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2043 implementing = null;
2049 // If implementing is still valid, set flags
2051 if (implementing != null){
2052 // Console.WriteLine ("Implementing for:" + (iface_type != null ? iface_type.FullName : "<null>") + " " + short_name);
2054 if (implementing.DeclaringType.IsInterface)
2055 flags |= MethodAttributes.NewSlot;
2058 MethodAttributes.Virtual |
2059 MethodAttributes.HideBySig;
2062 // clear the pending implementation flag
2064 parent.Pending.ImplementMethod (
2065 iface_type, short_name, ret_type, parameters, explicit_impl);
2068 Attribute dllimport_attr = null;
2069 if (OptAttributes != null && OptAttributes.AttributeSections != null) {
2070 foreach (AttributeSection asec in OptAttributes.AttributeSections) {
2071 if (asec.Attributes == null)
2074 foreach (Attribute a in asec.Attributes)
2075 if (a.Name.IndexOf ("DllImport") != -1) {
2076 flags |= MethodAttributes.PinvokeImpl;
2083 // Finally, define the method
2086 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
2088 if ((ModFlags & Modifiers.STATIC) == 0) {
2089 Report.Error (601, Location, "The DllImport attribute must be specified on " +
2090 "a method marked 'static' and 'extern'.");
2094 EmitContext ec = new EmitContext (
2095 parent, Location, null, GetReturnType (parent), ModFlags);
2097 MethodBuilder = dllimport_attr.DefinePInvokeMethod (
2098 ec, parent.TypeBuilder,
2099 Name, flags, ret_type, parameters);
2101 MethodBuilder = parent.TypeBuilder.DefineMethod (
2103 GetCallingConvention (parent is Class),
2104 ret_type, parameters);
2106 if (implementing != null && explicit_impl)
2107 parent.TypeBuilder.DefineMethodOverride (
2108 MethodBuilder, implementing);
2111 if (MethodBuilder == null)
2115 // HACK because System.Reflection.Emit is lame
2117 ParameterInfo = new InternalParameters (parent, Parameters);
2119 if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo,
2123 "Class `" + parent.Name + "' already contains a definition with " +
2124 " the same return value and parameter types for method `" +
2130 // This is used to track the Entry Point,
2132 if (Name == "Main" &&
2133 ((ModFlags & Modifiers.STATIC) != 0) &&
2134 (RootContext.MainClass == null ||
2135 RootContext.MainClass == parent.TypeBuilder.FullName)){
2136 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2137 if (RootContext.EntryPoint == null) {
2138 RootContext.EntryPoint = MethodBuilder;
2139 RootContext.EntryPointLocation = Location;
2141 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2142 DuplicateEntryPoint (MethodBuilder, Location);
2145 Report28(MethodBuilder);
2154 public void Emit (TypeContainer parent)
2159 if ((flags & MethodAttributes.PinvokeImpl) == 0)
2160 ig = MethodBuilder.GetILGenerator ();
2164 ec = new EmitContext (parent, Location, ig, GetReturnType (parent), ModFlags);
2166 if (OptAttributes != null)
2167 Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location);
2170 LabelParameters (ec, ParameterTypes (parent), MethodBuilder);
2173 // abstract or extern methods have no bodies
2175 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
2177 if ((ModFlags & Modifiers.ABSTRACT) != 0){
2179 500, "Abstract method `" +
2180 TypeManager.CSharpSignature (MethodBuilder) +
2181 "' can not have a body");
2188 // Handle destructors specially
2190 // FIXME: This code generates buggy code
2192 if (Name == "Finalize" && type_return_type == TypeManager.void_type)
2193 EmitDestructor (ec);
2195 ISymbolWriter sw = CodeGen.SymbolWriter;
2197 if ((sw != null) && (!Location.IsNull (Location))) {
2198 MethodToken token = MethodBuilder.GetToken ();
2199 sw.OpenMethod (new SymbolToken (token.Token));
2200 sw.SetMethodSourceRange (Location.SymbolDocument,
2202 Block.EndLocation.SymbolDocument,
2203 Block.EndLocation.Row, 0);
2205 ec.EmitTopBlock (Block, Location);
2209 ec.EmitTopBlock (Block, Location);
2213 void EmitDestructor (EmitContext ec)
2215 ILGenerator ig = ec.ig;
2217 Label finish = ig.DefineLabel ();
2218 bool old_in_try = ec.InTry;
2220 ig.BeginExceptionBlock ();
2222 ec.ReturnLabel = finish;
2223 ec.HasReturnLabel = true;
2224 ec.EmitTopBlock (Block, Location);
2225 ec.InTry = old_in_try;
2227 // ig.MarkLabel (finish);
2228 bool old_in_finally = ec.InFinally;
2229 ec.InFinally = true;
2230 ig.BeginFinallyBlock ();
2232 if (ec.ContainerType.BaseType != null) {
2233 Expression member_lookup = Expression.MemberLookup (
2234 ec, ec.ContainerType.BaseType, "Finalize",
2235 MemberTypes.Method, Expression.AllBindingFlags, Location);
2237 if (member_lookup != null){
2238 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
2240 ig.Emit (OpCodes.Ldarg_0);
2241 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
2244 ec.InFinally = old_in_finally;
2246 ig.EndExceptionBlock ();
2247 //ig.MarkLabel (ec.ReturnLabel);
2248 ig.Emit (OpCodes.Ret);
2252 public abstract class ConstructorInitializer {
2253 ArrayList argument_list;
2254 ConstructorInfo parent_constructor;
2257 public ConstructorInitializer (ArrayList argument_list, Location location)
2259 this.argument_list = argument_list;
2260 this.location = location;
2263 public ArrayList Arguments {
2265 return argument_list;
2269 public bool Resolve (EmitContext ec)
2271 Expression parent_constructor_group;
2274 if (argument_list != null){
2275 foreach (Argument a in argument_list){
2276 if (!a.Resolve (ec, location))
2281 if (this is ConstructorBaseInitializer) {
2282 if (ec.ContainerType.BaseType == null)
2285 t = ec.ContainerType.BaseType;
2286 if (ec.ContainerType.IsValueType) {
2287 Report.Error (522, location,
2288 "structs cannot call base class constructors");
2292 t = ec.ContainerType;
2294 parent_constructor_group = Expression.MemberLookup (
2296 MemberTypes.Constructor,
2297 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2300 if (parent_constructor_group == null){
2301 Report.Error (1501, location,
2302 "Can not find a constructor for this argument list");
2306 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2307 (MethodGroupExpr) parent_constructor_group, argument_list, location);
2309 if (parent_constructor == null){
2310 Report.Error (1501, location,
2311 "Can not find a constructor for this argument list");
2318 public void Emit (EmitContext ec)
2320 if (parent_constructor != null)
2321 ec.ig.Emit (OpCodes.Ldarg_0);
2322 if (argument_list != null)
2323 Invocation.EmitArguments (ec, null, argument_list);
2324 if (parent_constructor != null)
2325 ec.ig.Emit (OpCodes.Call, parent_constructor);
2329 public class ConstructorBaseInitializer : ConstructorInitializer {
2330 public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2335 public class ConstructorThisInitializer : ConstructorInitializer {
2336 public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
2341 public class Constructor : MethodCore {
2342 public ConstructorBuilder ConstructorBuilder;
2343 public ConstructorInitializer Initializer;
2344 public Attributes OptAttributes;
2347 // Modifiers allowed for a constructor.
2349 const int AllowedModifiers =
2351 Modifiers.PROTECTED |
2352 Modifiers.INTERNAL |
2358 // The spec claims that static is not permitted, but
2359 // my very own code has static constructors.
2361 public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
2362 : base (name, args, l)
2368 // Returns true if this is a default constructor
2370 public bool IsDefault ()
2372 if ((ModFlags & Modifiers.STATIC) != 0)
2373 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2374 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2377 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2378 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2379 (Initializer is ConstructorBaseInitializer) &&
2380 (Initializer.Arguments == null);
2384 // Creates the ConstructorBuilder
2386 public override bool Define (TypeContainer parent)
2388 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2389 MethodAttributes.SpecialName);
2391 Type [] parameters = ParameterTypes (parent);
2393 if (parameters == null)
2396 if ((ModFlags & Modifiers.STATIC) != 0)
2397 ca |= MethodAttributes.Static;
2399 if (parent is Struct && parameters.Length == 0){
2402 "Structs can not contain explicit parameterless " +
2406 ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
2409 foreach (Type partype in parameters)
2410 if (!TypeContainer.AsAccessible (partype, ModFlags))
2413 ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
2414 ca, GetCallingConvention (parent is Class), parameters);
2417 // HACK because System.Reflection.Emit is lame
2419 ParameterInfo = new InternalParameters (parent, Parameters);
2421 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
2424 "Class `" +parent.Name+ "' already contains a definition with the " +
2425 "same return value and parameter types for constructor `" + Name
2436 public void Emit (TypeContainer parent)
2438 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2439 EmitContext ec = new EmitContext (parent, Location, ig, null, ModFlags, true);
2441 if ((ModFlags & Modifiers.STATIC) == 0){
2442 if (parent is Class && Initializer == null)
2443 Initializer = new ConstructorBaseInitializer (null, parent.Location);
2447 // Spec mandates that Initializers will not have
2451 if (Initializer != null && !Initializer.Resolve (ec))
2453 ec.IsStatic = false;
2456 LabelParameters (ec, ParameterTypes (parent), ConstructorBuilder);
2459 // Classes can have base initializers and instance field initializers.
2461 if (parent is Class){
2462 if ((ModFlags & Modifiers.STATIC) == 0)
2463 parent.EmitFieldInitializers (ec);
2465 if (Initializer != null)
2466 Initializer.Emit (ec);
2468 if ((ModFlags & Modifiers.STATIC) != 0)
2469 parent.EmitFieldInitializers (ec);
2471 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
2473 ec.EmitTopBlock (Block, Location);
2477 abstract public class MemberBase : MemberCore {
2478 public Expression Type;
2479 public readonly Attributes OptAttributes;
2481 protected MethodAttributes flags;
2484 // The "short" name of this property / indexer / event. This is the
2485 // name without the explicit interface.
2487 public string ShortName;
2490 // The type of this property / indexer / event
2492 public Type MemberType;
2495 // Are we implementing an interface ?
2497 public bool IsImplementing = false;
2500 // If true, this is an explicit interface implementation
2502 public bool IsExplicitImpl = false;
2505 // The name of the interface we are explicitly implementing
2507 public string ExplicitInterfaceName = null;
2510 // If true, the interface type we are explicitly implementing
2512 public Type InterfaceType = null;
2515 // The constructor is only exposed to our children
2517 protected MemberBase (Expression type, int mod, int allowed_mod, string name,
2518 Attributes attrs, Location loc)
2522 ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
2523 OptAttributes = attrs;
2526 protected virtual MethodBuilder DefineAccessor (TypeContainer parent, string accessor_name,
2527 Type return_type, Type [] parameter_types,
2528 InternalParameters parameters,
2529 MethodAttributes flags)
2531 MethodInfo implementing = null;
2532 MethodBuilder builder = null;
2533 string method_name, name, prefix;
2536 prefix = InterfaceType.FullName + ".";
2540 name = accessor_name + "_" + ShortName;
2541 method_name = prefix + name;
2543 if (parent.Pending != null){
2544 if (this is Indexer)
2545 implementing = parent.Pending.IsInterfaceIndexer (
2546 InterfaceType, return_type, parameter_types);
2548 implementing = parent.Pending.IsInterfaceMethod (
2549 InterfaceType, name, return_type, parameter_types);
2551 if (InterfaceType != null && implementing == null){
2552 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
2559 // For implicit implementations, make sure we are public, for
2560 // explicit implementations, make sure we are private.
2562 if (implementing != null){
2564 // Setting null inside this block will trigger a more
2565 // verbose error reporting for missing interface implementations
2567 // The "candidate" function has been flagged already
2568 // but it wont get cleared
2570 if (!IsExplicitImpl){
2572 // We already catch different accessibility settings
2573 // so we just need to check that we are not private
2575 if ((ModFlags & Modifiers.PRIVATE) != 0)
2576 implementing = null;
2579 // Static is not allowed
2581 if ((ModFlags & Modifiers.STATIC) != 0)
2582 implementing = null;
2584 if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
2585 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
2586 implementing = null;
2592 // If implementing is still valid, set flags
2594 if (implementing != null){
2596 // When implementing interface methods, set NewSlot.
2598 if (implementing.DeclaringType.IsInterface)
2599 flags |= MethodAttributes.NewSlot;
2602 MethodAttributes.Virtual |
2603 MethodAttributes.HideBySig;
2605 // Get the method name from the explicit interface.
2606 if (InterfaceType != null) {
2607 name = implementing.Name;
2608 method_name = prefix + name;
2611 IsImplementing = true;
2615 // Create the MethodBuilder for the method
2618 builder = parent.TypeBuilder.DefineMethod (
2619 method_name, flags, return_type, parameter_types);
2621 if (IsImplementing) {
2623 // clear the pending implemntation flag
2625 if (this is Indexer) {
2626 parent.Pending.ImplementIndexer (
2627 InterfaceType, builder, return_type,
2628 parameter_types, true);
2630 parent.Pending.ImplementMethod (
2631 InterfaceType, name, return_type,
2632 parameter_types, IsExplicitImpl);
2635 parent.TypeBuilder.DefineMethodOverride (
2636 builder, implementing);
2639 if (!TypeManager.RegisterMethod (builder, parameters, parameter_types)) {
2640 Report.Error (111, Location,
2641 "Class `" + parent.Name +
2642 "' already contains a definition with the " +
2643 "same return value and parameter types as the " +
2644 "'get' method of property `" + Name + "'");
2651 protected virtual bool CheckBase (TypeContainer parent)
2656 protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
2660 foreach (Type partype in parameters){
2661 if (!TypeContainer.AsAccessible (partype, ModFlags))
2663 if (partype.IsPointer && !UnsafeOK (parent))
2670 protected virtual bool DoDefine (TypeContainer parent)
2675 if (!parent.MethodModifiersValid (ModFlags, Name, Location))
2678 flags = Modifiers.MethodAttr (ModFlags);
2680 // Lookup Type, verify validity
2681 MemberType = parent.ResolveType (Type, false, Location);
2682 if (MemberType == null)
2685 // verify accessibility
2686 if (!TypeContainer.AsAccessible (MemberType, ModFlags))
2689 if (MemberType.IsPointer && !UnsafeOK (parent))
2692 if (!CheckBase (parent))
2696 // Check for explicit interface implementation
2698 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
2699 int pos = Name.LastIndexOf (".");
2701 ExplicitInterfaceName = Name.Substring (0, pos);
2702 ShortName = Name.Substring (pos + 1);
2706 if (ExplicitInterfaceName != null) {
2707 InterfaceType = RootContext.LookupType (
2708 parent, ExplicitInterfaceName, false, Location);
2709 if (InterfaceType == null)
2712 // Compute the full name that we need to export.
2713 Name = InterfaceType.FullName + "." + ShortName;
2715 if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
2718 IsExplicitImpl = true;
2720 IsExplicitImpl = false;
2727 // Fields and Events both generate FieldBuilders, we use this to share
2728 // their common bits. This is also used to flag usage of the field
2730 abstract public class FieldBase : MemberBase {
2731 public readonly Object Initializer;
2732 public FieldBuilder FieldBuilder;
2733 public Status status;
2736 public enum Status : byte { ASSIGNED = 1, USED = 2 }
2739 // The constructor is only exposed to our children
2741 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
2742 object init, Attributes attrs, Location loc)
2743 : base (type, mod, allowed_mod, name, attrs, loc)
2750 // The Field class is used to represents class/struct fields during parsing.
2752 public class Field : FieldBase {
2754 // Modifiers allowed in a class declaration
2756 const int AllowedModifiers =
2759 Modifiers.PROTECTED |
2760 Modifiers.INTERNAL |
2763 Modifiers.VOLATILE |
2767 public Field (Expression type, int mod, string name, Object expr_or_array_init,
2768 Attributes attrs, Location loc)
2769 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
2773 public override bool Define (TypeContainer parent)
2775 Type t = parent.ResolveType (Type, false, Location);
2780 if (!TypeContainer.AsAccessible (t, ModFlags))
2783 if (t.IsPointer && !UnsafeOK (parent))
2786 if (RootContext.WarningLevel > 1){
2787 Type ptype = parent.TypeBuilder.BaseType;
2789 // ptype is only null for System.Object while compiling corlib.
2793 mi = TypeContainer.FindMembers (
2794 ptype, MemberTypes.Method,
2795 BindingFlags.Public |
2796 BindingFlags.Static | BindingFlags.Instance,
2797 System.Type.FilterName, Name);
2801 if ((ModFlags & Modifiers.VOLATILE) != 0){
2803 if (TypeManager.IsEnumType (t))
2804 t = TypeManager.EnumToUnderlying (t);
2806 if (!((t == TypeManager.bool_type) ||
2807 (t == TypeManager.sbyte_type) ||
2808 (t == TypeManager.byte_type) ||
2809 (t == TypeManager.short_type) ||
2810 (t == TypeManager.ushort_type) ||
2811 (t == TypeManager.int32_type) ||
2812 (t == TypeManager.uint32_type) ||
2813 (t == TypeManager.char_type) ||
2814 (t == TypeManager.float_type))){
2816 677, Location, parent.MakeName (Name) +
2817 " A volatile field can not be of type `" +
2818 TypeManager.CSharpName (t) + "'");
2824 FieldBuilder = parent.TypeBuilder.DefineField (
2825 Name, t, Modifiers.FieldAttr (ModFlags));
2827 TypeManager.RegisterFieldBase (FieldBuilder, this);
2831 public void Emit (TypeContainer tc)
2833 EmitContext ec = new EmitContext (tc, Location, null,
2834 FieldBuilder.FieldType, ModFlags);
2836 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes, Location);
2841 // `set' and `get' accessors are represented with an Accessor.
2843 public class Accessor {
2845 // Null if the accessor is empty, or a Block if not
2848 public Attributes OptAttributes;
2850 public Accessor (Block b, Attributes attrs)
2853 OptAttributes = attrs;
2857 public class Property : MemberBase {
2858 public Accessor Get, Set;
2859 public PropertyBuilder PropertyBuilder;
2860 public MethodBuilder GetBuilder, SetBuilder;
2862 const int AllowedModifiers =
2865 Modifiers.PROTECTED |
2866 Modifiers.INTERNAL |
2870 Modifiers.OVERRIDE |
2871 Modifiers.ABSTRACT |
2876 public Property (Expression type, string name, int mod_flags,
2877 Accessor get_block, Accessor set_block,
2878 Attributes attrs, Location loc)
2879 : base (type, mod_flags, AllowedModifiers, name, attrs, loc)
2886 // Checks our base implementation if any
2888 protected override bool CheckBase (TypeContainer parent)
2891 // Find properties with the same name on the base class
2894 MemberInfo [] props;
2895 MemberInfo [] props_static = TypeManager.MemberLookup (
2897 parent.TypeBuilder.BaseType,
2898 MemberTypes.Property, BindingFlags.Public | BindingFlags.Static,
2901 MemberInfo [] props_instance = TypeManager.MemberLookup (
2903 parent.TypeBuilder.BaseType,
2904 MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance,
2908 // Find if we have anything
2910 if (props_static != null && props_static.Length > 0)
2911 props = props_static;
2912 else if (props_instance != null && props_instance.Length > 0)
2913 props = props_instance;
2918 // If we have something on the base.
2919 if (props != null && props.Length > 0){
2920 if (props.Length > 1)
2921 throw new Exception ("Should not happen");
2923 PropertyInfo pi = (PropertyInfo) props [0];
2925 MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
2926 MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
2928 MethodInfo reference = inherited_get == null ?
2929 inherited_set : inherited_get;
2931 if (reference != null)
2932 if (!CheckMethodAgainstBase (parent, flags, reference))
2936 if ((ModFlags & Modifiers.NEW) != 0)
2937 WarningNotHiding (parent);
2939 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2940 Report.Error (115, Location,
2941 parent.MakeName (Name) +
2942 " no suitable properties found to override");
2949 bool DefineMethod (TypeContainer parent, MethodAttributes flags, bool is_get)
2952 Type [] parameters = TypeManager.NoTypes;
2954 InternalParameters ip = new InternalParameters (
2955 parent, Parameters.GetEmptyReadOnlyParameters ());
2957 GetBuilder = DefineAccessor (
2958 parent, "get", MemberType, parameters, ip, flags);
2960 if (GetBuilder == null)
2963 Type [] parameters = new Type [1];
2964 parameters [0] = MemberType;
2966 Parameter [] parms = new Parameter [1];
2967 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
2968 InternalParameters ip = new InternalParameters (
2969 parent, new Parameters (parms, null, Location));
2971 SetBuilder = DefineAccessor (
2972 parent, "set", TypeManager.void_type, parameters, ip, flags);
2974 if (SetBuilder == null)
2977 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
2983 public override bool Define (TypeContainer parent)
2985 if (!DoDefine (parent))
2988 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
2991 if (!DefineMethod (parent, flags, true))
2995 if (!DefineMethod (parent, flags, false))
2998 // FIXME - PropertyAttributes.HasDefault ?
3000 PropertyAttributes prop_attr =
3001 PropertyAttributes.RTSpecialName |
3002 PropertyAttributes.SpecialName;
3004 if (!IsExplicitImpl){
3005 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3006 Name, prop_attr, MemberType, null);
3009 PropertyBuilder.SetGetMethod (GetBuilder);
3012 PropertyBuilder.SetSetMethod (SetBuilder);
3015 // HACK for the reasons exposed above
3017 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
3020 "Class `" + parent.Name +
3021 "' already contains a definition for the property `" +
3029 public void Emit (TypeContainer tc)
3034 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
3037 // The PropertyBuilder can be null for explicit implementations, in that
3038 // case, we do not actually emit the ".property", so there is nowhere to
3039 // put the attribute
3041 if (PropertyBuilder != null)
3042 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
3044 Attribute.ApplyAttributes (ec, GetBuilder, Get, Get.OptAttributes, Location);
3046 Attribute.ApplyAttributes (ec, SetBuilder, Set, Set.OptAttributes, Location);
3049 // abstract or extern properties have no bodies
3051 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3055 ig = GetBuilder.GetILGenerator ();
3056 ec = new EmitContext (tc, Location, ig, MemberType, ModFlags);
3058 ec.EmitTopBlock (Get.Block, Location);
3062 ig = SetBuilder.GetILGenerator ();
3063 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3065 ec.EmitTopBlock (Set.Block, Location);
3072 /// Gigantic workaround for lameness in SRE follows :
3073 /// This class derives from EventInfo and attempts to basically
3074 /// wrap around the EventBuilder so that FindMembers can quickly
3075 /// return this in it search for members
3077 public class MyEventBuilder : EventInfo {
3080 // We use this to "point" to our Builder which is
3081 // not really a MemberInfo
3083 EventBuilder MyBuilder;
3086 // We "catch" and wrap these methods
3088 MethodInfo raise, remove, add;
3090 EventAttributes attributes;
3091 Type declaring_type, reflected_type, event_type;
3094 public MyEventBuilder (TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
3096 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
3098 // And now store the values in our own fields.
3100 declaring_type = type_builder;
3102 reflected_type = type_builder;
3104 attributes = event_attr;
3106 this.event_type = event_type;
3110 // Methods that you have to override. Note that you only need
3111 // to "implement" the variants that take the argument (those are
3112 // the "abstract" methods, the others (GetAddMethod()) are
3115 public override MethodInfo GetAddMethod (bool nonPublic)
3120 public override MethodInfo GetRemoveMethod (bool nonPublic)
3125 public override MethodInfo GetRaiseMethod (bool nonPublic)
3131 // These methods make "MyEventInfo" look like a Builder
3133 public void SetRaiseMethod (MethodBuilder raiseMethod)
3135 raise = raiseMethod;
3136 MyBuilder.SetRaiseMethod (raiseMethod);
3139 public void SetRemoveOnMethod (MethodBuilder removeMethod)
3141 remove = removeMethod;
3142 MyBuilder.SetRemoveOnMethod (removeMethod);
3145 public void SetAddOnMethod (MethodBuilder addMethod)
3148 MyBuilder.SetAddOnMethod (addMethod);
3151 public void SetCustomAttribute (CustomAttributeBuilder cb)
3153 MyBuilder.SetCustomAttribute (cb);
3156 public override object [] GetCustomAttributes (bool inherit)
3158 // FIXME : There's nothing which can be seemingly done here because
3159 // we have no way of getting at the custom attribute objects of the
3164 public override object [] GetCustomAttributes (Type t, bool inherit)
3166 // FIXME : Same here !
3170 public override bool IsDefined (Type t, bool b)
3175 public override EventAttributes Attributes {
3181 public override string Name {
3187 public override Type DeclaringType {
3189 return declaring_type;
3193 public override Type ReflectedType {
3195 return reflected_type;
3199 public Type EventType {
3206 public class Event : FieldBase {
3207 const int AllowedModifiers =
3210 Modifiers.PROTECTED |
3211 Modifiers.INTERNAL |
3216 Modifiers.OVERRIDE |
3220 public readonly Accessor Add;
3221 public readonly Accessor Remove;
3222 public MyEventBuilder EventBuilder;
3224 MethodBuilder AddBuilder, RemoveBuilder;
3226 public Event (Expression type, string name, Object init, int mod, Accessor add,
3227 Accessor remove, Attributes attrs, Location loc)
3228 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
3234 bool DefineMethod (TypeContainer parent, MethodAttributes flags, bool is_add)
3236 Type [] parameter_types = new Type [1];
3237 parameter_types [0] = MemberType;
3239 Parameter [] parms = new Parameter [1];
3240 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
3241 InternalParameters ip = new InternalParameters (
3242 parent, new Parameters (parms, null, Location));
3245 AddBuilder = DefineAccessor (
3246 parent, "add", TypeManager.void_type,
3247 parameter_types, ip, flags);
3249 if (AddBuilder == null)
3252 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3254 RemoveBuilder = DefineAccessor (
3255 parent, "remove", TypeManager.void_type,
3256 parameter_types, ip, flags);
3258 if (RemoveBuilder == null)
3261 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
3267 public override bool Define (TypeContainer parent)
3269 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
3271 if (!DoDefine (parent))
3274 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
3275 Report.Error (66, Location, "'" + parent.Name + "." + Name +
3276 "' : event must be of a delegate type");
3281 // Now define the accessors
3283 if (!DefineMethod (parent, flags, true))
3286 if (!DefineMethod (parent, flags, false))
3289 if (!IsExplicitImpl){
3290 EventBuilder = new MyEventBuilder (
3291 parent.TypeBuilder, Name, e_attr, MemberType);
3293 if (Add == null && Remove == null) {
3294 FieldBuilder = parent.TypeBuilder.DefineField (
3295 Name, MemberType, FieldAttributes.FamANDAssem);
3296 TypeManager.RegisterPrivateFieldOfEvent (
3297 (EventInfo) EventBuilder, FieldBuilder);
3298 TypeManager.RegisterFieldBase (FieldBuilder, this);
3301 EventBuilder.SetAddOnMethod (AddBuilder);
3302 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
3304 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
3305 Report.Error (111, Location,
3306 "Class `" + parent.Name +
3307 "' already contains a definition for the event `" +
3316 void EmitDefaultMethod (EmitContext ec, bool is_add)
3318 ILGenerator ig = ec.ig;
3319 MethodInfo method = null;
3322 method = TypeManager.delegate_combine_delegate_delegate;
3324 method = TypeManager.delegate_remove_delegate_delegate;
3326 ig.Emit (OpCodes.Ldarg_0);
3327 ig.Emit (OpCodes.Ldarg_0);
3328 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
3329 ig.Emit (OpCodes.Ldarg_1);
3330 ig.Emit (OpCodes.Call, method);
3331 ig.Emit (OpCodes.Castclass, MemberType);
3332 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
3333 ig.Emit (OpCodes.Ret);
3336 public void Emit (TypeContainer tc)
3341 ig = AddBuilder.GetILGenerator ();
3342 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3345 Attribute.ApplyAttributes (ec, AddBuilder, Add, Add.OptAttributes, Location);
3346 ec.EmitTopBlock (Add.Block, Location);
3348 EmitDefaultMethod (ec, true);
3350 ig = RemoveBuilder.GetILGenerator ();
3351 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
3353 if (Remove != null) {
3354 Attribute.ApplyAttributes (ec, RemoveBuilder, Remove, Remove.OptAttributes, Location);
3355 ec.EmitTopBlock (Remove.Block, Location);
3357 EmitDefaultMethod (ec, false);
3359 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
3360 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
3367 // FIXME: This does not handle:
3369 // int INTERFACENAME [ args ]
3374 // int this [ args ]
3376 public class Indexer : MemberBase {
3378 const int AllowedModifiers =
3381 Modifiers.PROTECTED |
3382 Modifiers.INTERNAL |
3386 Modifiers.OVERRIDE |
3391 public readonly Parameters FormalParameters;
3392 public readonly Accessor Get, Set;
3393 public MethodBuilder GetBuilder;
3394 public MethodBuilder SetBuilder;
3395 public PropertyBuilder PropertyBuilder;
3396 public string IndexerName;
3397 public string InterfaceIndexerName;
3401 public Indexer (Expression type, string int_type, int flags, Parameters parms,
3402 Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
3403 : base (type, flags, AllowedModifiers, "", attrs, loc)
3405 ExplicitInterfaceName = int_type;
3406 FormalParameters = parms;
3411 public override bool Define (TypeContainer parent)
3413 PropertyAttributes prop_attr =
3414 PropertyAttributes.RTSpecialName |
3415 PropertyAttributes.SpecialName;
3417 if (!DoDefine (parent))
3420 Type [] parameters = FormalParameters.GetParameterInfo (parent);
3422 // Check if the and arguments were correct
3423 if ((parameters == null) || !CheckParameters (parent, parameters))
3426 ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
3428 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
3429 if (IndexerName == null)
3430 IndexerName = "Item";
3431 else if (IsExplicitImpl)
3432 Report.Error (592, Location,
3433 "Attribute 'IndexerName' is not valid on this declaration " +
3434 "type. It is valid on `property' declarations only.");
3436 ShortName = IndexerName;
3437 if (IsExplicitImpl) {
3438 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
3439 Name = InterfaceType.FullName + "." + IndexerName;
3441 InterfaceIndexerName = IndexerName;
3446 InternalParameters ip = new InternalParameters (parent, FormalParameters);
3448 GetBuilder = DefineAccessor (
3449 parent, "get", MemberType, parameters, ip, flags);
3451 if (GetBuilder == null)
3456 int top = parameters.Length;
3457 Type [] set_pars = new Type [top + 1];
3458 parameters.CopyTo (set_pars, 0);
3459 set_pars [top] = MemberType;
3461 Parameter [] fixed_parms = FormalParameters.FixedParameters;
3463 if (fixed_parms == null){
3464 throw new Exception ("We currently do not support only array arguments in an indexer");
3465 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3466 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3468 // Here is the problem: the `value' parameter has
3469 // to come *after* the array parameter in the declaration
3471 // X (object [] x, Type value)
3474 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3475 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
3479 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
3482 fixed_parms.CopyTo (tmp, 0);
3483 tmp [fixed_parms.Length] = new Parameter (
3484 Type, "value", Parameter.Modifier.NONE, null);
3486 Parameters set_formal_params = new Parameters (tmp, null, Location);
3488 InternalParameters ip = new InternalParameters (parent, set_formal_params);
3490 SetBuilder = DefineAccessor (
3491 parent, "set", TypeManager.void_type, set_pars, ip, flags);
3493 if (SetBuilder == null)
3498 // Now name the parameters
3500 Parameter [] p = FormalParameters.FixedParameters;
3504 for (i = 0; i < p.Length; ++i) {
3506 GetBuilder.DefineParameter (
3507 i + 1, p [i].Attributes, p [i].Name);
3510 SetBuilder.DefineParameter (
3511 i + 1, p [i].Attributes, p [i].Name);
3515 SetBuilder.DefineParameter (
3516 i + 1, ParameterAttributes.None, "value");
3518 if (i != parameters.Length) {
3519 Parameter array_param = FormalParameters.ArrayParameter;
3520 SetBuilder.DefineParameter (i + 1, array_param.Attributes,
3527 // Define the PropertyBuilder if one of the following conditions are met:
3528 // a) we're not implementing an interface indexer.
3529 // b) the indexer has a different IndexerName and this is no
3530 // explicit interface implementation.
3532 if (!IsImplementing ||
3533 (!IsExplicitImpl && (IndexerName != InterfaceIndexerName))){
3534 PropertyBuilder = parent.TypeBuilder.DefineProperty (
3535 IndexerName, prop_attr, MemberType, parameters);
3537 if (GetBuilder != null)
3538 PropertyBuilder.SetGetMethod (GetBuilder);
3540 if (SetBuilder != null)
3541 PropertyBuilder.SetSetMethod (SetBuilder);
3543 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
3549 public void Emit (TypeContainer tc)
3554 // The PropertyBuilder can be null for explicit implementations, in that
3555 // case, we do not actually emit the ".property", so there is nowhere to
3556 // put the attribute
3558 if (PropertyBuilder != null)
3559 Attribute.ApplyAttributes (
3560 ec, PropertyBuilder, this, OptAttributes, Location);
3562 Attribute.ApplyAttributes (ec, GetBuilder, Get, Get.OptAttributes, Location);
3564 Attribute.ApplyAttributes (ec, SetBuilder, Set, Set.OptAttributes, Location);
3566 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3570 ig = GetBuilder.GetILGenerator ();
3571 ec = new EmitContext (tc, Location, ig, MemberType, ModFlags);
3573 ec.EmitTopBlock (Get.Block, Location);
3577 ig = SetBuilder.GetILGenerator ();
3578 ec = new EmitContext (tc, Location, ig, null, ModFlags);
3580 ec.EmitTopBlock (Set.Block, Location);
3585 public class Operator : MemberCore {
3587 const int AllowedModifiers =
3593 const int RequiredModifiers =
3597 public enum OpType : byte {
3607 // Unary and Binary operators
3630 // Implicit and Explicit
3635 public readonly OpType OperatorType;
3636 public readonly Expression ReturnType;
3637 public readonly Expression FirstArgType, SecondArgType;
3638 public readonly string FirstArgName, SecondArgName;
3639 public readonly Block Block;
3640 public Attributes OptAttributes;
3641 public MethodBuilder OperatorMethodBuilder;
3643 public string MethodName;
3644 public Method OperatorMethod;
3646 public Operator (OpType type, Expression ret_type, int flags,
3647 Expression arg1type, string arg1name,
3648 Expression arg2type, string arg2name,
3649 Block block, Attributes attrs, Location loc)
3652 OperatorType = type;
3653 ReturnType = ret_type;
3654 ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
3655 FirstArgType = arg1type;
3656 FirstArgName = arg1name;
3657 SecondArgType = arg2type;
3658 SecondArgName = arg2name;
3660 OptAttributes = attrs;
3663 string Prototype (TypeContainer parent)
3665 return parent.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
3666 SecondArgType + ")";
3669 public override bool Define (TypeContainer parent)
3672 MethodName = "op_" + OperatorType;
3674 if (SecondArgType != null)
3677 Parameter [] param_list = new Parameter [length];
3679 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
3682 "User defined operators `" +
3683 Prototype (parent) +
3684 "' must be declared static and public");
3688 param_list[0] = new Parameter (FirstArgType, FirstArgName,
3689 Parameter.Modifier.NONE, null);
3690 if (SecondArgType != null)
3691 param_list[1] = new Parameter (SecondArgType, SecondArgName,
3692 Parameter.Modifier.NONE, null);
3694 OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
3695 new Parameters (param_list, null, Location),
3696 OptAttributes, Mono.CSharp.Location.Null);
3698 OperatorMethod.Define (parent);
3700 if (OperatorMethod.MethodBuilder == null)
3703 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
3705 Type [] param_types = OperatorMethod.ParameterTypes (parent);
3706 Type declaring_type = OperatorMethodBuilder.DeclaringType;
3707 Type return_type = OperatorMethod.GetReturnType (parent);
3708 Type first_arg_type = param_types [0];
3710 // Rules for conversion operators
3712 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
3713 if (first_arg_type == return_type && first_arg_type == declaring_type){
3716 "User-defined conversion cannot take an object of the " +
3717 "enclosing type and convert to an object of the enclosing" +
3722 if (first_arg_type != declaring_type && return_type != declaring_type){
3725 "User-defined conversion must convert to or from the " +
3730 if (first_arg_type == TypeManager.object_type ||
3731 return_type == TypeManager.object_type){
3734 "User-defined conversion cannot convert to or from " +
3739 if (first_arg_type.IsInterface || return_type.IsInterface){
3742 "User-defined conversion cannot convert to or from an " +
3747 if (first_arg_type.IsSubclassOf (return_type) ||
3748 return_type.IsSubclassOf (first_arg_type)){
3751 "User-defined conversion cannot convert between types " +
3752 "that derive from each other");
3755 } else if (SecondArgType == null) {
3756 // Checks for Unary operators
3758 if (first_arg_type != declaring_type){
3761 "The parameter of a unary operator must be the " +
3766 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
3767 if (return_type != declaring_type){
3770 "The parameter and return type for ++ and -- " +
3771 "must be the containing type");
3777 if (OperatorType == OpType.True || OperatorType == OpType.False) {
3778 if (return_type != TypeManager.bool_type){
3781 "The return type of operator True or False " +
3788 // Checks for Binary operators
3790 if (first_arg_type != declaring_type &&
3791 param_types [1] != declaring_type){
3794 "One of the parameters of a binary operator must " +
3795 "be the containing type");
3803 public void Emit (TypeContainer parent)
3805 EmitContext ec = new EmitContext (parent, Location, null, null, ModFlags);
3806 Attribute.ApplyAttributes (ec, OperatorMethodBuilder, this, OptAttributes, Location);
3809 // abstract or extern methods have no bodies
3811 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
3814 OperatorMethod.Block = Block;
3815 OperatorMethod.Emit (parent);
3820 // This is used to compare method signatures
3822 struct MethodSignature {
3824 public Type RetType;
3825 public Type [] Parameters;
3828 /// This delegate is used to extract methods which have the
3829 /// same signature as the argument
3831 public static MemberFilter method_signature_filter;
3834 /// This delegate is used to extract inheritable methods which
3835 /// have the same signature as the argument. By inheritable,
3836 /// this means that we have permissions to override the method
3837 /// from the current assembly and class
3839 public static MemberFilter inheritable_method_signature_filter;
3841 static MethodSignature ()
3843 method_signature_filter = new MemberFilter (MemberSignatureCompare);
3844 inheritable_method_signature_filter = new MemberFilter (
3845 InheritableMemberSignatureCompare);
3848 public MethodSignature (string name, Type ret_type, Type [] parameters)
3853 if (parameters == null)
3854 Parameters = TypeManager.NoTypes;
3856 Parameters = parameters;
3859 public override int GetHashCode ()
3861 return Name.GetHashCode ();
3864 public override bool Equals (Object o)
3866 MethodSignature other = (MethodSignature) o;
3868 if (other.Name != Name)
3871 if (other.RetType != RetType)
3874 if (Parameters == null){
3875 if (other.Parameters == null)
3880 if (other.Parameters == null)
3883 int c = Parameters.Length;
3884 if (other.Parameters.Length != c)
3887 for (int i = 0; i < c; i++)
3888 if (other.Parameters [i] != Parameters [i])
3894 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
3898 if (! (m is MethodInfo))
3901 MethodSignature sig = (MethodSignature) filter_criteria;
3903 if (m.Name != sig.Name)
3906 mi = (MethodInfo) m;
3909 // we use sig.RetType == null to mean `do not check the
3910 // method return value.
3912 if (sig.RetType != null)
3913 if (mi.ReturnType != sig.RetType)
3916 Type [] args = TypeManager.GetArgumentTypes (mi);
3917 Type [] sigp = sig.Parameters;
3919 if (args.Length != sigp.Length)
3922 for (int i = args.Length; i > 0; ){
3924 if (args [i] != sigp [i])
3931 // This filter should be used when we are requesting methods that
3932 // we want to override.
3934 // This makes a number of assumptions, for example
3935 // that the methods being extracted are of a parent
3936 // class (this means we know implicitly that we are
3937 // being called to find out about members by a derived
3940 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
3942 if (MemberSignatureCompare (m, filter_criteria)){
3943 MethodInfo mi = (MethodInfo) m;
3944 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
3946 // If only accessible to the current class.
3947 if (prot == MethodAttributes.Private)
3950 // If only accessible to the defining assembly or
3951 if (prot == MethodAttributes.FamANDAssem ||
3952 prot == MethodAttributes.Assembly){
3953 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
3959 // Anything else (FamOrAssembly and Public) is fine